www.pudn.com > EvsCommun.rar > SerialPort.cpp


#include "StdAfx.h" 
#include ".\serialport.h" 
#include  
 
CSerialPort::CSerialPort(void) 
: m_bOpen(false) 
{ 
	::ZeroMemory(&m_Dcb,sizeof(m_Dcb)); 
	m_Dcb.DCBlength = sizeof(m_Dcb); 
	m_hCommu = INVALID_HANDLE_VALUE; 
	m_nBufferIn = m_nBufferOut = 512; 
	::ZeroMemory(&m_nTimeOut,sizeof(m_nTimeOut)); 
	m_nTimeOut.ReadIntervalTimeout = 100; 
	m_nTimeOut.ReadTotalTimeoutMultiplier = 150; 
	m_nTimeOut.WriteTotalTimeoutConstant = 1000; 
	m_nTimeOut.WriteTotalTimeoutMultiplier = 1000; 
	m_nTimeOut.WriteTotalTimeoutConstant = 1000; 
	::ZeroMemory(&m_OvlpWrite,sizeof(m_OvlpWrite)); 
	m_OvlpWrite.hEvent = CreateEvent(NULL, true, false, NULL); 
	assert(m_OvlpWrite.hEvent != INVALID_HANDLE_VALUE); 
	::ZeroMemory(&m_OvlpRead,sizeof(m_OvlpRead)); 
	m_OvlpRead.hEvent = CreateEvent(NULL,true,false,NULL); 
} 
 
CSerialPort::~CSerialPort(void) 
{ 
	if(m_bOpen) Close(); 
} 
 
void CSerialPort::Init(void) 
{ 
	 
} 
 
void CSerialPort::Close(void) 
{ 
	if(m_bOpen) 
		::CloseHandle(m_hCommu); 
	m_bOpen = false; 
	m_hCommu = INVALID_HANDLE_VALUE; 
	::ResetEvent(m_OvlpWrite.hEvent); 
	::CloseHandle(m_OvlpWrite.hEvent); 
	::ResetEvent(m_OvlpRead.hEvent); 
	::CloseHandle(m_OvlpRead.hEvent); 
} 
 
bool CSerialPort::Open(UINT nPort,DWORD BaudRate,  
					   BYTE ByteSize,BYTE Parity, BYTE StopBits) 
{ 
	m_nPort = nPort; 
	if(m_bOpen) Close(); 
	char com_str[10]; 
	strcpy(com_str, "COM"); 
	ltoa(m_nPort, com_str + 3, 10); 
	m_hCommu = CreateFile( 
		com_str, 
		GENERIC_READ | GENERIC_WRITE, 
		0, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,	//重叠I/O 
		NULL 
		); 
	if(m_hCommu == INVALID_HANDLE_VALUE) return false; 
	BOOL tempBit; 
	//---------------------------------------------------------------------- 
	//设置缓冲区 
	tempBit = SetupComm(m_hCommu,m_nBufferIn,m_nBufferOut); 
	if(!tempBit) return false; 
	//----------------------------------------------------------------------- 
	//设置串口参数:波特率,数据位......等等 
	tempBit = GetCommState(m_hCommu,&m_Dcb); 
	if(!tempBit) return false; 
	m_Dcb.BaudRate = BaudRate; 
	m_Dcb.ByteSize = ByteSize; 
	m_Dcb.Parity = NOPARITY;//MODBUS的特殊需要 
	m_Dcb.StopBits = StopBits; 
	tempBit = SetCommState(m_hCommu,&m_Dcb); 
	if(!tempBit) return false; 
	//------------------------------------------------------------------------------ 
	//设置超时时间 
	tempBit = SetCommTimeouts(m_hCommu, &m_nTimeOut); 
	if(!tempBit) return false; 
	//-------------------------------------------------------------------------------- 
	//清空串口缓冲区 
	tempBit = PurgeComm(m_hCommu,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); 
	if(!tempBit) return false; 
	//----------------------------------------------------------------------------------- 
	m_bOpen = true; 
	return true; 
} 
//用于多机通信 
bool CSerialPort::SetParityBit(BYTE nParity) 
{ 
	m_Dcb.Parity = nParity; 
	if(SetCommState(m_hCommu,&m_Dcb)) return true; 
	return false; 
} 
//在开串口之前调用有效 
void CSerialPort::InitBufferSize(UINT nBufferIn, UINT nBufferOut) 
{ 
	m_nBufferIn = nBufferIn; 
	m_nBufferOut = nBufferOut; 
} 
//异步写数据 
bool CSerialPort::WriteData(BYTE* pWriteBuff, WORD nWrite) 
{ 
	if(!m_bOpen) return false; 
	assert(pWriteBuff); 
	m_OvlpWrite.Offset = 0; 
	m_OvlpWrite.OffsetHigh = 0; 
	DWORD dwError; 
	COMSTAT state; 
	::ClearCommError(m_hCommu,&dwError,&state);//清除错误标志 
	PurgeComm(m_hCommu, PURGE_TXABORT | PURGE_TXCLEAR 
						|PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区和终止发送与接收	 
	DWORD nRealWrite = 0; 
	BOOL bResult; 
	bool bWrite = true; 
	bResult = WriteFile(m_hCommu,pWriteBuff,nWrite,&nRealWrite,&m_OvlpWrite);//异步写 
	if(!bResult) 
	{ 
		dwError = ::GetLastError(); 
		switch(dwError) 
		{ 
			case ERROR_IO_PENDING: 
			{ 
				bWrite = false; 
				break; 
			} 
			default:return false; 
		} 
	} 
	if(!bWrite) 
	{ 
		bResult = ::GetOverlappedResult(m_hCommu,&m_OvlpWrite,&nRealWrite,true); 
		if(!bResult) return false; 
		bWrite = true; 
	} 
	return true; 
} 
//异步读数据 
DWORD CSerialPort::ReadData(BYTE* pReadBuff, WORD nRead) 
{ 
	COMSTAT state; 
	BOOL bResult; 
	DWORD dwError = 0; 
	DWORD nRealRead = 0; 
	bool bRead = true; 
	::ClearCommError(m_hCommu,&dwError,&state); 
	bResult = ::ReadFile(m_hCommu,pReadBuff,nRead,&nRealRead,&m_OvlpRead); 
	if(!bResult) 
	{ 
		dwError = ::GetLastError(); 
		switch(dwError) 
		{ 
			case ERROR_IO_PENDING: 
			{ 
				bRead = false; 
				break; 
			} 
			default:return false; 
		} 
	} 
	if(!bRead) 
	{ 
		bResult = ::GetOverlappedResult(m_hCommu,&m_OvlpRead,&nRealRead,true); 
		if(!bResult) return false; 
		bRead = true; 
	} 
	return nRealRead; 
}