简单封装的串口通信类
#include
"
stdafx.h
"
#include " SerialPort.h "
#include " assert.h "
CSerialPort::CSerialPort()
{
memset( & m_OverlappedRead, 0 , sizeof (m_OverlappedRead));
memset( & m_OverlappedWrite, 0 , sizeof (m_OverlappedWrite));
m_bOpened = false ;
m_ReadComThread = NULL;
m_hIDCom = NULL;
m_dwReadLen = 0 ;
}
CSerialPort:: ~ CSerialPort()
{
}
BOOL CSerialPort::OpenPort(UINT nPort, UINT nBaud)
{
ASSERT(nPort > 0 && nPort < 5 );
if (m_bOpened)
return true ;
TCHAR szPort[ 15 ];
TCHAR szComParams[ 50 ];
DCB dcb;
wsprintf(szPort, _T( " COM%d " ), nPort);
m_hIDCom = ::CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE,
0 ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (m_hIDCom == NULL)
return false ;
memset( & m_OverlappedRead, 0 , sizeof (OVERLAPPED));
memset( & m_OverlappedWrite, 0 , sizeof (OVERLAPPED));
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 5000 ;
::SetCommTimeouts(m_hIDCom, & CommTimeOuts);
wsprintf(szComParams, _T( " COM%d:%d,N,8,1 " ), nPort, nBaud);
m_OverlappedRead.Offset = 0 ;
m_OverlappedRead.OffsetHigh = 0 ;
m_OverlappedRead.hEvent = ::CreateEvent(NULL, true , false , NULL);
m_OverlappedWrite.Offset = 0 ;
m_OverlappedWrite.OffsetHigh = 0 ;
m_OverlappedWrite.hEvent = ::CreateEvent(NULL, true , false , NULL);
dcb.DCBlength = sizeof (DCB);
::GetCommState(m_hIDCom, & dcb);
dcb.BaudRate = nBaud;
dcb.ByteSize = 8 ;
dcb.Parity = 0 ;
if ( ! SetCommState(m_hIDCom, & dcb) || ! SetupComm(m_hIDCom, 4096 , 4096 ) ||
m_OverlappedRead.hEvent == NULL || m_OverlappedWrite.hEvent == NULL)
{
DWORD dwError = ::GetLastError();
if (m_OverlappedRead.hEvent != NULL)
::CloseHandle(m_OverlappedRead.hEvent);
if (m_OverlappedWrite.hEvent != NULL)
::CloseHandle(m_OverlappedWrite.hEvent);
::CloseHandle(m_hIDCom);
return false ;
}
::SetCommMask(m_hIDCom, EV_RXCHAR);
::PurgeComm(m_hIDCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
::EscapeCommFunction(m_hIDCom, SETDTR);
m_bOpened = true ;
m_bExitThread = false ;
StartMonitoring();
return m_bOpened;
}
BOOL CSerialPort::Close()
{
if ( ! m_bOpened || m_hIDCom == NULL)
return true ;
m_bExitThread = true ;
::SetCommMask(m_hIDCom, 0 );
StopMonitoring();
if (m_OverlappedRead.hEvent != NULL)
::CloseHandle(m_OverlappedRead.hEvent);
if (m_OverlappedWrite.hEvent != NULL)
::CloseHandle(m_OverlappedWrite.hEvent);
::CloseHandle(m_hIDCom);
m_bOpened = false ;
m_hIDCom = NULL;
return true ;
}
// 向串口写数据
void CSerialPort::WriteToPort(BYTE * Byte, int Len)
{
if ( ! m_bOpened || m_hIDCom == NULL)
return ;
BOOL bWriteStat;
DWORD dwBytesWritten;
ClearReadBuf();
bWriteStat = ::WriteFile(m_hIDCom, Byte, Len, & dwBytesWritten, & m_OverlappedWrite);
if ( ! bWriteStat && (::GetLastError() == ERROR_IO_PENDING))
{
// WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就
// 返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
// 否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。
DWORD dw = ::WaitForSingleObject(m_OverlappedWrite.hEvent, INFINITE );
if (dw == WAIT_TIMEOUT)
{
dwBytesWritten = 0 ;
DCB dcb;
::GetCommState(m_hIDCom, & dcb);
::PurgeComm(m_hIDCom, PURGE_TXCLEAR);
return ;
}
else
{
::GetOverlappedResult(m_hIDCom, & m_OverlappedWrite, & dwBytesWritten, false ); // 等待服务器完成IO操作
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return ;
}
// 从串口读取数据
int CSerialPort::ReadFromPort(BYTE * lpszBlock, int nRLen)
{
if ( ! m_bOpened || m_hIDCom == NULL)
return 0 ;
BOOL bReadStat;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
::ClearCommError(m_hIDCom, & dwErrorFlags, & ComStat);
if ( ! ComStat.cbInQue)
return 0 ;
dwBytesRead = (DWORD) ComStat.cbInQue;
if (nRLen < ( int )dwBytesRead)
dwBytesRead = (DWORD) nRLen;
bReadStat = ::ReadFile(m_hIDCom, lpszBlock, dwBytesRead, & dwBytesRead, & m_OverlappedRead);
if ( ! bReadStat)
{
if (::GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(m_OverlappedRead.hEvent, INFINITE);
return ( int )dwBytesRead;
}
return 0 ;
}
return ( int )dwBytesRead;
}
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort * pSerialPort = (CSerialPort * )pParam;
BYTE Buffer[ 4096 ];
DWORD dwEvent, dwError;
COMSTAT ComStat;
int ReadLen = 0 ;
memset(pSerialPort -> m_ReadBuf, ' \0 ' , sizeof (pSerialPort -> m_ReadBuf));
::SetCommMask(pSerialPort -> m_hIDCom, EV_RXCHAR);
while ( ! pSerialPort -> m_bExitThread)
{
memset(Buffer, ' \0 ' , 4096 );
::WaitCommEvent(pSerialPort -> m_hIDCom, & dwEvent, NULL);
::ClearCommError(pSerialPort -> m_hIDCom, & dwError, & ComStat);
if ((dwEvent & EV_RXCHAR) && ComStat.cbInQue)
{
pSerialPort -> m_dwReadLen = pSerialPort -> ReadFromPort(Buffer, 4096 );
pSerialPort -> m_dwReadLen = ReadLen > 4096 ? 4096 : ReadLen;
if (pSerialPort -> m_dwReadLen > 0 )
{
memcpy(pSerialPort -> m_ReadBuf, Buffer,pSerialPort -> m_dwReadLen);
}
}
::PurgeComm(pSerialPort -> m_hIDCom, PURGE_RXCLEAR);
}
return 0 ;
}
BOOL CSerialPort::StartMonitoring()
{
if (m_ReadComThread == NULL)
{
if ( ! (m_ReadComThread = ::AfxBeginThread(CommThread, this )))
return false ;
}
return true ;
}
BOOL CSerialPort::StopMonitoring()
{
if (m_ReadComThread != NULL)
{
::TerminateThread(m_ReadComThread -> m_hThread, 0 ); // 终结线程
m_ReadComThread = NULL;
}
return true ;
}
void CSerialPort::ClearReadBuf()
{
memset(m_ReadBuf, ' \0 ' , sizeof (m_ReadBuf));
m_dwReadLen = 0 ;
}
#include " SerialPort.h "
#include " assert.h "
CSerialPort::CSerialPort()
{
memset( & m_OverlappedRead, 0 , sizeof (m_OverlappedRead));
memset( & m_OverlappedWrite, 0 , sizeof (m_OverlappedWrite));
m_bOpened = false ;
m_ReadComThread = NULL;
m_hIDCom = NULL;
m_dwReadLen = 0 ;
}
CSerialPort:: ~ CSerialPort()
{
}
BOOL CSerialPort::OpenPort(UINT nPort, UINT nBaud)
{
ASSERT(nPort > 0 && nPort < 5 );
if (m_bOpened)
return true ;
TCHAR szPort[ 15 ];
TCHAR szComParams[ 50 ];
DCB dcb;
wsprintf(szPort, _T( " COM%d " ), nPort);
m_hIDCom = ::CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE,
0 ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (m_hIDCom == NULL)
return false ;
memset( & m_OverlappedRead, 0 , sizeof (OVERLAPPED));
memset( & m_OverlappedWrite, 0 , sizeof (OVERLAPPED));
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 5000 ;
::SetCommTimeouts(m_hIDCom, & CommTimeOuts);
wsprintf(szComParams, _T( " COM%d:%d,N,8,1 " ), nPort, nBaud);
m_OverlappedRead.Offset = 0 ;
m_OverlappedRead.OffsetHigh = 0 ;
m_OverlappedRead.hEvent = ::CreateEvent(NULL, true , false , NULL);
m_OverlappedWrite.Offset = 0 ;
m_OverlappedWrite.OffsetHigh = 0 ;
m_OverlappedWrite.hEvent = ::CreateEvent(NULL, true , false , NULL);
dcb.DCBlength = sizeof (DCB);
::GetCommState(m_hIDCom, & dcb);
dcb.BaudRate = nBaud;
dcb.ByteSize = 8 ;
dcb.Parity = 0 ;
if ( ! SetCommState(m_hIDCom, & dcb) || ! SetupComm(m_hIDCom, 4096 , 4096 ) ||
m_OverlappedRead.hEvent == NULL || m_OverlappedWrite.hEvent == NULL)
{
DWORD dwError = ::GetLastError();
if (m_OverlappedRead.hEvent != NULL)
::CloseHandle(m_OverlappedRead.hEvent);
if (m_OverlappedWrite.hEvent != NULL)
::CloseHandle(m_OverlappedWrite.hEvent);
::CloseHandle(m_hIDCom);
return false ;
}
::SetCommMask(m_hIDCom, EV_RXCHAR);
::PurgeComm(m_hIDCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
::EscapeCommFunction(m_hIDCom, SETDTR);
m_bOpened = true ;
m_bExitThread = false ;
StartMonitoring();
return m_bOpened;
}
BOOL CSerialPort::Close()
{
if ( ! m_bOpened || m_hIDCom == NULL)
return true ;
m_bExitThread = true ;
::SetCommMask(m_hIDCom, 0 );
StopMonitoring();
if (m_OverlappedRead.hEvent != NULL)
::CloseHandle(m_OverlappedRead.hEvent);
if (m_OverlappedWrite.hEvent != NULL)
::CloseHandle(m_OverlappedWrite.hEvent);
::CloseHandle(m_hIDCom);
m_bOpened = false ;
m_hIDCom = NULL;
return true ;
}
// 向串口写数据
void CSerialPort::WriteToPort(BYTE * Byte, int Len)
{
if ( ! m_bOpened || m_hIDCom == NULL)
return ;
BOOL bWriteStat;
DWORD dwBytesWritten;
ClearReadBuf();
bWriteStat = ::WriteFile(m_hIDCom, Byte, Len, & dwBytesWritten, & m_OverlappedWrite);
if ( ! bWriteStat && (::GetLastError() == ERROR_IO_PENDING))
{
// WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就
// 返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
// 否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。
DWORD dw = ::WaitForSingleObject(m_OverlappedWrite.hEvent, INFINITE );
if (dw == WAIT_TIMEOUT)
{
dwBytesWritten = 0 ;
DCB dcb;
::GetCommState(m_hIDCom, & dcb);
::PurgeComm(m_hIDCom, PURGE_TXCLEAR);
return ;
}
else
{
::GetOverlappedResult(m_hIDCom, & m_OverlappedWrite, & dwBytesWritten, false ); // 等待服务器完成IO操作
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return ;
}
// 从串口读取数据
int CSerialPort::ReadFromPort(BYTE * lpszBlock, int nRLen)
{
if ( ! m_bOpened || m_hIDCom == NULL)
return 0 ;
BOOL bReadStat;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
::ClearCommError(m_hIDCom, & dwErrorFlags, & ComStat);
if ( ! ComStat.cbInQue)
return 0 ;
dwBytesRead = (DWORD) ComStat.cbInQue;
if (nRLen < ( int )dwBytesRead)
dwBytesRead = (DWORD) nRLen;
bReadStat = ::ReadFile(m_hIDCom, lpszBlock, dwBytesRead, & dwBytesRead, & m_OverlappedRead);
if ( ! bReadStat)
{
if (::GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(m_OverlappedRead.hEvent, INFINITE);
return ( int )dwBytesRead;
}
return 0 ;
}
return ( int )dwBytesRead;
}
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort * pSerialPort = (CSerialPort * )pParam;
BYTE Buffer[ 4096 ];
DWORD dwEvent, dwError;
COMSTAT ComStat;
int ReadLen = 0 ;
memset(pSerialPort -> m_ReadBuf, ' \0 ' , sizeof (pSerialPort -> m_ReadBuf));
::SetCommMask(pSerialPort -> m_hIDCom, EV_RXCHAR);
while ( ! pSerialPort -> m_bExitThread)
{
memset(Buffer, ' \0 ' , 4096 );
::WaitCommEvent(pSerialPort -> m_hIDCom, & dwEvent, NULL);
::ClearCommError(pSerialPort -> m_hIDCom, & dwError, & ComStat);
if ((dwEvent & EV_RXCHAR) && ComStat.cbInQue)
{
pSerialPort -> m_dwReadLen = pSerialPort -> ReadFromPort(Buffer, 4096 );
pSerialPort -> m_dwReadLen = ReadLen > 4096 ? 4096 : ReadLen;
if (pSerialPort -> m_dwReadLen > 0 )
{
memcpy(pSerialPort -> m_ReadBuf, Buffer,pSerialPort -> m_dwReadLen);
}
}
::PurgeComm(pSerialPort -> m_hIDCom, PURGE_RXCLEAR);
}
return 0 ;
}
BOOL CSerialPort::StartMonitoring()
{
if (m_ReadComThread == NULL)
{
if ( ! (m_ReadComThread = ::AfxBeginThread(CommThread, this )))
return false ;
}
return true ;
}
BOOL CSerialPort::StopMonitoring()
{
if (m_ReadComThread != NULL)
{
::TerminateThread(m_ReadComThread -> m_hThread, 0 ); // 终结线程
m_ReadComThread = NULL;
}
return true ;
}
void CSerialPort::ClearReadBuf()
{
memset(m_ReadBuf, ' \0 ' , sizeof (m_ReadBuf));
m_dwReadLen = 0 ;
}