1. 程式人生 > >ZigBee協議棧開發(五)

ZigBee協議棧開發(五)

一、協議棧的使用

1、更改檔案中的名稱為自己的定義

2、選擇不同的選項卡來選擇協調器、路由器、終端程式的下載,由於選項選擇不同,就會導致參與編譯的配置檔案不同,配置不同就會導致部分巨集定義不同,巨集定義不同就會導致工程裡某些巨集的值不同,這些巨集值不同就會影響程式執行的流程,就會導致出現不同的功能,所以就有了不同功能的程式碼版本,協調器、路由器、終端。

3、程式碼解析:

(1)-DDEFAULT_CHANLIST=0x00000800  // 11 - 0x0B 

#define  DEFAULT_CHANLIST 0x00000800

DEFAULT_CHANLIST表明Zigbee模組要工作的網路,當有多個通道引數值進行或操作之後,把結果作為DEFAULT_CHANLIST 值,那麼對於路由器和終端協調器的意義分別是:

路由器和終端:

  可以在參與或操作的這些通道上選擇一個相對來說最佳的網路加入進去

協調器

  可以在參與或操作的這些通道上選擇一個最佳的通道並在這個通道上建立自己的Zigbee網路

(2)PANID

 非0xFFFF時

   路由器和終端:必須要加入到PANID為引數值這樣一個Zigbee無線區域網

   協調器:要建立一個網路,並且把這個引數值作為這個網路的PANID

 為0xFFFF時:

   路由器和終端:在加入網路的時候沒有PANID的限制

   協調器:可以隨機生成一個值,把這個隨機值作為這個網路的PANID

當兩個模組下載相同的協調器程式碼,並且指定的PANID引數值為非0xFFFF時,先上電的協調器會首先建立一個以這個引數為PANID的網路,後上電的會建立一個以這個引數加1為PANID的網路,再多則依次加1建立網路。

(3)uint8osal_set_event( uint8 task_id, uint16 event_flag )

在ZStack裡按照程式碼功能來分,分成不同的層,比如硬體操作相關的硬體層,網路相關的網路層,自己寫應用程式的應用層。幾乎每一個層都是一個任務,系統為每一個任務分配一個一個位元組的唯一數值編號,每一個任務都能處理一些他們能夠處理的事物,我們把數值編號叫做任務ID,他們能處理的事物叫做事件。這個函式的第一個引數是任務ID,第二個是事件號,呼叫這個函式可以指定任務中的事件進行處理。

(4)uint8 osal_start_timerEx(uint8 taskID, uint16 event_id, uint16 timeout_value )

這個函式與上一個函式類似,前兩個引數都相同,多加了一個引數是間隔時間(單位是ms),呼叫這個函式可以指定任務的某個事件在一定時間之後進行處理。

使用者可以自己定義自己的事件並且進行處理,一個任務號對應的事件只能有16個,因為事件號只有16位,每個事件號之能是16位中有1位為1。但是系統在執行時,會有許多事件需要處理,所以事件號是不夠用的,為此引入了訊息的概念。

訊息處理的原理:

首先定義事件:#define SYS_EVENT_MSG            0x8000  // A message is waiting event

當需要應用層任務來處理某件事時,首先給應用層任務傳送一個訊息,呼叫osal_set_event(SDApp_TaskID,SYS_EVENT_MSG);這樣應用層就會進入SYS_EVENT_MSG事件處理,在這個事件處理函式中判斷剛剛引發產生SYS_EVENT_MSG事件的是哪一種訊息,然後根據訊息型別做相應的處理,而訊息的型別可以自己無限定義,這樣應用層可以處理的事情就很多了。

注:某些硬體可能會與TI官方定義的板子硬體初始化衝突,所以一方面我們要把自己的初始化程式放在官方初始化程式之後,然後也一定要把初始化工作做全面,比如LED設定io口時,模式、輸入輸出一定要都定義一下。

4、按鍵的相關修改

這裡不建議修改官方的巨集定義,而是建立自己的初始化函式放在官方初始化函式之後即可,要注意的是按鍵有延時,協議棧中進入中斷應該儘快出去,所以在按鍵中斷中不要用延時函式,改為使用osal_start_timerEx函式,定時25ms之後進入一個時間中處理按鍵事件。

 

二、OSAL作業系統原理

1、應用層是一個任務,有一個系統分配給它的數值唯一的編號——任務ID。

2、任務可以處理事件,處理事件的這些程式碼都在一個函式中,這個函式叫做任務事件處理函式。

3、應用層任務還有一個2個位元組的變數,叫任務事件變數。任務事件變數與應用層定義的事件的關係是:如果事件變數和某個事件的巨集值與操作為1,那麼表示應用層任務將要處理這個事件。系統在執行時會不斷的讀應用層任務事件變數,當它發現這個變數為0就認為應用層任務當前沒有事件需要去處理,如果發現這個變數不為0,它就認為應用層任務有事件將要去處理,就會呼叫應用層任務事件處理函式SDApp_ProcessEvent( byte task_id, UINT16 events ),並且把任務事件變數的值傳給events,在事件處理函式中,events會分別和應用層定義的所有事件巨集巨集值進行與操作,如果發現哪個為0,那麼就去執行這個事件處理對應的程式碼。

4、呼叫osal_set_event(SDApp_TaskID,SYS_EVENT_MSG)函式時,SDApp_TaskID就會去執行SYS_EVENT_MSG事件相應的程式碼。這是由於這個函式的本質是把SDApp_TaskID(應用層任務)的任務事件變數中對應於SYS_EVENT_MSG巨集值為1的那一位變為 1,這樣的話首先這個任務事件變數就變成非0,系統在檢測到任務事件變數為非0時,就會去呼叫任務事件處理函式SDApp_ProcessEvent,在這個函式中,任務事件變數肯定和SYS_EVENT_MSG巨集值與操作為1,所以必定會執行這個事件相關的程式碼。

幾乎每個層都是一個任務,那麼每一個層都有一個任務ID,任務處理函式,任務事件變數。

協議棧將各個層的所有任務處理函式都放在一個函式陣列中,將所有的任務事件變數也都放到一個變數陣列中。

任務ID是系統根據陣列下標分配的,我們可以通過這個值立即找到這個任務自己的任務事件處理函式和事件變數,應用層任務的任務ID是8,taskArr[8]就是應用層事件處理函式,tasksEvents[8]就是應用層事件變數。

系統在osal_init_system()中的 osalInitTasks()中為各層分配任務ID。

5、osal_start_system(void )中會不斷重複一個過程,在這個過程中,首先會不斷輪詢各層任務變數,如果發現哪一個任務變數不為0則會跳出輪詢,然後通過這個不為0的任務變數找到對應的任務ID,從而進入對應任務ID的任務處理函式。處理完之後再繼續這個過程。