Windows中C++写的串口操作类,用CreateFile打开串口:
HANDLE hSerialPort = ::CreateFile ( szPortName, GENERIC_READ| GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
设置参数:
DCB dcb={0}; if(::GetCommState(hSerialPort, &dcb)) { dcb.BaudRate = wBaundRate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; bRet = ::SetCommState(hSerialPort, &dcb); }
设置超时:
if(::SetupComm(hSerialPort, CT_READ_CACHE, CT_WRITE_CACHE)) { // COMMTIMEOUTS cto={0}; cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutConstant = 0; cto.ReadTotalTimeoutMultiplier = 3000; cto.WriteTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; bRet = ::SetCommTimeouts(hSerialPort, &cto); }
清空串口并开启读取线程:
if(bRet&&::PurgeComm(hSerialPort,PURGE_TXCLEAR|PURGE_RXCLEAR)) { if(NULL == m_pbBuffer) { m_cbBuffer = CT_READ_CACHE; bRet = (NULL!=(m_pbBuffer=(LPBYTE)::malloc(m_cbBuffer*sizeof(BYTE)))); } if(bRet) { m_bStarted = TRUE; bRet = (INVALID_HANDLE_VALUE!=(m_hReadThread = ::CreateThread(NULL, 0, LPTHREAD_START_ROUTINE (_SerialPortProc), this, 0, NULL))); } }
读取线程:
DWORD SerialPortHelper::SerialPortProc ( void ) { DWORD dwError = 0; COMSTAT cs={0}; SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING); DWORD dwCommStatus = 0; while (m_bStarted) { WaitCommEvent(m_hSerialPort, &dwCommStatus, 0); SetCommMask (m_hSerialPort, EV_RXCHAR); if(dwCommStatus & EV_RXCHAR) { if(::ClearCommError(m_hSerialPort, &dwError, &cs)) { if(cs.cbInQue>0) { ReceiveData(cs.cbInQue); } } } } return 0; }
这种情况下,如果调用WriteFile就永远无法返回,WriteFile被挂起了。
实际上原因在于读取线程中,如果串口没有任何数据到达,则串口被WaitCommEvent()挂起,所以无法写入数据,导致WriteFile()函数被挂起。