串口状态:
(1)通信事件:用SetCommMask()函数设置想要得到的通信事件的掩码,再调用WaitCommEvent()函数检测通信事件的发生。可设置的通信事件标志(即SetCommMask()函数所设置的掩码)可以有EV_BREAK、EV_CTS、EV_DSR、 EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。 注意:1对于EV_RING标志的设置,WIN95是不会返回EV_RING事件的,因为WIN95不检测该事件。2设置EV_RXCHAR,可以检测到字符到达,但是在绑定此事件和ReadFile()函数一起读取串口接收数据时,可能会出现错误,造成少读字节数,具体原因查看MSDN帮助。可以采用循环读的办法,另外一个比较好的解决办法是调用ClearCommError()函数,确定在一次读操作中在缓冲区中等待被读的字节数。 (2)错误处理和通信状态:在串口通信中,可能会产生很多的错误,使用ClearCommError()函数可以检测错误并且xx错误条件。 (3)Modem状态:用SetcommMask()可以包含很多事件标志,但是这些事件标志只指示在串口线路上的电压变化情况。而调用 GetCommModemStatus()函数可以获得线路上真正的电压状态。 扩展函数:如果应用程序想用自己的流控,可以使用 EscapeCommFunction()函数设置DTR和RTS线路的电平。 通信超时:在通信中,超时是个很重要的考虑因素,因为如果在数据接收过程中由于某种原因突然中断或停止,如果不采取超时控制机制,将会使得I/O线程被挂起或无限阻塞。串口通信中的超时设置分为两步,首先设置 COMMTIMEOUTS结构的五个变量,然后调用SetcommTimeouts()设置超时值。对于使用异步方式读写的操作,如果操作挂起后,异步成功完成了读写,WaitForSingleObject()或 WaitForMultipleObjects()函数将返回WAIT_OBJECT_0,GetOverlappedResult()返回TRUE。其实还可以用GetCommTimeouts()得到系统初始值。 关闭串口:程序结束或需要释放串口资源时,应该正确关闭串口,关闭串口比较简单,使用API调用CloseHandle()关闭串口的句柄就可以了。 调用方法为:CloseHandle(hComm); 但是值得注意的是在关闭串口之前必须保证读写串口线程已经退出,否则会引起误操作,一般采用的办法是使用事件驱动机制,启动一事件,通知串口读写线程强制退出,在线程退出之前,通知主线程可以关闭串口。 二、实现 一般来说,串口的读写由串口读写线程完成,这样可以避免读写阻塞时主程序死锁。对于全双工的串口读写,应该分别开启读线程和写线程;对于半双工和单工的,建议只需开启一个线程即可。在线程中,按照预定好的通信握手方式,正确检测串口状态,读取发送串口数据。 2.实现细节 在半双工的情况下,首先完成必要的串口配置,成功打开串口、DCB设置、超时设置;然后开启线程,如: CwinThread hSerialThread = (CWinThread*) AfxBeginThread(SerialOperation,hWnd,THREAD_PRIORITY_NORMAL); 其中开启之线程为SerialOperation,优先级为普通。 全双工情况下的串口编程,与单工差不多,区别仅仅在于启动双线程,分别为读线程和写线程,读线程根据不同的事件或消息,通过不断查询串口所收到的有效数据,完成读操作;写线程通过接收主线程的发送数据事件和要发送的数据,向串口发送。 /////////////////////////////////////////////////////////////////////////////////////// 打开端口
|