//继续DWORD WINAPI CommWatchProc(LPVOID lpPara)
{
CSerial* pComm =  (CSerial*)lpPara; if(!::SetCommMask(pComm->m_hComDev, EV_RXCHAR | EV_ERR))
return 1;

int d;
COMSTAT Stat;
DWORD dwError;
DWORD dwEvtMask=0 ;

for(DWORD dwLength, dwMask = 0; pComm->m_bOpened && pComm->IsOpen(); dwMask = 0)
{
if(!::WaitCommEvent(pComm->m_hComDev, &dwMask, &pComm->m_WaitOverlapped))
{
if(::GetLastError() == ERROR_IO_PENDING)
{
::GetOverlappedResult(pComm->m_hComDev, &pComm->m_WaitOverlapped, &dwLength, TRUE);
}
}

if(dwMask & EV_ERR) // == EV_ERR
::ClearCommError(pComm->m_hComDev, &dwError, &Stat);

if(dwMask & EV_RXCHAR) // == EV_RXCHAR
{
::ClearCommError(pComm->m_hComDev, &dwError, &Stat);

if(Stat.cbInQue > (pComm->m_nNotifyNum))
{
d = pComm->Read((char*)(pComm->m_OutData), Stat.cbInQue);

if(d >0)
{
::PostMessage(pComm->m_hUIWnd, ON_COM_RECEIVE, WPARAM(pComm->m_nPort), LPARAM(Stat.cbInQue));
}

}


}
}
return 0;
}CSerial::CSerial()
{
// memset(_szCommStr, 0, 20);

memset(&m_ReadOverlapped, 0, sizeof(m_ReadOverlapped));
memset(&m_WriteOverlapped, 0, sizeof(m_WriteOverlapped));
memset(&m_WaitOverlapped, 0, sizeof(m_WaitOverlapped));

m_hComDev = INVALID_HANDLE_VALUE;
m_hWatchThread = INVALID_HANDLE_VALUE;
m_hUIWnd = NULL;
m_bOpened = false;
m_nNotifyNum = 0;}CSerial::~CSerial()
{
Close();}//打开串口,异步通讯
int CSerial::Open( int nPort, int nBaud ,BYTE ByteSize, BYTE Parity , BYTE StopBits)
{
if( m_bOpened ) return( TRUE );
bool ret;
char szPort[15];
DCB dcb;
memset(szPort, 0, sizeof(szPort));
wsprintf( szPort, "COM%d", nPort ); m_nPort = nPort;

m_hComDev = CreateFile( szPort, GENERIC_READ |    GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hComDev == INVALID_HANDLE_VALUE ) return( 1 );
//设定超时结构
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000; SetCommTimeouts( m_hComDev, &CommTimeOuts ); dcb.DCBlength = sizeof( DCB );
GetCommState( m_hComDev, &dcb ); //设定波特率
dcb.BaudRate = nBaud;
//设定无奇偶校验
dcb.Parity = Parity;
//设定数据位为8 
dcb.ByteSize = ByteSize;
//设定一个停止位 
dcb.StopBits=ONESTOPBIT; ret = SetCommState( m_hComDev, &dcb );
if(!ret){

m_nErrId =  GetLastError();
return 2;
}//设置推荐缓冲区
ret = SetupComm( m_hComDev, 2048,2048 );
if(!ret){

m_nErrId =  GetLastError();
return 3;
} //清空串口缓冲区
PurgeComm( m_hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR| PURGE_RXCLEAR ); //清干净输入、输出缓冲区 m_ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
assert(m_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE); 

m_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
assert(m_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);

m_WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
assert(m_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);
if( m_ReadOverlapped.hEvent == NULL ||
        m_WriteOverlapped.hEvent == NULL )
{
DWORD dwError = GetLastError();
if(m_ReadOverlapped.hEvent!= NULL)                                  
CloseHandle( m_ReadOverlapped.hEvent );  if(m_WriteOverlapped.hEvent!= NULL)     
CloseHandle( m_WriteOverlapped.hEvent );
CloseHandle( m_hComDev );

m_nErrId =  GetLastError();
return 4;
}
// unsigned long  i;
// GetCommConfig(m_hComDev, &m_CommConfig, &i);
//
// m_CommConfig.dwProviderSubType = PST_RS422;
// SetCommConfig(m_hComDev, &m_CommConfig, sizeof(COMMCONFIG));
// GetCommConfig(m_hComDev, &m_CommConfig, &i); DWORD   dw;
m_hWatchThread = CreateThread(NULL, 0, CommWatchProc, this, 0, &dw);
if(!m_hWatchThread)  return 5;

m_bOpened = TRUE;
return 0;
}bool CSerial::IsOpen()
{ return m_hComDev != INVALID_HANDLE_VALUE;;
}//写串口 szBuffer
DWORD CSerial::Write(char *szBuffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0;

DWORD dwError; if(::ClearCommError(m_hComDev, &dwError, NULL) && dwError > 0) //清除错误
::PurgeComm(m_hComDev, PURGE_TXABORT | PURGE_TXCLEAR); unsigned long uWriteLength = 0; if(!::WriteFile(m_hComDev, szBuffer, dwBufferLength, &uWriteLength, &m_WriteOverlapped))
if(::GetLastError() != ERROR_IO_PENDING)
uWriteLength = 0; return uWriteLength;
} //读取串口 dwBufferLength  个字符到 szBuffer 返回实际读到的字符数
DWORD CSerial::Read(char *szBuffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0;

// szBuffer[0] = '\0';

COMSTAT  Stat;
DWORD dwError;

if(::ClearCommError(m_hComDev, &dwError, &Stat) && dwError > 0) //清除错误
{
::PurgeComm(m_hComDev, PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/
return 0;
}

if(!Stat.cbInQue)// 缓冲区无数据
return 0;

unsigned long uReadLength = 0;

/// dwBufferLength = dwBufferLength - 1 > Stat.cbInQue ? Stat.cbInQue : dwBufferLength - 1;
dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength ;
if(!::ReadFile(m_hComDev, szBuffer, dwBufferLength, &uReadLength, &m_ReadOverlapped)) //2000 下 ReadFile 始终返回 True
{
if(::GetLastError() == ERROR_IO_PENDING) // 结束异步I/O
{

if(!::GetOverlappedResult(m_hComDev, &m_ReadOverlapped, &uReadLength, false))
{
if(::GetLastError() != ERROR_IO_INCOMPLETE)//其他错误
uReadLength = 0;
WaitForSingleObject(m_ReadOverlapped.hEvent, 20); //等待20ms
}
}
else
uReadLength = 0;
}


// szBuffer[uReadLength] = '\0';
return uReadLength;
}
//关闭串口
bool  CSerial::Close()
{
if(IsOpen())
{
if(m_hWatchThread != NULL)
{
m_bOpened = false; ::SetCommMask(m_hComDev, 0);
::SetEvent(m_WaitOverlapped.hEvent);
if(::WaitForSingleObject(m_hWatchThread, 100) != WAIT_OBJECT_0)
if(!::TerminateThread(m_hWatchThread, 0))
{
return false;
}
::CloseHandle(m_hWatchThread);
::ResetEvent(m_WaitOverlapped.hEvent); m_hWatchThread = NULL;

}
::CloseHandle(m_hComDev); m_hComDev = INVALID_HANDLE_VALUE; if(m_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(m_ReadOverlapped.hEvent);

if(m_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(m_WriteOverlapped.hEvent);

if(m_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(m_WaitOverlapped.hEvent); m_hComDev = INVALID_HANDLE_VALUE; return true;
}
}
//送消息的窗口句柄
 void CSerial::SetWnd(HWND hWnd)
{
m_hUIWnd = hWnd;
}void  CSerial::SetNotifyNum(int NotifyNum)
{
m_nNotifyNum = NotifyNum;}