日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Win32 串口编程(二)

發布時間:2025/3/12 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win32 串口编程(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

3 串口狀態

有兩種獲取通信端口狀態的方法。第一種方法是設置事件掩碼,當指定事件發生時應用程序會收到通知。SetCommMask函數用于設置事件掩碼,WaitCommEvent用于等待指定的事件發生。它們與16位Windows中的SetCommEventMaskEnableCommNotification類似,只是它們不發送WM_COMMNOTIFY消息。第二種方法是不時地調用另一些狀態函數來獲取通信端口的狀態。當然,輪詢是低效的,不建議使用。

3.1 通信事件

通信事件在使用通信端口時可能隨時發生。接收通信事件需要兩個步驟:

  • SetCommMask設定需要接收通知的事件
  • WaitCommEvent提交狀態檢查請求,請求可以是重疊的或者非重疊的,與讀寫操作一樣。

下面是使用SetCommMask的示例:

DWORD?dwStoredFlags;
dwStoredFlags?=?EV_BREAK?|?EV_CTS???|?EV_DSR?|?EV_ERR?|?EV_RING?|???????????????
??????????????? EV_RLSD?|?EV_RXCHAR?|?EV_RXFLAG?|?EV_TXEMPTY?;
if?(!SetCommMask(hComm,?dwStoredFlags))???
?? //?error?setting?communications?mask

?

?


下表描述了每種事件類型。

?

事件標志

描述

EV_BREAK

檢測到輸入中的break

EV_CTS

CTS(Clear?To?Send)信號狀態改變。要取得CTS線路狀態,應使用GetCommModemStatus函數。

EV_DSR

DSR(Data?Set?Ready)信號狀態改變。要取得DSR線路狀態,應使用GetCommModemStatus函數。

EV_ERR

某線路狀態錯誤發生。線路狀態錯誤包括CE_FRAME、CE_OVERRUN和CE_RXPARITY。要取得具體錯誤種類,需調用ClearCommError函數。

EV_RING

檢測到振鈴指示

EV_RLSD

RLSD(Receive?Line?Signal?Detect)信號狀態改變。要取得RLSD線路狀態,需調用GetCommModemStatus函數。注意,RLSD通常被稱作CD(carrier?detect)。

EV_RXCHAR

接收到一個字符并且已放入輸入緩沖區。請參考下面的“警告”節對此標志的詳細討論。

EV_RXFLAG

接收到一個事件字符并且已放入輸入緩沖區。事件字符由下文討論的DCB結構EvtChar字段指定。下面的“警告”節也討論了這個標志。

EV_TXEMPTY

輸出緩沖區中最后一個字符被發送到串口設備了。如果使用硬件緩沖區,此標志僅表示所有數據已經發送到硬件了。如果不與設備驅動交互,是無法確定硬件緩沖區空的。

?

指定事件掩碼后,使用WaitCommEvent函數檢測事件發生。如果以非重疊方式打開端口,則WaitCommEvent不需要OVERLAPPED結構體,函數阻塞調用線程直到某事件發生。如果沒有事件發生,調用線程將無限阻塞。

下面的代碼片段展示了如何在以非重疊方式打開的端口上等待EV_RING事件。

???DWORD?dwCommEvent;
???if?(!SetCommMask(hComm,?EV_RING))??????
???????//?Error?setting?communications?mask??????
?????? return?FALSE;
???if?(!WaitCommEvent(hComm,?&dwCommEvent,?NULL))
?????? //?An?error?occurred?waiting?for?the?event.
???????return?FALSE;
?? else
?????? //?Event?has?occurred.
?????? return?TRUE;


?

?

?

?


如果沒有事件發生,上面的代碼將無限阻塞調用線程。解決方法是以重疊方式打開端口,用下面的方式等待狀態事件:

?

?? #define?STATUS_CHECK_TIMEOUT??????500???//?Milliseconds


???DWORD??????dwRes;
???DWORD??????dwCommEvent;
???DWORD??????dwStoredFlags;
???BOOL??????fWaitingOnStat?=?FALSE;
???OVERLAPPED?osStatus?=?{0};
???dwStoredFlags?=?EV_BREAK?|?EV_CTS?|?EV_DSR?|?EV_ERR?|?EV_RING?|\
??????????????????EV_RLSD?|?EV_RXCHAR?|?EV_RXFLAG?|?EV_TXEMPTY?;
???if?(!SetCommMask(comHandle,?dwStoredFlags))
??????//?error?setting?communications?mask;?abort
??????return?0;
???osStatus.hEvent?=?CreateEvent(NULL,?TRUE,?FALSE,?NULL);
???if?(osStatus.hEvent?==?NULL)
??????//?error?creating?event;?abort
??????return?0;
???for?(?;?;?)?{
??????//?Issue?a?status?event?check?if?one?hasn't?been?issued?already.
??????if?(!fWaitingOnStat)?{
?????????if?(!WaitCommEvent(hComm,?&dwCommEvent,?&osStatus))?{
????????????if?(GetLastError()?==?ERROR_IO_PENDING)
???????????????bWaitingOnStatusHandle?=?TRUE;
????????????else
???????????????//?error?in?WaitCommEvent;?abort
???????????????break;
?????????}
?????????else
????????????//?WaitCommEvent?returned?immediately.
????????????//?Deal?with?status?event?as?appropriate.
????????????ReportStatusEvent(dwCommEvent);?
??????}
??????//?Check?on?overlapped?operation.
??????if?(fWaitingOnStat)?{
?????????//?Wait?a?little?while?for?an?event?to?occur.
?????????dwRes?=?WaitForSingleObject(osStatus.hEvent,?STATUS_CHECK_TIMEOUT);
?????????switch(dwRes)
?????????{
?????????????//?Event?occurred.
?????????????case?WAIT_OBJECT_0:?
?????????????????if?(!GetOverlappedResult(hComm,?&osStatus,?&dwOvRes,?FALSE))
????????????????????//?An?error?occurred?in?the?overlapped?operation;
????????????????????//?call?GetLastError?to?find?out?what?it?was
????????????????????//?and?abort?if?it?is?fatal.
?????????????????else
????????????????????//?Status?event?is?stored?in?the?event?flag
????????????????????//?specified?in?the?original?WaitCommEvent?call.
????????????????????//?Deal?with?the?status?event?as?appropriate.
????????????????????ReportStatusEvent(dwCommEvent);
?????????????????//?Set?fWaitingOnStat?flag?to?indicate?that?a?new
?????????????????//?WaitCommEvent?is?to?be?issued.
?????????????????fWaitingOnStat?=?FALSE;
?????????????????break;
?????????????case?WAIT_TIMEOUT:
?????????????????//?Operation?isn't?complete?yet.?fWaitingOnStatusHandle?flag?
?????????????????//?isn't?changed?since?I'll?loop?back?around?and?I?don't?want
?????????????????//?to?issue?another?WaitCommEvent?until?the?first?one?finishes.
?????????????????//
?????????????????//?This?is?a?good?time?to?do?some?background?work.
????????????????DoBackgroundWork();
?????????????????break;???????????????????????
?????????????default:
?????????????????//?Error?in?the?WaitForSingleObject;?abort
?????????????????//?This?indicates?a?problem?with?the?OVERLAPPED?structure's
?????????????????//?event?handle.
????????????????CloseHandle(osStatus.hEvent);
????????????????return?0;
?????????}
??????}
???}
???CloseHandle(osStatus.hEvent);


上面的代碼片段與重疊讀取操作的代碼非常相似。實際上,MTTTY使用WaitForMultipleObjects在同一個線程中等待讀取完成或者狀態改變事件發生。 SetCommMask和WaitCommEvent有兩種很有意思的邊際效應。第一,如果以非重疊方式打開通信端口,WaitCommEvent將阻塞直到某事件發生。如果其他線程調用SetCommMask設置新的事件掩碼,則線程將阻塞在SetCommMask調用上,原因是第一個線程的WaitCommEvent調用仍在執行中。SetCommMask將一直阻塞調用線程,直到第一個線程的WaitCommEvent調用返回。這種邊際效應對于以非重疊方式打開的端口是通用的。如果某線程阻塞在任何通信函數上,則第二個線程對任何通信函數的調用都將阻塞,直到第一個線程的函數調用返回。第二種邊際效應是關于以重疊方式打開的端口的。如果使用SetCommMask設置新的事件掩碼,則未決的WaitCommEvent調用將成功完成,導致調用完成的事件掩碼將是NULL。

?

總結

以上是生活随笔為你收集整理的Win32 串口编程(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。