版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第6章Zstack協(xié)議棧6.1概述 6.2Zstack軟件架構6.3HAL層分析6.4NWK層分析6.5Tools配置和分析6.6Profile層分析6.7ZDO層分析6.8API函數(shù)6.9APP層分析6.10OSAL運行機制
理解Zstack軟件架構。
掌握操作系統(tǒng)的運行機制。
掌握Zstack各層的作用。
【描述6.D.】
使用Zstack協(xié)議棧進行數(shù)據(jù)傳輸。
Zstack協(xié)議棧是德州儀器(TI)公司為Zigbee提供的一個解決方案,結合CC2530F256芯片可以完整的實現(xiàn)Zigbee。本章將對Zstack協(xié)議棧進行分層剖析,以介紹其運作原理,這是進行Zstack應用開發(fā)的基礎。6.1概述
Zstack協(xié)議棧符合Zigbee協(xié)議結構,由物理層、MAC層、網絡層和應用層組成。如本書前面所述,物理層和MAC層由IEEE802.15.4定義,網絡層和應用層由Zigbee聯(lián)盟定義。Zigbee聯(lián)盟將應用層詳細劃分為應用支持子層、應用設備框架以及Zigbee設備對象等。
本節(jié)將詳細介紹Zigbee協(xié)議棧的結構。6.2Zstack軟件架構
6.2.1Zigbee協(xié)議棧的結構
Zigbee協(xié)議棧的結構可參考第2章的圖2-3,其中各層的功能如下:
物理層內容:物理層定義了物理無線信道和MAC子層之間的接口,提供物理層數(shù)據(jù)服務單元(PD-SAP)和物理層管理服務(MLME-SAP)。
MAC(介質接入控制子層):MAC層負責處理所有物理無線信道的訪問,并產生網絡信號、同步信號;支持PAN連接和分離,提供兩個對等的MAC實體之間的可靠鏈路。
NWK(網絡層):網絡層是Zigbee協(xié)議棧的核心部分,網絡層主要實現(xiàn)節(jié)點加入或者離開網絡、接收或拋棄節(jié)點、路由查找及維護等功能。
APL(應用層):Zigbee應用層包括應用支持子層APS、應用程序框架AF、Zigbee設備對象ZDO等。
應用支持子層APS:APS層在NWK層和APL層之間,提供APSDE-SAP和APSME-SAP兩個接口,兩個接口的主要功能如下:
APSDE-SAP提供在同一個網絡中的兩個或者更多的應用實體之間(即端點)的數(shù)據(jù)通信。
APSME-SAP提供多種服務給應用對象ZDO,這些服務包括安全服務和綁定設備服務,并維護管理對象的數(shù)據(jù)庫(即AIB)。
應用程序框架AF:運行在Zigbee協(xié)議棧上的應用程序實際是廠商自定義的應用對象,并且遵循規(guī)范(Profile)運行在端點1~240上。設備對象層ZDO:遠程設備通過ZDO請求描述信息,接收到這些請求時,ZDO會調用配置對象獲取相應的描述符值。ZDO通過APSME-SAP接口提供綁定服務。
6.2.2Zstack協(xié)議棧
Zstack協(xié)議棧可以從TI的官方網站下載(截止本書出版時,Zstack協(xié)議棧的最新版本為Zstack-CC2530-2.5.1a),其下載網址為,下載完成后,雙擊可執(zhí)行程序即可安裝。使用IAR8.10版本打開Zstack-CC2530-2.5.1a中的SampleApp工程,其協(xié)議棧代碼文件夾如圖6-1所示。
其中部分層的功能如下:
APP:應用層目錄,用戶可以根據(jù)需求添加自己的任務。這個目錄中包含了應用層和項目的主要內容,在協(xié)議棧里面一般是以操作任務實現(xiàn)的。
圖6-1協(xié)議棧代碼文件夾
HAL:硬件驅動層,包括與硬件相關的配置、驅動以及操作函數(shù)。
OSAL:協(xié)議棧的操作系統(tǒng)。
Profile:AF層目錄,包含AF層處理函數(shù)。
Security&Services:安全服務層目錄,包含安全層和服務層處理函數(shù),比如加密。
Tools:工程配置目錄,包括空間劃分及ZStack相關配置信息。
ZDO:ZDO設備對象目錄。
ZMac:MAC層目錄,包括MAC層參數(shù)及MAC層的LIB庫函數(shù)回調處理函數(shù)。
Zmain:主函數(shù)目錄,包括入口函數(shù)及硬件配置文件。
Output:輸出文件目錄,由IAR自動生成。
6.2.3Zigbee協(xié)議棧與Zstack的對比
Zigbee協(xié)議棧的結構與Zstack協(xié)議棧的各層關系如表6-1所示。
表6-1Zigbee協(xié)議棧結構與Zstack對比
注意:Zstack協(xié)議棧是一個半開源的協(xié)議棧,其中MAC層和ZMAC層的源碼沒有全部開源,關于他們的具體內容,在實際的工程開發(fā)中也不需要詳細了解。
Zigbee的HAL層提供了開發(fā)板所有硬件設備(例如LED、LCD、KEY、UART等)的驅動函數(shù)及接口。HAL文件夾為硬件平臺的抽象層,包含common、include和target三個文件夾,如圖6-2所示。6.3HAL層分析
圖6-2HAL層目錄
6.3.1Common文件夾
Common文件夾下包含有hal_assert.c和hal_dirvers.c兩個文件。其中hal_assert.c是聲明文件,用于調試,hal_dirvers.c是驅動文件,如圖6-3所示。
圖6-3Common目錄
1.
hal_assert.c
在hal_assert.c文件中包含兩個重要的函數(shù):halAssertHandler()和halAssertHazardLights()。
(1)
halAssertHandler()函數(shù)為硬件系統(tǒng)檢測函數(shù)。如果定義了ASSERT_RESET宏,系統(tǒng)將調用HAL_SYSTEM_RESET復位,否則將調用halAaaertHazardLights()執(zhí)行閃爍LED命令。halAssertHandler()函數(shù)如下:
【函數(shù)6-1】halAssertHandler()
voidhalAssertHandler(void)
{
//如果定義了ASSERT_RESET宏定義
#ifdefASSERT_RESET
//系統(tǒng)復位
HAL_SYSTEM_RESET();
#else!definedASSERT_WHILE
//當檢測到錯誤時,LED燈閃爍命令函數(shù)
halAssertHazardLights();
#else
while(1);
#endif
}
(2)
halAssertHazardLights()函數(shù)控制LED燈閃爍,根據(jù)不同的硬件平臺定義的LED的個數(shù)來決定閃爍的LED的不同。例如,CC2430和CC2530所使用的硬件平臺不同,決定了閃爍的LED不同,其主要代碼如下:
【代碼6-1】halAssertHazardLights()
//如果硬件平臺定義的LED的個數(shù)為1
#if(HAL_NUM_LEDS>=1)
//LED1閃爍
HAL_TOGGLE_LED1();
//如果硬件平臺定義的LED的個數(shù)為2
#if(HAL_NUM_LEDS>=2)
//LED2閃爍
HAL_TOGGLE_LED2();
//如果硬件平臺定義的LED的個數(shù)為3
#if(HAL_NUM_LEDS>=3)
//LED3閃爍
HAL_TOGGLE_LED3();
//如果硬件平臺定義的LED的個數(shù)為4
#if(HAL_NUM_LEDS>=4)
//LED4閃爍
HAL_TOGGLE_LED4();
#endif
#endif
#endif
#endif
2.
hal_drivers.c
hal_drivers.c文件中包含了與硬件相關的初始化和事件處理函數(shù)。此文件中有4個比較重要的函數(shù):硬件初始化函數(shù)Hal_Init()、硬件驅動初始化函數(shù)HalDriverInit()、硬件事件處理函數(shù)Hal_ProcessEvent()和詢檢函數(shù)Hal_ProcessPoll()。
(1)
Hal_Init()函數(shù)是硬件初始化函數(shù),其功能是通過“注冊任務ID號”以實現(xiàn)在OSAL層注冊,從而允許硬件驅動的消息和事件由OSAL處理。其函數(shù)內容為:
【函數(shù)6-2】Hal_Init()
voidHal_Init(uint8task_id)
{
//注冊任務ID
Hal_TaskID=task_id;
}
(2)
HalDriverInit()函數(shù)被main()函數(shù)調用,用于初始化與硬件設備有關的驅動。HalDriverInit()函數(shù)的具體功能如下:
【函數(shù)6-3】HalDriverInit()
voidHalDriverInit(void)
{
//如果定義了定時器則初始化定時器
#if(definedHAL_TIMER)&&(HAL_TIMER==TRUE)
//在Zstack-CC2530-2.5.1a版本中移除了定時器的初始化,但不影響Zstack的運行。
#error"Thehaltimerdrivermoduleisremoved."
#endif
//如果定義了ADC,初始化ADC
#if(definedHAL_ADC)&&(HAL_ADC==TRUE)
HalAdcInit();
#endif
//如果定義了DMA,初始化DMA
#if(definedHAL_DMA)&&(HAL_DMA==TRUE)
HalDmaInit();
#endif
//如果定義了AES,初始化AES
#if(definedHAL_AES)&&(HAL_AES==TRUE)
HalAesInit();
#endif
//如果定義了LCD,初始化LCD
#if(definedHAL_LCD)&&(HAL_LCD==TRUE)
HalLcdInit();
#endif
//如果定義了LED,初始化LED
#if(definedHAL_LED)&&(HAL_LED==TRUE)
HalLedInit();
#endif
//如果定義了UART,初始化UART
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTInit();
#endif
//如果定義了按鍵,初始化KEY
#if(definedHAL_KEY)&&(HAL_KEY==TRUE)
HalKeyInit();
#endif
//如果定義了SPI,初始化SPI
#if(definedHAL_SPI)&&(HAL_SPI==TRUE)
HalSpiInit();
#endif
//如果定義了USB,初始化USB,只限CC2531
#if(definedHAL_HID)&&(HAL_HID==TRUE)
usbHidInit();
#endif
}
(3)
Hal_ProcessEvent()函數(shù)在APP層中的任務事件處理中被調用,用于對相應的硬件事件作出處理,具體包括系統(tǒng)消息事件、LED閃爍事件、按鍵處理事件和睡眠模式等。
【函數(shù)6-4】Hal_ProcessEvent()
uint16Hal_ProcessEvent(uint8task_id,uint16events)
{
uint8*msgPtr;
(void)task_id;
//系統(tǒng)消息事件
if(events&SYS_EVENT_MSG)
{
msgPtr=osal_msg_receive(Hal_TaskID);
while(msgPtr)
{
osal_msg_deallocate(msgPtr);
msgPtr=osal_msg_receive(Hal_TaskID);
}
returnevents^SYS_EVENT_MSG;
}
//LED閃爍事件
if(events&HAL_LED_BLINK_EVENT)
{
#if(defined(BLINK_LEDS))&&(HAL_LED==TRUE)
HalLedUpdate();
#endif
returnevents^HAL_LED_BLINK_EVENT;
}
//按鍵處理事件
if(events&HAL_KEY_EVENT)
{
#if(definedHAL_KEY)&&(HAL_KEY==TRUE)
HalKeyPoll();
if(!Hal_KeyIntEnable)
{
osal_start_timerEx(Hal_TaskID,HAL_KEY_EVENT,100);
}
#endif
returnevents^HAL_KEY_EVENT;
}
//睡眠模式
#ifdefPOWER_SAVING
if(events&HAL_SLEEP_TIMER_EVENT)
{
halRestoreSleepLevel();
returnevents^HAL_SLEEP_TIMER_EVENT;
}
#endif
return0;
}
(4)
Hal_ProcessPoll()函數(shù)在main()函數(shù)中被osal_start_system()調用,用來對可能產生的硬件事件進行詢檢。函數(shù)原型為:
【函數(shù)6-5】Hal_ProcessPoll()
voidHal_ProcessPoll()
{
//定時器詢檢
#if(definedHAL_TIMER)&&(HAL_TIMER==TRUE)
HalTimerTick();
#endif
//UART詢檢
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTPoll();
#endif
//定時器詢檢
#if(definedHAL_TIMER)&&(HAL_TIMER==TRUE)
//在Zstack-CC2530-2.5.1a版本中移除了定時器的初始化,但不影響Zstack的運行。
#error"Thehaltimerdrivermoduleisremoved."
#endif
//串口詢檢
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTPoll();
#endif
//SPI詢檢
#if(definedHAL_SPI)&&(HAL_SPI==TRUE)
HalSpiPoll();
#endif
//USB詢檢(僅限CC2530)
#if(definedHAL_HID)&&(HAL_HID==TRUE)
usbHidProcessEvents();
#endif
//如果定義了休眠模式
#ifdefined(POWER_SAVING)
//允許在下一個事件到來之前進入休眠模式
ALLOW_SLEEP_MODE();
#endif
}硬件驅動初始化函數(shù)HalDriverInit()和硬件事件處理函數(shù)Hal_ProcessEvent()是Zigbee協(xié)議棧固有的,一般不需要作出較大范圍的修改,只需要直接使用即可。
6.3.2Include文件夾
Include文件夾主要包含各個硬件模塊的頭文件,主要內容是與硬件相關的常量定義以及函數(shù)聲明,如圖6-4所示。
圖6-4Include目錄
表6-2Include目錄下頭文件類型
6.3.3Target文件夾
Target目錄下包含了某個設備類型下的硬件驅動文件、硬件開發(fā)板上的配置文件、MCU信息和數(shù)據(jù)類型。本書采用的硬件平臺為CC2530,因此本節(jié)以硬件設備類型CC2530EB(EB是版本號,表示的是評估版)為例進行講解,如圖6-5所示。
注意:上述“CC2530EB”中的字符“EB”是TI公司的Zstack在某個硬件實現(xiàn)上的版本號,例如,“BB”是電池版(BatteryBoard),“DB”是開發(fā)版(DevelopmentBoard),“EB”是評估版(EvaluateBoard)。
在CC2530EB文件夾下包含了三個子文件夾,分別是Config、Drivers、Includes,如圖6-6所示。
圖6-5Target文件夾
圖6-6CC2530EB文件夾
1.
Config文件夾
Config文件夾中包含了hal_board_cfg.h,在hal_board_cfg.h中定義了硬件CC2530硬件資源的配置,比如GPIO、DMA、ADC等。
在hal_board_cfg.h文件中可以定義開發(fā)板的硬件資源。以LED為例,TI官方的CC2530EB版本定義了兩個LED:LED1和LED2,其在hal_board_cfg.h中定義如下:
【代碼6-2】hal_board_cfg.h
//有關LED1宏定義
#defineLED1_BVBV(0)
#defineLED1_SBITP1_0
#defineLED1_DDRP1DIR
#defineLED1_POLARITYACTIVE_HIGH
//如果定義了HAL_BOARD_CC2530EB_REV17,則定義LED2和LED3
#ifdefined(HAL_BOARD_CC2530EB_REV17)
//有關LED2的宏定義
#defineLED2_BVBV(1)
#defineLED2_SBITP1_1
#defineLED2_DDRP1DIR
#defineLED2_POLARITYACTIVE_HIGH
//有關LED3的宏定義
#defineLED3_BVBV(4)
#defineLED3_SBITP1_4
#defineLED3_DDRP1DIR
#defineLED3_POLARITYACTIVE_HIGH
#endif
LED宏定義完成之后,設置LED的打開和關閉,其代碼在hal_board_cfg.h文件中,代碼如下:
【代碼6-3】hal_board_cfg.h
/*如果定義了HAL_BOARD_CC2530EB_REV17且沒有定義HAL_PA_LNA和HAL_PA_LNA_
CC2590,則定義LED的狀態(tài)*/
#ifdefined(HAL_BOARD_CC2530EB_REV17)&&!defined(HAL_PA_LNA)
&&!defined(HAL_PA_LNA_CC2590)
//打開LED1~LED3
#defineHAL_TURN_OFF_LED1()st(LED1_SBIT=LED1_POLARITY(0);)
#defineHAL_TURN_OFF_LED2()st(LED2_SBIT=LED2_POLARITY(0);)
#defineHAL_TURN_OFF_LED3()st(LED3_SBIT=LED3_POLARITY(0);)
#defineHAL_TURN_OFF_LED4()HAL_TURN_OFF_LED1()
//關閉LED1~LED3
#defineHAL_TURN_ON_LED1()st(LED1_SBIT=LED1_POLARITY(1);)
#defineHAL_TURN_ON_LED2()st(LED2_SBIT=LED2_POLARITY(1);)
#defineHAL_TURN_ON_LED3()st(LED3_SBIT=LED3_POLARITY(1);)
#defineHAL_TURN_ON_LED4()HAL_TURN_ON_LED1()
//改變LED1~LED3的狀態(tài)
#defineHAL_TOGGLE_LED1()st(if(LED1_SBIT){LED1_SBIT=0;}
else{LED1_SBIT=1;})
#defineHAL_TOGGLE_LED2()st(if(LED2_SBIT){LED2_SBIT=0;}
else{LED2_SBIT=1;})
#defineHAL_TOGGLE_LED3()st(if(LED3_SBIT){LED3_SBIT=0;}
else{LED3_SBIT=1;})
#defineHAL_TOGGLE_LED4()HAL_TOGGLE_LED1()
LED的設置根據(jù)開發(fā)板的不同,可以設置不同的LED,其設置過程如上所述。
2.
Drivers文件夾
在Drivers文件中定義了硬件資源的驅動文件,所定義的硬件資源如表6-3所示。
表6-3硬件資源驅動文件其中,以最常用的LED為例,在hal_led.c文件中提供了兩個封裝好的函數(shù),在應用層可以直接調用,以控制LED,這兩個函數(shù)是:
HalLedSet(uint8leds,uint8mode)。
HalLedBlink(uint8leds,uint8numBlinks,uint8percent,uint16period)。
(1)
HalLedSet()函數(shù)用來控制LED的亮滅,該函數(shù)的原型如下:
【函數(shù)6-6】HalLedSet()
HalLedSet(uint8leds,uint8mode);
其中:
參數(shù)leds,指LED的名稱,取值可以是:
HAL_LED_1。
HAL_LED_2。
HAL_LED_3。
HAL_LED_4。參數(shù)mode,指LED的狀態(tài),取值可以為以下幾種情況:
打開LED:HAL_LED_MODE_ON。
關閉LED:HAL_LED_MODE_OFF。
改變LED狀態(tài):HAL_LED_MODE_TOGGLE。
以上數(shù)據(jù)定義在hal_led.h文件中。
(2)
HalLedBlink()函數(shù)是用來控制LED閃爍的,函數(shù)原型如下:
【函數(shù)6-7】HalLedBlink()
HalLedBlink(uint8leds,uint8numBlinks,uint8percent,uint16period)
其中:
參數(shù)leds,指LED的名稱,參數(shù)可以為:
HAL_LED_1。
HAL_LED_2。
HAL_LED_3。
HAL_LED_4。參數(shù)numBlinks,指閃爍次數(shù)。
參數(shù)percent,指LED亮和滅的所用事件占空比,例如亮和滅所用的事件比例為
1∶1,則占空比為100/2
=
50。
參數(shù)period,指LED閃爍一個周期所需要的時間,以毫秒為單位。
Zstack的NWK層負責的功能有:節(jié)點地址類型的分配、協(xié)議棧模板、網絡拓撲結構、網絡地址的分配的選擇等。在Zstack協(xié)議棧中,NWK層的結構如圖6-7所示。6.4NWK層分析
圖6-7NWK層結構
6.4.1節(jié)點地址類型的選擇
Zstack中地址類型有兩種:64位IEEE地址和16位網絡地址(在Zstack中也稱短地址或網絡短地址)。
64位IEEE地址:即MAC地址(也稱“長地址”或“擴展地址”),是一個全球唯一的地址,一經分配將跟隨設備一生,通常由制造商在設備出廠或安裝時設置,這些地址由IEEE組織來維護和分配。
16位網絡地址:是設備加入網絡后,由網絡中的協(xié)調器分配給設備的地址(也稱“短地址”),它在網絡中是唯一的,用來在網絡中鑒別設備和發(fā)送數(shù)據(jù)。對于協(xié)調器,網絡地址固定為0x0000。
Zstack協(xié)議棧聲明了讀取IEEE地址和網絡地址的函數(shù),函數(shù)的聲明可以在NLMEDE.h文件中看到,但是具體的函數(shù)實現(xiàn)是非開源的,在使用的時候直接調用即可。
【代碼6-4】NLMEDE.h
//讀取父節(jié)點的網絡地址
uint16NLME_GetCoordShortAddr(void);
//讀取父節(jié)點的物理地址
voidNLME_GetCoordExtAddr(byte*);
//讀取節(jié)點本身的網絡地址
uint16NLME_GetShortAddr(void);
//讀取自己的物理地址
byte*NLME_GetExtAddr(void);
6.4.2協(xié)議棧模板
Zstack協(xié)議棧模板由Zigbee聯(lián)盟定義,在同一個網絡中的設備必須符合相同的協(xié)議棧模板。Zstack協(xié)議棧使用了Zigbee聯(lián)盟定義的三種模板:Zigbee協(xié)議棧模板、ZigbeePRO協(xié)議棧模板和特定網絡模板。所有的設備只要遵循該協(xié)議,一般情況下,即使使用不同廠商的不同設備,同樣可以形成網絡。
另外,開發(fā)者為了開發(fā)具有特殊性的產品,可以向Zigbee聯(lián)盟申請自定義的模板,在Zstack協(xié)議棧中,開發(fā)者申請了兩種自定義模板。
協(xié)議棧模板由一個ID標識符區(qū)分,此ID標識符可以通過查詢設備發(fā)送的信標幀獲得。在設備加入網絡之前,首先需要確認協(xié)議棧模板的ID標識符。在Zstack協(xié)議棧中,各種模板的ID標識符的定義如下:
“特定網絡”模板的ID標識符被定義為“NETWORK_SPECIFIC”,且模板ID標識符為0。
“Zigbee協(xié)議棧”模板的ID標識符被定義為
“HOME_SPECIFIC”,且模板ID標識符為1。其中,“Zigbee協(xié)議?!蹦0宄S糜谥悄芗揖拥目刂?。
“ZigbeePRO協(xié)議棧”模板的ID標識符被定義為“ZIGBEEPRO_SPECIFIC”,且模板ID標識符為2。自定義模板的ID標識符被定義為“GENERIC_STAR”和“GENERIC_TREE”,且模板ID標識符被分別定義為3和4。從模板ID標識符的定義來看,這兩個自定義模板分別是為星型網絡和樹型網絡專門定義的。三種模板的配置在nwk_globals.h文件中,代碼如下:
【代碼6-5】nwk_globals.h
//“特定網絡”模板ID
#defineNETWORK_SPECIFIC 0
//Zigbee協(xié)議模板ID
#defineHOME_CONTROLS 1
//ZigbeePRO模板ID
#defineZIGBEEPRO_PROFILE 2
//自定義模板ID
#defineGENERIC_STAR 3
//自定義模板ID
#defineGENERIC_TREE 4
//如果定義了ZIGBEEPRO,那么協(xié)議棧為ZIGBEEPRO模板
#ifdefined(ZIGBEEPRO)
#defineSTACK_PROFILE_IDZIGBEEPRO_PROFILE
#else
//如果沒有定義ZIGBEEPRO,那么協(xié)議棧為ZIGBEE模板
#defineSTACK_PROFILE_IDHOME_CONTROLS
#endif
6.4.3網絡參數(shù)配置
網絡參數(shù)配置包括對網絡類型參數(shù)、網絡深度和網絡中每一級可以容納的節(jié)點個數(shù)的配置。
網絡類型即網絡的拓撲結構,包括星型網絡、樹型網絡和網狀型網絡。
網絡深度即路由級別,協(xié)調器位于深度0,協(xié)調器的一級子節(jié)點(即協(xié)調器的直屬子節(jié)點)位于深度1,協(xié)調器的二級子節(jié)點(即協(xié)調器直屬子節(jié)點的子節(jié)點)位于深度2……依次類推,在Zstack協(xié)議棧中定義MAX_NODE_DEPTH為網絡的最大深度。網絡中每一級可以容納的節(jié)點個數(shù),即在Zstack協(xié)議棧中規(guī)定的每一級的路由可以掛載的路由器或終端節(jié)點的個數(shù)。
1.網絡類型參數(shù)和網絡深度的設置
在Zstack協(xié)議棧中星型網絡、樹型網絡和網狀型網絡三種網絡類型的定義在nwk_globals.h文件中,其代碼如下:
【代碼6-6】nwk_globals.h—網絡類型的定義
/**********定義網絡類型***********/
//星型網
#defineNWK_MODE_STAR0
//樹型網
#defineNWK_MODE_TREE1
//網狀網
#defineNWK_MODE_MESH2在Zstack協(xié)議棧中定義的三種網絡拓撲結構分別在不同的模板下定義,且每一種模板下都定義了該網絡的網絡深度,具體定義在nwk_globals.h文件中,其代碼如下:
【代碼6-7】nwk_globals.h—網絡類型和網絡深度的定義
//如果協(xié)議棧模板為ZigbeePRO模板
#if(STACK_PROFILE_ID==ZIGBEEPRO_PROFILE)
//網絡的最大深度為20
#defineMAX_NODE_DEPTH 20
//定義網絡類型為網狀網絡
#defineNWK_MODE NWK_MODE_MESH
#defineSECURITY_MODE SECURITY_COMMERCIAL
#if(SECURE!=0)
#defineUSE_NWK_SECURITY 1//trueorfalse
#defineSECURITY_LEVEL 5
#else
#defineUSE_NWK_SECURITY 0//trueorfalse
#defineSECURITY_LEVEL 0
#endif
//如果協(xié)議棧模板定義為Zigbee協(xié)議棧模板
#elif(STACK_PROFILE_ID==HOME_CONTROLS)
//網絡的最大深度為5
#defineMAX_NODE_DEPTH 5
//定義網絡類型為網狀網絡
#defineNWK_MODE NWK_MODE_MESH
#defineSECURITY_MODE SECURITY_COMMERCIAL
#if(SECURE!=0)
#defineUSE_NWK_SECURITY 1//trueorfalse
#defineSECURITY_LEVEL 5
#else
#defineUSE_NWK_SECURITY 0//trueorfalse
#defineSECURITY_LEVEL 0
#endif
//如果模板為星型網絡的自定義模板
#elif(STACK_PROFILE_ID==GENERIC_STAR)
//網絡的最大深度為5
#defineMAX_NODE_DEPTH 5
//定義網絡類型為星型網絡
#defineNWK_MODE NWK_MODE_STAR
#defineSECURITY_MODE SECURITY_RESIDENTIAL
#if(SECURE!=0)
#defineUSE_NWK_SECURITY 1//trueorfalse
#defineSECURITY_LEVEL 5
#else
#defineUSE_NWK_SECURITY 0//trueorfalse
#defineSECURITY_LEVEL 0
#endif
//如果網絡模板為特定網絡模板
#elif(STACK_PROFILE_ID==NETWORK_SPECIFIC)
//網絡的最大深度為5
#defineMAX_NODE_DEPTH 5
//定義網絡類型為網狀型網絡
#defineNWK_MODE NWK_MODE_MESH
#defineSECURITY_MODE SECURITY_RESIDENTIAL
#if(SECURE!=0)
#defineUSE_NWK_SECURITY 1//trueorfalse
#defineSECURITY_LEVEL 5
#else
#defineUSE_NWK_SECURITY 0//trueorfalse
#defineSECURITY_LEVEL 0
#endif
#endif
2.每一級可以容納的節(jié)點個數(shù)的配置
在Zstack協(xié)議棧中,每一級路由可以容納的節(jié)點的個數(shù)的配置分為兩種情況。
一個路由器或者一個協(xié)調器可以連接的子節(jié)點的最大個數(shù)。
一個路由器或者一個協(xié)調器可以連接的具有路由功能的節(jié)點的最大個數(shù)。如果前者用C來表示,后者用R來表示,那么R為C的一個子集。另外,這兩個參數(shù)的設置與協(xié)議棧模板有關系,具體配置在nwk_globals.c文件中,其代碼如下:
【代碼6-8】nwk_globals.c
//如果協(xié)議規(guī)范為ZigbeePRO模板
#if(STACK_PROFILE_ID==ZIGBEEPRO_PROFILE)
//定義MAX_ROUTERS為默認值
byteCskipRtrs[1]={0};
//定義MAX_ROUTERS為默認值
byteCskipChldrn[1]={0};
//如果協(xié)議規(guī)范為Zigbee模板
#elif(STACK_PROFILE_ID==HOME_CONTROLS)
//定義協(xié)調器和每級路由器下攜帶的路由器節(jié)點個數(shù)為6
byteCskipRtrs[MAX_NODE_DEPTH+1]={6,6,6,6,6,0};
//定義協(xié)調器和每級路由器可以攜帶的節(jié)點個數(shù)為20個
byteCskipChldrn[MAX_NODE_DEPTH+1]={20,20,20,20,20,0};
//如果協(xié)議模板為自定義GENERIC_STAR模板
#elif(STACK_PROFILE_ID==GENERIC_STAR)
//定義協(xié)調器和每級路由器下攜帶的路由器節(jié)點個數(shù)為5
byteCskipRtrs[MAX_NODE_DEPTH+1]={5,5,5,5,5,0};
定義協(xié)調器和每級路由器下攜帶的節(jié)點個數(shù)為5
byteCskipChldrn[MAX_NODE_DEPTH+1]={5,5,5,5,5,0};
//如果協(xié)議規(guī)范為自定義GENERIC_STAR規(guī)范
#elif(STACK_PROFILE_ID==NETWORK_SPECIFIC)
//定義協(xié)調器和每級路由器下攜帶的路由器節(jié)點個數(shù)為5
byteCskipRtrs[MAX_NODE_DEPTH+1]={5,5,5,5,5,0};
//定義協(xié)調器和每級路由器下攜帶的路由器節(jié)點個數(shù)為5
byteCskipChldrn[MAX_NODE_DEPTH+1]={5,5,5,5,5,0};
以上代碼定義中將C和R分別定義為CskipChldrn和CskipRtrs數(shù)組中的元素值。在數(shù)組中元素0表示協(xié)調器下面掛載的節(jié)點或路由器節(jié)點的個數(shù),元素1表示路由器1級下面掛載的節(jié)點或路由器節(jié)點的個數(shù)。依次類推,元素n表示n級路由器下面掛載的節(jié)點或路由器節(jié)點的個數(shù)。例如CskipChldrn數(shù)組中的第一個元素為20,那么C=20;CskipRtrs數(shù)組中的第一個元素為6,那么R=6。這兩個參數(shù)的設置,有時會影響網絡地址的分配。在Zigbee網絡中,網絡地址的分配是由網絡中的協(xié)調器來完成的。在網狀型網絡中,網絡地址的分配是由協(xié)調器隨機地分配的。但是在樹型網絡中,網絡地址的分配遵循了一定的算法。
在ZigbeePRO協(xié)議棧模板中定義的CskipChldrn和CskipRtrs數(shù)組為默認值,其定義代碼如下:
【代碼6-9】ZigbeePRO定義的CskipChldrn和CskipRtrs
//如果協(xié)議規(guī)范為ZigbeePRO模板
#if(STACK_PROFILE_ID==ZIGBEEPRO_PROFILE)
//定義MAX_ROUTERS為默認值
byteCskipRtrs[1]={0};
//定義MAX_ROUTERS為默認值
byteCskipChldrn[1]={0};當在協(xié)議棧模板中使用的CskipChldrn和CskipRtrs數(shù)組為默認值時,網絡地址遵循隨機分配機制,對新加入的節(jié)點使用隨機地址分配,即當一個節(jié)點加入時,首先將接收到父節(jié)點的隨機分配的網絡地址,然后產生“設備聲明”(包含分配到的網絡地址和IEEE地址)發(fā)送至網絡中的其余節(jié)點。如果另一個節(jié)點有著同樣的網絡地址,則通過路由器廣播“網絡狀態(tài)-地址沖突”至網絡中的所有節(jié)點。所有發(fā)生網絡地址沖突的節(jié)點更改自己的網絡地址,然后再發(fā)起“設備聲明”檢測新的網絡地址是否沖突。終端設備不會廣播“地址沖突”,它們的父節(jié)點會幫助完成這個過程。如果一個終端設備發(fā)生了“地址沖突”,它們的父節(jié)點發(fā)送“重新加入”消息至終端設備,并要求其更改網絡地址。然后,終端設備再發(fā)起“設備聲明”檢測新的網絡地址是否沖突。
3.樹型網絡中網絡地址分配的算法
在Zigbee的樹型網絡中,網絡地址分配算法需要三個參數(shù):
網絡的最大深度,在Zstack協(xié)議中被定義為MAX_NODE_DEPTH,在此算法中用L表示。
路由器或協(xié)調器可以連接的子節(jié)點的最大個數(shù),在Zstack協(xié)議棧中被定義為CskipChldrn數(shù)組中元素的值,在此算法中用C表示。路由器或協(xié)調器可以連接的具有路由功能的子節(jié)點的最大個數(shù),在Zstack協(xié)議棧中被定義為CskipRtrs數(shù)組中的元素的值,在此算法中用R表示。
以上三個參數(shù)設置完成后,如果需要計算深度為d的網絡地址偏移量Cskip(d),則有如下計算公式:若L
=
6,C
=
20,R
=
6,那么計算深度d
=
1的網絡地址偏移量Cskip(1)為5181(十六進制為143D),協(xié)調器網絡地址為0x0000,那么協(xié)調器下第一個路由器的網絡地址為0x0001,第二個路由器的網絡地址為0x0001
+
0x143D
=
0x143E。
Tools文件為工程設置文件目錄,比如信道、PANID、設備類型的設置,如圖6-8所示為Tools文件。6.5Tools配置和分析
圖6-8Tools文件在Tools文件中包含了五個子文件,分別是f8w2530.xcl文件、f8wConfig.cfg文件、f8wCoord.cfg文件、f8wEndev.cfg文件和f8wRouter.cfg文件。其中f8w2530.xcl為CC2530的配置文件,使用Zstack協(xié)議棧時不用修改此項,在這里不做講解。
1.
f8wConfig.cfg文件
f8wConfig.cfg文件為Zstack協(xié)議棧的配置文件,在此文件中設置Zigbee使用的信道和Zigbee網絡PANID。其代碼如下:
【代碼6-10】f8wConfig.cfg
//信道設置
//0:868MHz0x00000001
//1-10:915MHz0x000007FE
//11-26:2.4GHz0x07FFF800
//-DMAX_CHANNELS_868MHz 0x00000001
//-DMAX_CHANNELS_915MHz 0x000007FE
//-DMAX_CHANNELS_24GHz 0x07FFF800
//以下為信道11-26的設置
//-DDEFAULT_CHANLIST=0x04000000//26-0x1A
-DDEFAULT_CHANLIST=0x02000000//25-0x19
//-DDEFAULT_CHANLIST=0x01000000//24-0x18
//-DDEFAULT_CHANLIST=0x00800000//23-0x17
//-DDEFAULT_CHANLIST=0x00400000//22-0x16
//-DDEFAULT_CHANLIST=0x00200000//21-0x15
//-DDEFAULT_CHANLIST=0x00100000//20-0x14
//-DDEFAULT_CHANLIST=0x00080000//19-0x13
//-DDEFAULT_CHANLIST=0x00040000//18-0x12
//-DDEFAULT_CHANLIST=0x00020000//17-0x11
//-DDEFAULT_CHANLIST=0x00010000//16-0x10
//-DDEFAULT_CHANLIST=0x00008000//15-0x0F
//-DDEFAULT_CHANLIST=0x00004000//14-0x0E
//-DDEFAULT_CHANLIST=0x00002000//13-0x0D
//-DDEFAULT_CHANLIST=0x00001000//12-0x0C
//-DDEFAULT_CHANLIST=0x00000800//11-0x0B
//網絡PANID的設置
-DZDAPP_CONFIG_PAN_ID=0xFFFF
Zigbee工作在2.4
GHz,在2.4
GHz上定義了16個信道,即11~26號信道,以上是工作在25號信道上的。當需要修改信道時,只需要將所需信道的注釋符“//
”去掉,將原來使用的信道注釋掉。
當網絡PANID設置為0xFFFF時,即協(xié)調器建立網絡時將在0x0000~0xFFFF之間隨機選擇一個數(shù)作為網絡的PANID。如果網絡的PANID為0x0000~0xFFFF之間指定的一個數(shù),則協(xié)調器建立網絡時將會以選定的PANID作為網絡PANID建立網絡。例如:
【示例6-1】f8wConfig.cfg
//網絡PANID的設置
-DZDAPP_CONFIG_PAN_ID=0x1234
示例6-1中設定網絡PANID為0x1234,那么協(xié)調器建立網絡后,將會選擇0x1234作為網絡PANID。
2.
f8wCoord.cfg文件
f8wCoord.cfg文件是Zstack協(xié)議棧協(xié)調器設備類型配置文件,其功能是將程序編譯成具有協(xié)調器和路由器的雙重功能(這是因為協(xié)調器需要同時具有網絡建立和路由器的功能),其代碼如示例6-2所示。
【示例6-2】f8wCoord.cfg
/*協(xié)調器設置*/
//協(xié)調器功能
-DZDO_COORDINATOR
//路由器功能
-DRTR_NWK
3.
f8wRouter.cfg文件
f8wRouter.cfg文件為路由器配置文件,此文件將程序編譯成具有路由器的功能,其代碼如示例6-3所示。
【示例6-3】f8wRouter.cfg
/*路由器設置*/
-DRTR_NWK
4.
f8wEndev.cfg文件
此文件為終端節(jié)點的配置文件,在此文件中既沒有編譯協(xié)調器的功能也沒有編譯路由器的功能,因此,此文件一般不需要配置。
Profile對應Zigbee軟件架構中的應用程序框架AF層,其結構如圖6-9所示。Profile文件夾下面包含兩個文件:AF.c和AF.h。
AF層提供應用支持子層APS到應用層的接口,AF層主要提供兩種功能:端點的管理和數(shù)據(jù)的發(fā)送和接收。6.6Profile層分析
圖6-9Profile文件
6.6.1端點的管理
在Zigbee協(xié)議中每個設備都被看作一個節(jié)點,每個節(jié)點都有物理地址(長地址)和網絡地址(短地址),長地址或短地址用來作為其他節(jié)點發(fā)送數(shù)據(jù)的目的地址。另外,每一個節(jié)點都有241個端點,其中端點0預留,端點1~240被應用層分配,每個端點是可尋址的。端點的主要作用可以總結為以下兩個方面。
數(shù)據(jù)的發(fā)送和接收:當一個設備發(fā)送數(shù)據(jù)時,必須指定發(fā)送目的節(jié)點的長地址或短地址以及端點來進行數(shù)據(jù)的發(fā)送和接收,并且發(fā)送方和接收方所使用的端點號必須一致。綁定:如果設備之間需要綁定,那么在Zigbee的網絡層必須注冊一個或者多個端點來進行數(shù)據(jù)的發(fā)送和接收以及綁定表的建立。
端點的實現(xiàn)由端點描述符來完成,每一個端點描述符由一個結構體來實現(xiàn),在端點描述符中又包含了一個簡單描述符,它們的定義在AF.h中,具體講解如下。
1.端點描述符
節(jié)點中的每一個端點都需要一個端點描述符,此端點描述符結構體定義在AF.h文件中,如下所示。
【結構體6-1】endPointDesc_t
typedefstruct
{
byteendPoint;
byte*task_id;
SimpleDescriptionFormat_t*simpleDesc;
afNetworkLatencyReq_tlatencyReq;
}endPointDesc_t;
其中,endPointDesc_t結構體中每個成員所代表的含義如表6-4所示。
表6-4endPointDesc_t結構體成員
2.簡單描述符
每一個端點必有一個Zigbee簡單描述符,其他設備通過查詢這個端點的簡單描述符來獲得設備的一些信息,端點的簡單描述符結構體在AF.h文件中定義。
【結構體6-2】SimpleDescriptionFormat_t
typedefstruct
{
byteEndPoint;
uint16AppProfId;
uint16AppDeviceId;
byteAppDevVer:4;
byteReserved:4;
byteAppNumInClusters;
cId_t*pAppInClusterList;
byteAppNumOutClusters;
cId_t*pAppOutClusterList;
}SimpleDescriptionFormat_t;
其中,SimpleDescriptionFormat_t結構體中每個成員所代表的含義如表6-5所示。
表6-5SimpleDescriptionFormat_t結構體成員含義在實際數(shù)據(jù)收發(fā)的過程中,參與通信的兩個設備之間簡單描述符的輸入/輸出簇要相對應,即發(fā)送方的輸出簇對應接收方的輸入簇。例如,在Zstack官方的例程SampleAPP中,發(fā)送方所用的輸入/輸出簇都為SampleApp_ClusterList[],具體如示例6-4所示。
【示例6-4】收發(fā)雙方的輸入/輸出簇
constcId_t
SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS]=
{
SAMPLEAPP_PERIODIC_CLUSTERID,
SAMPLEAPP_FLASH_CLUSTERID
};
3.端點的注冊
在端點配置成功后,需要在AF層注冊端點,用到的函數(shù)是afRegister(),此函數(shù)在AF.c文件中定義,應用層將調用此函數(shù)注冊一個新的端點到AF層,其函數(shù)原型為:
【函數(shù)6-8】afRegister
afStatus_tafRegister(endPointDesc_t*epDesc)。
參數(shù)描述:epDesc—指向端點描述符的指針。
返回值:afStatus_t—如果注冊成功則返回ZSuccess,否則返回ZcomDef.h中定義的錯誤。
6.6.2數(shù)據(jù)的發(fā)送和接收
Zstack協(xié)議棧數(shù)據(jù)的發(fā)送和接收是通過數(shù)據(jù)發(fā)送和接收API來實現(xiàn)的,數(shù)據(jù)發(fā)送和接收的API在AF層定義。
1.數(shù)據(jù)的發(fā)送
數(shù)據(jù)的發(fā)送只要通過調用數(shù)據(jù)發(fā)送函數(shù)即可實現(xiàn),數(shù)據(jù)發(fā)送函數(shù)為AF_DataRequest(),此函數(shù)在AF.c文件中定義,數(shù)據(jù)發(fā)送函數(shù)原型為:
【函數(shù)6-9】AF_DataRequest()
afStatus_tAF_DataRequest
(
afAddrType_t*dstAddr,
endPointDesc_t*srcEP,
uint16cID,
uint16len,
uint8*buf,
uint8*transID,
uint8options,
uint8radius
);
各參數(shù)描述如下:
destAddr:指向發(fā)送目的的地址指針,地址類型為一個結構體。
srcEP:指向目的端點的端點描述符指針。
cID:發(fā)送端點的輸出簇ID。
len:發(fā)送字節(jié)數(shù)。
buf:指向發(fā)送數(shù)據(jù)緩存的指針。
transID:發(fā)送序列號指針,如果消息緩存發(fā)送,這個序列號將增加1。
options:發(fā)送選項,options的詳細配置如表6-6所示。其中options可以由表6-6中的一項或幾項相或得到。
radius:最大條數(shù)半徑。
表6-6options選項
返回值是一個afStatus_t類型的數(shù)據(jù),發(fā)送成功將返回“Zsuccess”,發(fā)送失敗將返回ZcomDef.h中定義的“Errors”。
當設備要發(fā)送數(shù)據(jù)時,在應用層直接調用此函數(shù)即可,發(fā)送信息代碼如示例6-5所示。
【示例6-5】發(fā)送信息
voidMySendtest_SendPeriodicMessage(void)
{//發(fā)送的數(shù)據(jù)
chartheMessageData[]="LED1";
if(AF_DataRequest(//發(fā)送目的地址
&MySendtest_Periodic_DstAddr,
//發(fā)送的端點描述符
&MySendtest_epDesc,
//簇ID號
MySendtest_PERIODIC_CLUSTERID,
//發(fā)送的字節(jié)長度
(uint16)osal_strlen(theMessageData)+1,
//發(fā)送的數(shù)據(jù)
(uint8*)theMessageData,
//發(fā)送的數(shù)據(jù)ID序號
&MyfirstAppCoordManage_TransID,
//設置路由發(fā)現(xiàn)
AF_DISCV_ROUTE,
//設置路由域
AF_DEFAULT_RADIUS)==ZSUCCESS)
{
}
else
{
}
}
2.發(fā)送數(shù)據(jù)的目的地址
發(fā)送函數(shù)AF_DataRequest()中的第一個參數(shù)是發(fā)送目的地址的信息,目的地址的信息為一個結構體,此結構體在AF.h中定義。
【結構體6-3】afAddrType_t
typedefstruct
{
union
{
uint16shortAddr;
ZLongAddr_textAddr;
}addr;
afAddrMode_taddrMode;
byteendPoint;
uint16panId;
}afAddrType_t;
其中,結構體afAddrType_t中有四個成員,每個成員所代表的含義如表6-7所示。
表6-7afAddrType_t結構體成員其中,addrMode被定義為枚舉類型afAddrMode_t,afAddrMode_t成員定義了發(fā)送信息的四種地址模式,afAddrMode_t在AF.h中定義。
【枚舉6-1】afAddrMode_t
typedefenum
{//間接尋址
afAddrNotPresent=AddrNotPresent,
//單點尋址,指定短地址
afAddr16Bit=Addr16Bit,
//單點尋址,指定長地址
afAddr64Bit=Addr64Bit,
//組尋址
afAddrGroup=AddrGroup,
//廣播尋址
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版養(yǎng)老院入住后法律援助與權益維護合同3篇
- 2025版上市公司員工薪酬協(xié)議書范本3篇
- 2025年食品行業(yè)電商平臺廣告監(jiān)測服務合同3篇
- 2025版健身房運營管理權及設備租賃合同4篇
- 2025年高科技企業(yè)實習生保密協(xié)議與研發(fā)成果歸屬合同3篇
- 2025年度煤礦井巷工程勞務派遣與人員培訓承包合同范本4篇
- 2025年度個人借款合同電子化管理規(guī)范4篇
- 2025版淋浴房防水保溫材料供應與施工合同4篇
- 2025版事故責任賠償協(xié)議范本:交通事故賠償15篇
- 2025年高端皮鞋定制加工合同范本3篇
- 無人化農場項目可行性研究報告
- 《如何存款最合算》課件
- 社區(qū)團支部工作計劃
- 拖欠工程款上訪信范文
- 《wifi協(xié)議文庫》課件
- 中華人民共和國職業(yè)分類大典是(專業(yè)職業(yè)分類明細)
- 2025年新高考語文復習 文言文速讀技巧 考情分析及備考策略
- 2024年??谑羞x調生考試(行政職業(yè)能力測驗)綜合能力測試題及答案1套
- 一年級下冊數(shù)學口算題卡打印
- 2024年中科院心理咨詢師新教材各單元考試題庫大全-下(多選題部分)
- 真人cs基于信號發(fā)射的激光武器設計
評論
0/150
提交評論