<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                * 導師視頻講解:[**去聽課**](https://www.bilibili.com/video/BV1k34y1D7Vz?p=27) >[success] **技術支持說明:** >**1**.一般以自主學習為主 > **2**.可到官方問答社區中提問:[**去提問**](https://bbs.csdn.net/forums/zigbee) > **3**.工程師**會盡快**解答社區問題,但他們是一線開發,【**難以保證**】解答時效,解答辛苦,感謝理解! <br/> 本節課的內容是后續課程的基礎,希望大家能夠好好學習,為后續課程打下良好的基礎。 <br/> ## **事件的類型與編碼**: 讀者可以發現每個層次的事件處理函數的參數都包含1個task id和1個events參數,例如: * MAC層事件處理函數,如圖所示。 ![](https://img.kancloud.cn/af/53/af535ca140b59c7f9bedb4112e9ce870_1378x691.png =400x) ### * 網絡層事件處理函數,如圖所示。 ![](https://img.kancloud.cn/05/f2/05f2dcc8568d4f756e09d165721b703b_1384x666.png =400x) ### * 應用層事件處理函數,如圖所示。 ![](https://img.kancloud.cn/7f/17/7f17ec477550183a9ecd7fd5dc55ee89_1380x737.png =400x) 以應用層事件處理函數為例,它的第2個參數UINT16 events表示了一個事件集合,其中包含了0個或多個待處理的事件。然而,events是一個16位的變量,它是怎么樣表示一個事件集合的呢? ### 答案是Z-Stack 3.0采用了獨熱碼(one-hot code)的方式對事件類型進行編碼。 ### **events的分類** 在講解獨熱碼之前,先來了解一下events的分類。 * events的最高位為1時,表示這是系統事件集合,即events中的事件全是系統事件。 * events的最高位為0時,表示這是用戶事件集合,即events中的事件全是用戶事件。 用戶事件可以由開發者自行定義其含義,以及相應的處理。 ### **使用獨熱碼** 采用獨熱碼的方式,把所有的**用戶事件編碼**列舉出來,并從中分析獨熱碼的規律,見下表。 | 2進制編碼 | 16進制編碼 | 事件名稱 | | --- | --- | --- | | 0000 0000 0000 0001 | 0x00 01 | 用戶事件A | | 0000 0000 0000 0010 | 0x00 02 |用戶事件B | | 0000 0000 0000 0100 | 0x00 04 | 用戶事件C | | 0000 0000 0000 1000 | 0x00 08 | 用戶事件D | | 0000 0000 0001 0000 | 0x00 10 | 用戶事件E | | 0000 0000 0010 0000 | 0x00 20 | 用戶事件F | | 0000 0000 0100 0000 | 0x00 40 | 用戶事件G | | 0000 0000 1000 0000 | 0x00 80 | 用戶事件H | | 0000 0001 0000 0000 | 0x01 00 | 用戶事件I | | 0000 0010 0000 0000 | 0x02 00 | 用戶事件J | | 0000 0100 0000 0000 | 0x04 00 | 用戶事件K | | 0000 1000 0000 0000 | 0x08 00 | 用戶事件L | | 0001 0000 0000 0000 | 0x10 00 | 用戶事件M | | 0010 0000 0000 0000 | 0x20 00 | 用戶事件N | | 0100 0000 0000 0000 | 0x40 00 | 用戶事件O | >[info] 其中事件名稱可以根據實際需命名,例如開燈事件、關燈事件或者發送警告事件等。 ### 從這些編碼中,可以得出2個規律: 1. 除了用于表示系統事件或者用戶事件的最高位,其他15個比特位中,只有1位為1,其他位均為0。 2. 使用15個比特位表示15種用戶事件。 >[info] 這兩個規律也是獨熱碼的規律。 利用規律1,可以很容易地理解為什么events可以表示一個事件集合。現在假設events的值為0000 0000 0101 0101,其中的右起第1、3、5和7位為1,于是可以理解為事件集合events包含了用戶事件A、C、E和G。 ### 利用規律2,可以得到events最多可以包含15種用戶事件。 <br/> ## **定義用戶事件** 可以使用以下方法在zcl\_samplesw.h文件中定義一個用戶事件。 1.定義事件名稱和對應的編碼。 ``` #define SAMPLEAPP_TEST_EVT 0x0040 ``` 2.把它復制到zcl\_samplesw.h文件中的如圖所示位置。 ![](https://img.kancloud.cn/9f/4d/9f4d135f1938a281576ec14535faf839_1392x1011.png) <br/> ## **處理用戶事件** 可以在zcl\_samplesw.c文件中的應用層事件處理函數中添加相關的處理,代碼如下: ``` uint16 zclSampleSw_event_loop( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter //用戶事件:SAMPLESW_TOGGLE_TEST_EVT if( events & SAMPLESW_TOGGLE_TEST_EVT ) { osal_start_timerEx(zclSampleSw_TaskID,SAMPLESW_TOGGLE_TEST_EVT,500); zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, 0 ); //消除已經處理的事件然后返回未處理的事件 return (events ^ SAMPLESW_TOGGLE_TEST_EVT); } //SYS_EVENT_MSG:0x8000表示系統事件,也就是說檢測uint16最高位 if ( events & SYS_EVENT_MSG ) { //省略系統事件的處理代碼 ......... // 消除系統事件標識然后返回未處理的事件 return (events ^ SYS_EVENT_MSG); } #if ZG_BUILD_ENDDEVICE_TYPE //用戶事件:SAMPLEAPP_END_DEVICE_REJOIN_EVT if ( events & SAMPLEAPP_END_DEVICE_REJOIN_EVT ) { bdb_ZedAttemptRecoverNwk(); return ( events ^ SAMPLEAPP_END_DEVICE_REJOIN_EVT ); } #endif //用戶事件:SAMPLEAPP_LCD_AUTO_UPDATE_EVT if ( events & SAMPLEAPP_LCD_AUTO_UPDATE_EVT ) { UI_UpdateLcd(); return ( events ^ SAMPLEAPP_LCD_AUTO_UPDATE_EVT ); } //用戶事件:SAMPLEAPP_KEY_AUTO_REPEAT_EVT if ( events & SAMPLEAPP_KEY_AUTO_REPEAT_EVT ) { UI_MainStateMachine(UI_KEY_AUTO_PRESSED); return ( events ^ SAMPLEAPP_KEY_AUTO_REPEAT_EVT ); } // 處理剛才自己定義的用戶事件:SAMPLEAPP_TEST_EVT if ( events & SAMPLEAPP_TEST_EVT ) { printf("Hello World!\r\n"); //消除已經處理的事件然后返回未處理的事件 return ( events ^ SAMPLEAPP_TEST_EVT ); } // Discard unknown events return 0; } ``` 通過前面講解可以了解到,每一種用戶事件類型編碼中只有1位為1,其他比特位為0。SAMPLEAPP\_TEST\_EVT的事件類型編碼為0x0040,其二進制數為:0000 0000 0000 0100。這個編碼的右起第3為1,其余位為0。 ### 于是上述代碼利用events?&?SAMPLEAPP_TEST_EVT讓事件集合參數events與預定義的事件類型SAMPLEAPP_TEST_EVT做與運算,判斷events中的右起第3位是否為1。如果為1,那么events?&?SAMPLEAPP_TEST_EVT的值為1,這表示事件集合參數events包含SAMPLEAPP_TEST_EVT這個事件,因此程序執行對應的處理代碼,即執行: ``` ?printf("Hello?World!\r\n");???? ``` ### 接著,代碼中利用events?^?SAMPLEAPP_TEST_EVT把events中的第3位清0,然后把這個值作為函數的返回值,表示events中的這個事件已經被處理了。 >[warning] 這段代碼中用到了 & 和 ^ 運算,如果不了解這兩種運算,需要先補習一下。 <br/> ## **觸發用戶事件** 前面已經定義好事件類型和對應的處理方式了,但是需要在OSAL中觸發該事件后,OSAL才會執行對應的處理代碼。 ### OSAL提供了專門的API來觸發事件。展開OSAL層,可以找到OSAL\_Timers.h文件,如圖所示。 ![](https://img.kancloud.cn/3b/1d/3b1d72df37d3aec4adf70dbbd42e136b_280x728.png =250x) ### 在OSAL\_Timers.h文件中,可以找到觸發事件的API,函數聲明如下: ``` uint8?osal_start_timerEx(uint8?task_id,uint16?event_id,uint32?timeout_value); ``` 該函數有三個參數,其說明如下: * task\_id:任務ID,用于標記這個事件是屬于哪一個層次的任務。 * event\_id:事件ID,用于標記這個事件的類型。 * timeout\_value:表示多少毫秒后才處理這個事件。 如果希望在觸發事件的3s后處理剛才自定義的事件,可在應用層初始化函數zclSampleSw\_Init()的末尾位置添加如下代碼: ``` osal_start_timerEx( zclSampleSw_TaskID,//標記本事件屬于應用層任務 SAMPLEAPP_TEST_EVT,//標記本事件的類型 3000);//表示3000ms后才處理這個事件 ``` 其中,zclSampleSw\_TaskID是一個全局變量,用于標記這個事件是屬于應用層任務的。 ### 添加代碼后的效果如圖所示。 ![](https://img.kancloud.cn/7d/d7/7dd706f032756037bc5282adea11abc3_738x270.png =600x) <br/> ## **調試仿真** 右擊工程名稱,選擇Options,如圖所示。 ![](https://img.kancloud.cn/aa/f4/aaf4d84e70bc77dce45b2870ca8e5c70_1000x585.png =500x) ### 選擇Debugger,然后在Driver選項卡中選擇Texas Instruments,最后單擊OK按鈕完成設置,如圖所示。 ![](https://img.kancloud.cn/46/6c/466ca2a3e4e0fc7e3b3f341c08f2ac01_1000x786.png =400x) ### 使用仿真器把配套的ZigBee開發板連接到電腦。 ### 單擊Download and Debug按鈕進行程序的編譯、鏈接和下載并進入仿真模式,如圖所示。 ![](https://img.kancloud.cn/81/16/81166ae4ef8ce78720f184d22911cd5b_1000x570.png =500x) ### 進入仿真模式之后,單擊Go按鈕運行程序,如圖所示。 ![](https://img.kancloud.cn/d7/61/d76127c40858f031348f5bd4856909ae_2560x827.png =200x) ### 程序在運行3后秒會在Terminal I/O窗口中輸出“Hello World!”,如圖所示。 ### ![](https://img.kancloud.cn/fe/24/fe2421c96cb6508d6bd9b0e8244ff447_1000x602.png =200x) <br/> <br/> ## **項目定制** * 如需項目定制開發,可掃碼添加項目經理好友(注明“**項目定制**”) * 定制范圍:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等IoT技術方案 * 善學坊官網:[www.sxf-iot.com](https://www.sxf-iot.com/) ![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =200x) * 非項目定制**勿擾**,此處**非**技術支持
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看