• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    Z-Stack協(xié)議棧的按鍵驅(qū)動(dòng)機(jī)制分析*

    2018-07-11 07:51:32
    關(guān)鍵詞:輪詢鍵值調(diào)用

    (河南城建學(xué)院 計(jì)算機(jī)與數(shù)據(jù)科學(xué)學(xué)院,平頂山 467036)

    引 言

    當(dāng)前在實(shí)現(xiàn)ZigBee Pro標(biāo)準(zhǔn)組成的WSN無線傳感網(wǎng)技術(shù)方案中,有TI公司的CC2530+Z-Stack方案,也有ST公司的STM32W108+EmberZnet方案。TI公司的CC2530是基于8051內(nèi)核,其Z-Stack協(xié)議棧被廣泛應(yīng)用在ZigBee通信設(shè)備中,研究其工作原理有著重要意義。

    1 Z-Stack協(xié)議棧簡介

    Z-Stack是一款業(yè)界領(lǐng)先的商業(yè)級(jí)協(xié)議棧,它把底層(尤其是MAC層)做成lib庫文件封裝起來(不開源),供其它層調(diào)用[1]。其中,HAL硬件抽象層、MAC層位于最底層,與硬件相關(guān);NWK網(wǎng)絡(luò)層、OSAL操作系統(tǒng)抽象層、APS應(yīng)用支持子層、AF應(yīng)用框架層、ZDO ZigBee設(shè)備對(duì)象以及安全層建立在HAL和MAC層之上,并且完全與硬件無關(guān);整個(gè)協(xié)議棧的最頂層就是用戶的應(yīng)用程序?qū)覣PP。HAL提供各種硬件模塊的驅(qū)動(dòng),包括定時(shí)器Timer、通用I/O口、UART、ADC等應(yīng)用程序接口API,提供各種服務(wù)的擴(kuò)展集。Z-Stack協(xié)議?;谑录?qū)動(dòng)和消息傳遞的機(jī)制,協(xié)議棧中的每一層都設(shè)計(jì)了一個(gè)事件處理函數(shù),用來處理與這一層操作相關(guān)的各種事件,將這些事件處理函數(shù)看成是與協(xié)議棧每一層相對(duì)應(yīng)的任務(wù),由ZigBee協(xié)議棧中OSAL來進(jìn)行調(diào)度管理,這樣不管何時(shí)發(fā)生了何種事件,都可以通過調(diào)度協(xié)議棧相應(yīng)層的事件處理函數(shù)/任務(wù)來進(jìn)行處理[2]。

    圖1示例解釋了Z-Stack協(xié)議棧中main()函數(shù)和osal_run_system()函數(shù)主循環(huán)的執(zhí)行流程。

    圖1 Z-Stack協(xié)議棧整體流程

    2 Z-Stack協(xié)議棧的按鍵定義和配置

    Z-Stack中總共定義了7個(gè)按鍵,其中SW1~SW5屬于Joystick的UP上、RT右、DN下、LT左、PUSH/CENTER中間5個(gè)按鍵,SW6和SW7屬于2個(gè)獨(dú)立的按鍵開關(guān),當(dāng)SW6按下時(shí),相應(yīng)P0.1引腳為低電平,彈起時(shí)靠上拉電阻處于高電平。在Z-Stack源代碼HALinclude目錄下的文件hal_key.h和hal_key.c中有按鍵的定義。Joystick按鍵對(duì)應(yīng)于圖2中的S3按鍵,通過組合邏輯SN74HC32D芯片輸出JOYSTICK_INT信號(hào)給P2.0引腳,通過其電平從低到高的變化來判斷按鍵是否按下;同時(shí)將各個(gè)按鍵按下時(shí)的不同電位通過同相比例放大器輸出按鍵信號(hào)JOYSTICK_ADC輸入給ADC,經(jīng)過ADC轉(zhuǎn)換之后獲取不同的按鍵值,以此判斷Joystick具體是哪個(gè)按鍵按下的動(dòng)作。Joystick按鍵原理圖下半部分如圖3所示。

    圖2 Joystick按鍵原理圖上半部

    圖3 Joystick按鍵原理圖下半部

    Z-Stack源代碼的hal_key.h中定義了按鍵的鍵值,hal_key.c中定義各個(gè)按鍵對(duì)應(yīng)的I/O引腳、終端觸發(fā)的方式、Joystick按鍵對(duì)應(yīng)的ADC通道等相關(guān)寄存器信息。

    根據(jù)Z-Stack協(xié)議棧工作流程,main()函數(shù)調(diào)用HalDriverInit()函數(shù)進(jìn)行硬件驅(qū)動(dòng)的初始化,HalDriverInit()函數(shù)調(diào)用HalKeyInit()進(jìn)行按鍵初始化,其中定義了全局變量HalKeyConfigured,用來作為按鍵是否已配置的標(biāo)志,其初始化為FALSE。

    在main()函數(shù)執(zhí)行第二次InitBoard()函數(shù),也就是板子的最終初始化時(shí),傳入的參數(shù)為OB_READY,因此調(diào)用HalKeyConfig()函數(shù)來進(jìn)行按鍵的配置。

    void InitBoard( uint8 level ){

    if ( level == OB_COLD ){

    ……

    }

    else// !OB_COLD{

    /*調(diào)用HalKeyConfig函數(shù)對(duì)按鍵進(jìn)行配置*/

    HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);

    }

    }

    按鍵配置函數(shù)HalKeyConfig的定義如下:

    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback){

    /*通過傳入的參數(shù)interruptEnable決定是否采用中斷的方式*/

    Hal_KeyIntEnable = interruptEnable;

    /*通過傳入的參數(shù)cback來注冊(cè)按鍵處理回調(diào)函數(shù)指針pHalKeyProcessFunction*/

    pHalKeyProcessFunction = cback;

    /*如果采用按鍵中斷的方式*/

    if (Hal_KeyIntEnable)

    {/*SW_6鍵(P0.1引腳) 上升沿或者下降沿觸發(fā)中斷的配置*/

    ……

    /*Joystick鍵 判斷按鍵是否動(dòng)作(P2.0引腳) 上升沿或者下降沿觸發(fā)中斷的配置*/

    HAL_KEY_JOY_MOVE_ICTL &=~(HAL_KEY_JOY_MOVE_EDGEBIT);

    /* Clear the edge bit */

    ……

    }

    else/*沒有采用中斷方式,也就是按鍵輪詢方式*/

    {/*SW_6鍵禁止中斷*/

    ……

    osal_set_event(Hal_TaskID, HAL_KEY_EVENT);

    /*產(chǎn)生HAL_KEY_EVENT事件*/

    }

    HalKeyConfigured = TRUE;

    /*HalKeyConfigured變量最終配置為TRUE*/

    }

    可以看出,HalKeyConfig函數(shù)針對(duì)按鍵采用輪詢方式或者中斷方式進(jìn)行了兩種配置,并且對(duì)按鍵處理回調(diào)函數(shù)指針pHalKeyProcessFunction進(jìn)行賦值,指定相應(yīng)的回調(diào)處理函數(shù),最終HalKeyConfig全局變量設(shè)置為TRUE,代表按鍵配置完畢。在按鍵輪詢的方式中,調(diào)用了osal_set_event(Hal_TaskID, HAL_KEY_EVENT)函數(shù),產(chǎn)生HAL_KEY_EVENT事件,交給HAL層去處理。

    3 Z-Stack協(xié)議棧的按鍵驅(qū)動(dòng)機(jī)制

    Z-Stack中提供了兩種方式采集按鍵數(shù)據(jù):輪詢方式和中斷方式。

    在輪詢方式中,每隔一定時(shí)間(默認(rèn)周期為100 ms)產(chǎn)生定時(shí)事件HAL_KEY_EVENT,OSAL調(diào)用HAL層的Hal_ProcessEvent()函數(shù)處理該事件,然后調(diào)用HalKeyPoll()函數(shù)來檢測(cè)按鍵狀態(tài),如果按鍵有變化,則交給pHalKeyProcessFunction()回調(diào)函數(shù)進(jìn)行相應(yīng)的處理。

    uint16 Hal_ProcessEvent(uint8 task_id, uint16 events){

    ……

    if (events & HAL_KEY_EVENT){

    #if (defined HAL_KEY) && (HAL_KEY == TRUE)

    HalKeyPoll();/*按鍵檢測(cè)狀態(tài)函數(shù)*/

    /*如果是按鍵輪詢方式,則通過定時(shí)器觸發(fā)HAL_KEY_EVENT事件來進(jìn)行下一輪輪詢*/

    if (!Hal_KeyIntEnable){/*100ms定時(shí)周期發(fā)送HAL_KEY_EVENT事件*/

    osal_start_timerEx(Hal_TaskID,HAL_KEY_EVENT,100);

    }

    #endif // HAL_KEY

    return events ^ HAL_KEY_EVENT;

    }

    ……

    }

    函數(shù)HalKeyPoll()的定義如下:

    void HalKeyPoll (void){

    uint8 keys = 0;/*keys用來儲(chǔ)存鍵值*/

    /*Joystick的P2.0引腳電平是高電平,表明Joystick有按鍵按下*/

    if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT)){

    /*通過halGetJoyKeyInput函數(shù)返回Joystick按鍵鍵值*/

    keys = halGetJoyKeyInput();

    }

    /*如果是按鍵輪詢方式,通過當(dāng)前按鍵狀態(tài)與之前的狀態(tài)進(jìn)行比較來判斷是否有按鍵按下*/

    if (!Hal_KeyIntEnable){

    if (keys == halKeySavedKeys){

    /*如果當(dāng)前按鍵狀態(tài)沒有變化,直接返回退出*/

    return;

    }

    halKeySavedKeys = keys;

    /*存儲(chǔ)當(dāng)前的按鍵值用于下一次的比較*/

    }

    ……

    /*通過P0.1引腳電平的高低來設(shè)置keys鍵值*/

    if (HAL_PUSH_BUTTON1()){/*等價(jià)于if(P0_1) */

    keys |= HAL_KEY_SW_6;

    }

    /*如果有按鍵按下,調(diào)用按鍵的回調(diào)函數(shù)處理按鍵事務(wù)*/

    if (keys && (pHalKeyProcessFunction)){

    (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);

    }

    }

    在中斷方式中,按鍵觸發(fā)按鍵中斷,在按鍵中斷ISR中調(diào)用halProcessKeyInterrupt()函數(shù),其通過延遲定時(shí)25 ms(按鍵消抖)后,產(chǎn)生按鍵HAL_KEY_EVENT事件,交給HAL層的Hal_ProcessEvent()函數(shù)進(jìn)行相應(yīng)處理,后續(xù)流程同輪詢方式。

    4 Joystick按鍵的工作原理

    通過上面的分析,可以看出不論是輪詢方式還是中斷方式,均通過HalKeyPoll()函數(shù)來判定按鍵狀態(tài)的變化,其中Joystick依靠halGetJoyKeyInput()函數(shù)來獲取鍵值。在分析該函數(shù)之前,先來看看Joystick按鍵工作的原理。

    由圖2可知,SN74HC32D是1個(gè)4組2輸入1輸出的或門,由其硬件電路可以推導(dǎo)出組合邏輯表達(dá)式:

    JOYSTICK_INT=3Y=3A+3B=PUSH+4Y=

    PUSH+4A+4B=PUSH+2Y+1Y=

    PUSH+2A+2B+1A+1B=

    PUSH+LT+RT+UP+DN

    這意味著,JOYSTICK_INT(P2.0引腳)是Joystick的SW1~SW5這5個(gè)按鍵狀態(tài)的邏輯或,只要有任意1個(gè)按鍵按下(Joystick按鍵的機(jī)械結(jié)構(gòu)決定了5個(gè)鍵中只能有1個(gè)按下,不可能有多個(gè)按鍵同時(shí)按下),那么P2.0引腳上就是高電平;否則當(dāng)5個(gè)按鍵都不按下,P2.0引腳為低電平;反過來,如果P2.0引腳上是高電平,只知道這5個(gè)鍵中有某個(gè)鍵被按下,但不知道是具體哪一個(gè)。

    具體按鍵的判斷是通過ADC轉(zhuǎn)換器獲取不同鍵值來判定的。當(dāng)UP鍵按下時(shí),圖3可以等效為圖4。

    圖4 UP鍵按下時(shí)的等效電路

    R//=(R16+R27)//(R11+R29+R30)//(R17+R36+R37)=300k//500k//764k=150.55k,由理想運(yùn)放的“虛斷”可知,U1的同相輸入端電位:

    由理想運(yùn)放的“虛短”可知,U1的反向輸入端電位:

    V-=V+=1.03125V

    對(duì)于U1的反向輸入端節(jié)點(diǎn),由基爾霍夫節(jié)點(diǎn)電流定律可知:

    對(duì)于運(yùn)放U2,構(gòu)成了一個(gè)同相比例放大電路,其電壓增益為:

    因此,U2輸出端JOYSTICK_ADC電位是:

    JOYSTICK_ADC=Vout1×Av=

    0.2394V×1.42553=0.3413V

    這表明,當(dāng)UP鍵按下時(shí),通過2個(gè)運(yùn)放放大之后,JOYSTICK_ADC電位是0.341 3 V。

    同理,可以依次計(jì)算,當(dāng)DN、LT、RT、CENTER鍵按下時(shí),不同的JOYSTICK_ADC電位值,由于Z-Stack協(xié)議棧中,對(duì)Joystick按鍵的ADC采用8位有效數(shù)字(最高位0代表正),參考電壓為3.3 V,那么經(jīng)過A/D轉(zhuǎn)換之后的值,如表1所列。

    在之前的按鍵代碼分析中提到,HalKeyPoll()函數(shù)用來判定按鍵狀態(tài)的變化,其中Joystick依靠halGetJoyKeyInput()函數(shù)來獲取鍵值,halGetJoyKeyInput()函數(shù)的代碼如下,可以看到與表1的理論計(jì)算結(jié)果完美對(duì)應(yīng)。

    表1 理論上Joystick按鍵對(duì)應(yīng)的電位值和A/D轉(zhuǎn)換值

    uint8 halGetJoyKeyInput(void){

    ……

    /*讀取Joystick按鍵ADC直到兩次連續(xù)ADC值相同(穩(wěn)定)為止*/

    adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8);//ADC 8位有效數(shù)字

    if ((adc >= 2) && (adc <= 38)){ // UP/13

    ksave0 |= HAL_KEY_UP;

    }

    else if ((adc >= 74) && (adc <= 88)){ // RT/77

    ksave0 |= HAL_KEY_RIGHT;

    }

    else if ((adc >= 60) && (adc <= 73)){// LT/68

    ksave0 |= HAL_KEY_LEFT;

    }

    else if ((adc >= 39) && (adc <= 59)){// DN/49

    ksave0 |= HAL_KEY_DOWN;

    }

    else if ((adc >= 89) && (adc <= 100)){// CENTER/90

    ksave0 |= HAL_KEY_CENTER;

    }

    ……

    }

    5 Z-Stack協(xié)議棧的按鍵事件處理

    在按鍵狀態(tài)檢測(cè)函數(shù)HalKeyPoll()中,如果發(fā)現(xiàn)按鍵狀態(tài)有變化,就會(huì)通過 (pHalKeyProcessFunction) (keys,HAL_KEY_STATE_NORMAL)來實(shí)現(xiàn)對(duì)按鍵事務(wù)回調(diào)函數(shù)OnBoard_KeyCallback()的調(diào)用。OnBoard_KeyCallback()函數(shù)又通過調(diào)用OnBoard_SendKeys(keys,shift),將按鍵值和按鍵狀態(tài)打包成KEY_CHANGE事件,發(fā)送到RegisterForKeys()函數(shù)注冊(cè)層,交給該層進(jìn)行按鍵事務(wù)的處理。

    在TI官方SampleApp項(xiàng)目例程中,SampleApp應(yīng)用層的任務(wù)初始化函數(shù)SampleApp_Init()通過RegisterForKeys(SampleApp_TaskID)把按鍵的最終處理交給應(yīng)用層。一旦有按鍵KEY_CHANGE事件,就會(huì)觸發(fā)應(yīng)用層的事件處理函數(shù)SampleApp_ProcessEvent()來進(jìn)行按鍵處理,如下所示:

    uint16 SampleApp_ProcessEvent(uint8 task_id, uint16 events){

    ……

    switch (MSGpkt->hdr.event){ //判斷消息包頭的事件是否是KEY_CHANGE

    case KEY_CHANGE:

    //應(yīng)用層處理按鍵事務(wù),交給SampleApp_HandleKeys函數(shù),可根據(jù)不同的鍵值做相應(yīng)處理

    SampleApp_HandleKeys(((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys);

    break;

    ……

    }

    ……

    }

    結(jié) 語

    簡單來說,Z-Stack中提供了兩種按鍵機(jī)制:輪詢方式和中斷方式,在HalKeyConfig()函數(shù)中按兩種機(jī)制分別進(jìn)行按鍵配置。兩者均調(diào)用HalKeyPoll()函數(shù)來檢測(cè)按鍵狀態(tài),如果按鍵有變化,則交給回調(diào)函數(shù)處理,同時(shí)回調(diào)函數(shù)會(huì)向RegisterForKeys()函數(shù)注冊(cè)層(一般是應(yīng)用層APP)發(fā)送事件KEY_CHANGE,最終交給該層的事件處理函數(shù)APP_ProcessEvent()集中處理[1,3]。

    需要注意的地方總結(jié)一下:①按鍵默認(rèn)為輪詢的方式,如果想修改按鍵為中斷方式,則需要將OnBoard.c中的函數(shù)void InitBoard()中的語句修改為HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE,OnBoard_KeyCallback);②Joystick通過或門器件實(shí)現(xiàn)了多個(gè)按鍵的按下判斷,并通過獲取ADC按鍵值來判定具體哪個(gè)按鍵被按下,通過這種方式,多按鍵的時(shí)候可以通過ADC外加2個(gè)I/O引腳來實(shí)現(xiàn)多按鍵驅(qū)動(dòng)。

    猜你喜歡
    輪詢鍵值調(diào)用
    非請(qǐng)勿進(jìn) 為注冊(cè)表的重要鍵值上把“鎖”
    核電項(xiàng)目物項(xiàng)調(diào)用管理的應(yīng)用研究
    基于等概率的ASON業(yè)務(wù)授權(quán)設(shè)計(jì)?
    LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
    一鍵直達(dá) Windows 10注冊(cè)表編輯高招
    電腦愛好者(2017年9期)2017-06-01 21:38:08
    基于系統(tǒng)調(diào)用的惡意軟件檢測(cè)技術(shù)研究
    依托站點(diǎn)狀態(tài)的兩級(jí)輪詢控制系統(tǒng)時(shí)延特性分析
    利用時(shí)間輪詢方式操作DDR3實(shí)現(xiàn)多模式下數(shù)據(jù)重排
    利用RFC技術(shù)實(shí)現(xiàn)SAP系統(tǒng)接口通信
    數(shù)據(jù)鏈輪詢多網(wǎng)優(yōu)化設(shè)計(jì)方法研究*
    蓝山县| 阿荣旗| 冀州市| 巴塘县| 尉犁县| 伊宁县| 天全县| 渝北区| 商洛市| 孟津县| 千阳县| 四子王旗| 兴宁市| 湘阴县| 海南省| 邻水| 城固县| 海林市| 塘沽区| 山西省| 南皮县| 彰化市| 嘉义市| 思南县| 白沙| 许昌县| 长葛市| 乐清市| 淳化县| 灵寿县| 镶黄旗| 建水县| 大悟县| 公安县| 苏州市| 枣强县| 沂源县| 延安市| 河源市| 汕头市| 武安市|