(配套源碼、軟體、開發闆等資源,可移步部落格同名QQ群/TB店鋪:拿破侖940911)
在Z-Stack協定棧中,對于按鍵的檢測,分為兩種不同的機制,分别稱為“輪詢模式”和“中斷模式”,類比單片機中的按鍵檢測,還是很好了解的。但是相比我們之前所學所用,Z-Stack協定棧中的按鍵檢測實作還是相對要複雜一些的。
本節将分為4點詳細講述Z-Stack協定棧中的按鍵檢測機制:
1、按鍵檢測機制選擇——“輪詢模式”or“中斷模式”
2、輪詢模式
3、中斷模式
4、HalKeyInit( )
實際運作過程中,按鍵檢測到底工作在哪種模式,由InitBoard( )函數中下面這句代碼決定:
HalKeyConfig( )函數中的第一個參數,若是HAL_KEY_INTERRUPT_DISABLE,則是選擇“輪詢模式”;若是HAL_KEY_INTERRUPT_ENABLE,則是選擇“中斷模式”;由上述代碼可見,Z-Stack協定棧中預設使用的是“輪詢模式”。具體是如何實作的,詳見HalKeyConfig( )函數中的實作代碼,該函數主要功能如下:
(1)指定按鍵回調函數為OnBoard_KeyCallback( ):
(2)如果要“使能中斷”,則進行相應的中斷配置(如配置觸發邊沿、清除中斷标志位等):
(3)如果不“使能中斷”,則向硬體抽象層任務(Hal_TaskID)發送按鍵查詢事件(HAL_KEY_EVENT),觸發一次按鍵查詢:
(1)上面已經提及,Z-Stack協定棧中預設使用的就是“輪詢模式”,第一次觸發硬體抽象層任務(Hal_TaskID)中的按鍵查詢事件(HAL_KEY_EVENT)後,随即也就觸發了間隔為100ms(1秒10次)的定時按鍵檢測(循環調用HalKeyPoll( )),故稱為“輪詢模式”:
(2)在HalKeyPoll( )函數中,對各個定義的按鍵狀态做完檢測之後,即調用前面指定的按鍵回調函數OnBoard_KeyCallback( ),對鍵值做進一步處理:
OnBoard_KeyCallback( )函數的代碼如下,可見其中又進一步調用了OnBoard_SendKeys( ):
在OnBoard_SendKeys( )函數中,最終将鍵值(keys)封裝成了一個keyChange_t類型的資料包,發送至了registeredKeysTaskID任務:
至于registeredKeysTaskID,其實就是在RegisterForKeys( )函數中被指派指定的:
而調用RegisterForKeys( )函數,則是在我們的應用層任務ProjectApp中,也就是所謂的“注冊按鍵”:
(3)緊接着,我們的應用層任務ProjectApp就會收到鍵值所在的資料包,具體處理鍵值的代碼如下:
具體ProjectApp_HandleKeys( )這個鍵值處理函數實作什麼功能,就完全取決于大家自己啦~
(1)在InitBoard( )函數中調用HalKeyConfig( )時,若第一個參數填為HAL_KEY_INTERRUPT_ENABLE,則會自動選擇為“中斷模式”;
(2)在“中斷模式”下,一旦按鍵所在IO口産生了外部中斷,程式便會立即響應,調到對應的中斷服務函數中(以P0組IO對應中斷為例):
Z-Stack協定棧中關于P0組的中斷服務函數已經編寫好,我們隻需關心其中的halProcessKeyInterrupt( )函數即可:
在halProcessKeyInterrupt( )函數中,首先對按鍵引發的外部中斷的有效性進行判斷,若有效,便也會如“輪詢模式”下一樣,向硬體抽象層任務(Hal_TaskID)發送按鍵查詢事件(HAL_KEY_EVENT),觸發一次按鍵查詢。不同的是,這裡是延時HAL_KEY_DEBOUNCE_VALUE(25)毫秒之後再執行,這裡的延時可以起到“消抖”的功能!
(3)延時HAL_KEY_DEBOUNCE_VALUE毫秒後,程式運作到了硬體抽象層任務(Hal_TaskID)的任務處理函數(Hal_ProcessEvent( ))中的HAL_KEY_EVENT分支,後面的代碼原理就和“輪詢模式”幾乎沒有任何差別了!唯一一點不同是不會像“輪詢模式”下那樣觸發間隔為100ms(1秒10次)的定時按鍵檢測。
不管選擇的是“輪詢模式”還是“中斷模式”,在系統真正開始進行按鍵檢測之前,一定都要對按鍵所在IO當做是普通IO口來進行相關初始化,對應的函數是HalKeyInit( )。