串口數據接收事件的一點感悟


剛才在看串口數據的接收問題。

這里的話,最開始的時候需要在打開串口后,對串口使用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結構有很大的關系。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM