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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

位掩码(bitmask)在windows 串口事件驱动中的应用

發布時間:2025/3/12 windows 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 位掩码(bitmask)在windows 串口事件驱动中的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在學習Windows串口通信,以事件驅動模式開發相關應用時,肯定會用到以下幾個函數:

SetCommMask(HANDLE hComm, DWORD dwEvtMask);

GetCommMask(HANDLE hComm, LPDWORD lpEvtMask);

WaitCommEvent(HANDLE hComm, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);

這幾個函數的使用我就不再廢話了,大家查MSDN就OK了。 我要說的重點是這幾個函數應用了位掩碼的方法來進行條件分支處理,非常自然,高效。無論對人 還是 對于機器來講,都很優美。 非常值得我們在自己的工程實踐中靈活運用。

其中的核心參數--需要捕獲的事件代碼,我們稱其為“事件掩碼”,用變量 dwEvtMask表示, 定義為16位長度,其可選值如下表所列。

英文單詞或縮寫的標識符常量,非常方便程序員理解,而其一一對應的十六進制常量值也早已在系統里預定義好了,各位直接使用意義直觀的字符串常量就OK了。


ValueMeaning

EV_BREAK
0x0040

A break was detected on input.

EV_CTS
0x0008

The CTS (clear-to-send) signal changed state.

EV_DSR
0x0010

The DSR (data-set-ready) signal changed state.

EV_ERR
0x0080

A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.

EV_RING
0x0100

A ring indicator was detected.

EV_RLSD
0x0020

The RLSD (receive-line-signal-detect) signal changed state.

EV_RXCHAR
0x0001

A character was received and placed in the input buffer.

EV_RXFLAG
0x0002

The event character was received and placed in the input buffer. The event character is specified in the device'sDCB structure, which is applied to a serial port by using theSetCommState function.

EV_TXEMPTY
0x0004

The last character in the output buffer was sent.

?

這個被定義為16位長度的事件掩碼變量,是我們這里要討論的主角。 在我理解了Windows 在這里使用位掩碼的機制之后,我建議你可以把它想象成一個由16盞信號燈排成一排所構成的一個信號燈箱,每盞燈只有開和關兩種狀態。

接下來我們再來看事件列表里的事件代碼的Value,就是那個 0x開頭的十六進制數,我們將它以二進制完全展開,如下所示:

事件代碼二進制表示

EV_BREAK
0x0040

0000 0000 0100 0000

EV_CTS
0x0008

0000 0000 0000 1000

EV_DSR
0x0010

0000 0000 0001 0000

EV_ERR
0x0080

0000 0000 1000 0000

EV_RING
0x0100

0000 0001 0000 0000

EV_RLSD
0x0020

0000 0000 0010 0000

EV_RXCHAR
0x0001

0000 0000 0000 0001

EV_RXFLAG
0x0002

0000 0000 0000 0010

EV_TXEMPTY
0x0004

0000 0000 0000 0100


秘密就在這里了。你有沒有發現所有事件掩碼值,要么是“1”,要么是2的正整數次冪,這樣設計的結果就是,任何一個事件的掩碼值的二進制表示里,“1”只出現一次,而所有九個事件的掩碼值的二進制表示,同一位的縱向每一列里,“1”最多只出現一次!

現在我們對全部事件的二進制碼進行位操作求 “|”,這有沒有讓你想到點什么?沒錯,就是當初我們設置要關注事件時,如果有兩個或兩個以上事件需要關注時,事件代碼之間用的就是 "|"?操作。”|“ 操作之后,我們得到 “0000 0001 1111 1111”。這里一共九個”1“,而事件也正好是九個,不同位置上的”1“ 對應著不同的事件,這就是位掩碼的意義所在。

/*小隱喻:剛才我說可以把事件掩碼變量 dwEvtMask 想象成由十六個信號燈排成一排所組成的信號燈箱,我們每關注一個事件,就相當于接通對應信號燈的線路,但僅僅只是接通線路,還沒有拉閘通電,當我們關注的事件真的發生了,那對應信號燈就會拉閘通電了。*/

接下來我們回到代碼層面,在設置事件掩碼時,如果我只關注一個事件,比如我只關注 “輸入緩沖區收到了一個字符” 這么一個事件,那么

?SetCommMask( hCom1, EV_RXCHAR);???? //此時事件掩碼變量 dwEvtMask 的值實際上是”0“ ,但相應位置上的信號燈的線路已經接通,我們就用 ”0000 0000 0000 000?“ 來表示這種狀態

如果我要關注兩個事件,比如:

?SetCommMask( hCom1, EV_RXCHAR | EV_ERR);?? //此時事件掩碼變量 dwEvtMask 的值實際上是”0“,但有兩盞信號燈的線路已接通,我們用 ”0000 0000 ?000 000?“來表示

那么三個,四個....哪怕全部九個事件都關注上,也是如此操作,如下:

SetCommMask( hCom1, EV_BREAK |?EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY);

?????????????????????????????????????????????? //此時事件掩碼變量 dwEvtMask 的值仍是”0“,但九盞信號燈的線路都已接通,燈箱的狀態為 ”0000 000? ???? ????“

當然我們也可以設置個燈箱指針,這樣操作起來方便點:

DWORD *lpdwEvtMask = (EV_BREAK |?EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY);

然后,我們啟動監視功能:

?WaitCommEvent(hCom1, lpdwEvtMask, NULL);??? //為聚焦今天的主題,這里暫不討論重疊方式

一旦 事件掩碼 變量里所羅列的事件中有任何一個或兩個/三個...九個 事件發生,則其位掩碼值將被填寫進 dwEvtMask,即相應位被置1 (此動作由系統完成),在我的隱喻里,則是對應的信號燈通電點亮了。? 當然,代碼里是沒有什么信號燈和可見光的(但是有智慧之光,呵呵),還是需要靠代碼來說話。

?SetCommMask( hCom1, EV_RXCHAR | EV_ERR);???? //假設我們現在關注兩個事件

? ...

?if ( WaitCommEvent(hCom1, lpdwEvtMask, NULL)?)??? //如果條件為真,則說明有關注的事件發生了,可能是一個,也可能是兩個關注的事件都發生了,所以需要進一步鑒別

?? {

??? if ( dwEvtMask & EV_RXCHAR?)??????? //如果EV_RXCHAR事件發生了,則dwEvtMask相應位被置”1“,條件運算的結果就是EV_RXCHAR事件的掩碼值,既非零,又明確指出了是哪個事件

?????? {

??????? ...?????? //響應 EV_RXCHAR 事件

??????? }

???? if ( dwEvtMask & EV_ERR?)

???????{

???????? ...????? //響應 EV_ERR 事件

??????? }

??? }

else

? ...??? //處理錯誤


這里的條件判斷,體現出了運用位掩碼的優勢,其通過位運算就完成了事件篩選,代碼閱讀起來清晰易懂,而機器執行起來又絕對的高速度和高效率,所以我說這樣的設計非常優美。

實際上,弄懂了這些之后,我們也完全可以在自己的代碼實踐中靈活運用 位掩碼,從而使代碼簡潔,高效,優美。



延伸閱讀:

http://blog.csdn.net/qsir/article/details/72457305

http://www.cnblogs.com/zyl910/archive/2012/03/12/noifopex1.html



總結

以上是生活随笔為你收集整理的位掩码(bitmask)在windows 串口事件驱动中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

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