简单封装的串口通信类

简单封装的串口通信类

#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 ;
}

你可能感兴趣的:(简单封装的串口通信类)