串口数据接收事件的一点感悟

刚才在看串口数据的接收问题。

这里的话,最开始的时候需要在打开串口后,对串口使用SetCommEvent函数去设置通知事件。

这里又涉及一个问题,就是一般SetCommEvent函数的第二个事件参数为

EV_RXCHAR

第一个参数不用想了,就是文件句柄。

响应这个事件的函数是:

WaitCommEvent

在一个已经完成了的串口类中,也是调用这个函数去响应消息的,而且在后台线程函数中,这个函数同时调用了两个时间等待函数。

第一个等待事件响应的就是这个函数,第二个则是著名的waitmultipleobjects函数。

然后在其代码注释中,那位大神说这个函数在调用之后不会持续等待,而是立刻返回,原因就是这个串口是以异步的方式打开的。

waitcommevent函数的返回值是一个BOOL值,其注释原文如下:

 1 // If WaitCommEvent() returns TRUE, check to be sure there are
 2             // actually bytes in the buffer to read.  
 3             //
 4             // If you are reading more than one byte at a time from the buffer 
 5             // (which this program does not do) you will have the situation occur 
 6             // where the first byte to arrive will cause the WaitForMultipleObjects() 
 7             // function to stop waiting.  The WaitForMultipleObjects() function 
 8             // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
 9             // as it returns.  
10             //
11             // If in the time between the reset of this event and the call to 
12             // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
13             // to the signeled state. When the call to ReadFile() occurs, it will 
14             // read all of the bytes from the buffer, and the program will
15             // loop back around to WaitCommEvent().
16             // 
17             // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
18             // but there are no bytes available to read.  If you proceed and call
19             // ReadFile(), it will return immediatly due to the async port setup, but
20             // GetOverlappedResults() will not return until the next character arrives.
21             //
22             // It is not desirable for the GetOverlappedResults() function to be in 
23             // this state.  The thread shutdown event (event 0) and the WriteFile()
24             // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
25             //
26             // The solution to this is to check the buffer with a call to ClearCommError().
27             // This call will reset the event handle, and if there are no bytes to read
28             // we can loop back through WaitCommEvent() again, then proceed.
29             // If there are really bytes to read, do nothing and proceed.
30         
31             bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
32 
33             if (comstat.cbInQue == 0)
34                 continue;

其意思我大概翻译一下:

如果BResult函数返回值为真,则必须要检测缓冲区中是否有数据。

如果你一次性的从缓冲区中读出多个数据,那么下面的这种情况就会出现:第一个将要到来数据会导致waitmultipleobjects函数停止等待。然后这个函数会在其返回的时候会重置位于OVERLAPPED结构中的事件句柄,将其置为未触发状态。

如果在重置了事件并且调用readfile函数时有更多的数据来临了,OVERLAPPEED结构中的event事件会被再次触发。此时调用readfile函数会把所有的数据全部都读取进来,然后再循环到waitcommevent函数(因为触发了的事件)。

在这个时候你会面临一个问题,就是,数据接收事件已经触发,但是缓冲区内无数据可读。此时运行并调用readfile函数,此函数会立即因为串口是异步的而返回,但是GetOverlappedResult函数并不会返回而是等待下一次字符的到来。

对于GetOverlappedResult函数来说,这个并不是我们想要的结果。如果线程被阻塞在这个函数,那么线程关闭时间和写事件就都无法响应了(当然~)

对这个问题的解决方法是调用ClearCommError函数来检查缓冲区这个函数会重置事件,如果缓冲区中没有数据可读,那么我们就重新到waitcommevent函数去等待(就是跳过waitmultipleobjects函数)

-------------------分割线----------------------------

原文就在那里,我自己翻译的可能会有点问题,但是大致的意思应该是对的。

不过现在还是在奇怪,既然waitcommevent函数不等待,那么如果只检查了一次就跳到waitformultipleobjects函数,那么在这个函数等待的时候,如果来了字符串该怎么办???我还是不很清楚这两个时间是怎么关联起来的。

不过目前看的话,应该是和OVERLAPPED结构有很大的关系。

 

 

 

 

 

posted @ 2013-05-28 18:48  Matrix_R  阅读(14345)  评论(0编辑  收藏  举报