快速了解ZigBee的協議(yi)棧(zhan)
時間:2018-09-25 來源:未(wei)知
帶大家來一起(qi)快速的看懂ZigBee的協議棧的運行(xing)流程。
1.讀任何程序都需要(yao)從main函(han)數入手,那(nei)我們先來看Zmain.c中的main函(han)數。
問題:在main中我們會看到很多的函數,我們究竟(jing)要看哪個(ge)函數呢?
回答:這(zhe)么多的(de)函數中其(qi)實我們只需要關(guan)注osal_init_system()和osal_start_system()兩(liang)個(ge)函數就可以了。我們在(zai)編程的(de)時候其(qi)實也(ye)只會關(guan)系(xi)到這(zhe)兩(liang)個(ge)函數。
2.我們跟(gen)蹤(把光(guang)標放在這個函數上點右鍵(jian),再點擊(ji)go to define)osal_init_system()這個函數,發現它在OSAL.c文件(jian)中。
問題:在這個函(han)(han)數中有(you)遇到了(le)很(hen)多函(han)(han)數,那我們又要關注(zhu)那些函(han)(han)數呢?
回(hui)答(da):這個(ge)函(han)數(shu)中(zhong)我(wo)們(men)只需(xu)要(yao)關注osalInitTasks()函(han)數(shu)就(jiu)可(ke)以了,這其(qi)實就(jiu)是(shi)把每個(ge)事件作為每個(ge)任務。
3.我們跟蹤osalInitTasks()這個(ge)函(han)數,發現(xian)在OSAL_SampleApp.c中。其他(ta)的函(han)數先不管。
在這個函數我(wo)們(men)可以(yi)看到我(wo)們(men)的(de)任務(wu)(wu)編號是從0開始的(de),然(ran)后每(mei)添加一個任務(wu)(wu)任務(wu)(wu)編號(taskID++)就加一,并(bing)且為任務(wu)(wu)分配內存。如(ru)下:
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
在這(zhe)個(ge)函(han)數(shu)中需(xu)要我(wo)(wo)們特別關注的(de)(de)是SampleApp_Init(taskID)這(zhe)個(ge)函(han)數(shu),因為我(wo)(wo)們在編程的(de)(de)時(shi)候這(zhe)個(ge)函(han)數(shu)是需(xu)要我(wo)(wo)們程序員(yuan)去編寫的(de)(de),這(zhe)個(ge)事協議棧提供的(de)(de)編程接口。
4.同(tong)樣(yang)我(wo)(wo)(wo)們跟蹤這(zhe)個函(han)數SampleApp_Init(taskID),發現它(ta)在SampleApp.c中(zhong)(這(zhe)個函(han)數很重(zhong)要(yao)(yao))。在這(zhe)個函(han)數中(zhong)我(wo)(wo)(wo)們看到需要(yao)(yao)我(wo)(wo)(wo)們去(qu)配置一些信息,如串口波特(te)率、流控等等。
uartConfig.callBackFunc = Serial_CallBack;
這(zhe)需要我(wo)們來定義串口回調函數(shu)來無線發(fa)送(song)數(shu)據。
5.現在系統的初始化已經做好了,遇到SampleApp_Init()函數的return后一步一步的返回。
6.返(fan)回到main函(han)數后(hou),我(wo)們(men)再來看osal_start_system()函(han)數,注意這個(ge)函(han)數一但進去之后(hou),此函(han)數就不會再返(fan)回。我(wo)們(men)跟蹤這個(ge)函(han)數,發(fa)現它在(zai)OSAL.c中(zhong)。
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt);
注意這(zhe)(zhe)段(duan)邏(luo)輯(ji),這(zhe)(zhe)是把任務中優先級高的選出來(lai)。
events = tasksEvents[idx];//把優先級高的選出來(lai)賦值給事件(jian)來(lai)處理。
這里我們需要來看一個數(shu)組:
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SampleApp_ProcessEvent
};
我們知道這(zhe)(zhe)些都是事件(jian)處理函數。問題又(you)來了(le),這(zhe)(zhe)么多(duo)我們應該看和用哪(na)一個呢?
協議棧給用(yong)戶提(ti)供的函數編(bian)程接口(kou)是SampleApp_ProcessEvent這個函數。
然而怎么調用到(dao)這(zhe)個(ge)函數呢?看下(xia)面的代(dai)碼。
events = (tasksArr[idx])( idx, events );//這是(shi)(shi)是(shi)(shi)一(yi)個函(han)數指針的應用。自己(ji)補C語言,這里不贅述。
7.既然是(shi)這樣我們就(jiu)要跟蹤SampleApp_ProcessEvent()這個函數,發現它在SampleApp.c中。
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
這是(shi)我們需要(yao)關注的(de)case,這個(ge)就是(shi)接受到數(shu)據(ju)的(de)時候讀出無線發(fa)過來的(de)數(shu)據(ju)。SampleApp_MessageMSGCB( MSGpkt );這個(ge)函數(shu)就需要(yao)程序(xu)員進行編寫。所以這個(ge)函數(shu)也(ye)非(fei)常的(de)重要(yao)。
這就(jiu)是協議棧(zhan)的(de)(de)大體運行過程,當然這些還(huan)很淺(qian)顯,還(huan)沒有討論一(yi)些深層次的(de)(de)內容,并(bing)且(qie)有些地方寫得不合適的(de)(de)地方,希(xi)望大家指正,這里我表(biao)示(shi)萬分的(de)(de)感激(ji)。

