王榮
摘要:Z-Stack是目前非常常用的ZigBee協(xié)議棧。如何基于Z-Stack開發(fā)出各種通信系統(tǒng)是現(xiàn)在的研究熱門。該文從一個典型的單播通信實驗出發(fā),給出了基于Z-Stack快速開發(fā)出數(shù)據(jù)采集無線通信的實現(xiàn)過程。文中給出了關(guān)鍵代碼片段的實現(xiàn),爭取以最簡練的方式剖析Z-Stack的無線數(shù)據(jù)采集開發(fā)流程。
關(guān)鍵詞:Z-Stack;協(xié)議棧;無線數(shù)據(jù)采集;快速開發(fā);ZigBee
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2015)17-0226-03
自從2007年TI公司宣布推出ZigBee的協(xié)議棧Z-Stack以來,已經(jīng)有8個年頭[1]。在此期間對于Z-Stack的開發(fā)研究層出不窮,各類期刊論文如雨后春筍般冒出??v觀各文獻(xiàn),大體分為兩類:第一類為設(shè)計類,主要介紹各種應(yīng)用系統(tǒng)的設(shè)計開發(fā),內(nèi)容多為框架結(jié)構(gòu)的介紹,很少涉及到實現(xiàn)過程;第二類為算法類,主要研究某一層次的通信算法優(yōu)化,難度較深,令不少學(xué)者望而卻步。正因為如此,本文立足于一個基本數(shù)據(jù)采集實驗,著重描述最細(xì)節(jié)的代碼實現(xiàn)過程,旨在用最深入淺出的方式為想要快速開發(fā)Z-Stack的讀者拋磚引玉。
1 系統(tǒng)框架結(jié)構(gòu)
1.1 系統(tǒng)功能
本實驗系統(tǒng)僅采用2個節(jié)點,節(jié)點芯片采用TI公司的無線射頻芯片CC2530。一個節(jié)點用作協(xié)調(diào)器,另一個為路由節(jié)點(也可以是終端節(jié)點,本文中這兩類角色不作功能上的區(qū)分)。協(xié)調(diào)器節(jié)點通過串口與電腦連接,接收到的電壓數(shù)據(jù)通過串口助手顯示到電腦屏幕上。路由節(jié)點主要負(fù)責(zé)電壓數(shù)據(jù)的采集,并在一定的時間間隔后周期性地將數(shù)據(jù)單播給協(xié)調(diào)器[2]。
1.2 系統(tǒng)硬件描述
本系統(tǒng)中的協(xié)調(diào)器和路由節(jié)點采用相同的結(jié)構(gòu),兼容TI公司的評估板。本實驗主要用到以下3個模塊:串口模塊,主控模塊和電源模塊。
1)串口模塊。串口模塊采用CC2530單片機異步UART模式的UART0接口,通過MAX232電壓轉(zhuǎn)換芯片和RS232標(biāo)準(zhǔn)接口相連。主要用于協(xié)調(diào)器通過串口線(也可以是USB轉(zhuǎn)串口線[3])和電腦串口助手之間的數(shù)據(jù)通信。
2)主控模塊。主控模塊包含了無線模塊,采用CC2530芯片。該芯片使用增強型8051內(nèi)核,如果開發(fā)者對8051單片機很熟悉的話,程序設(shè)計會很容易上手。除此之外,芯片內(nèi)部提供了一個IEEE 802.15.4兼容型無線收發(fā)器,該收發(fā)器為MCU提供了一個接口,可以用來發(fā)出命令、讀取狀態(tài)、確定無線設(shè)備事件的順序等。
3)電源模塊。電源模塊用于給CC2530芯片供電,典型工作電壓為3.3V,該電壓值隨著電池的使用時間增加略有下降,此電壓值為本實驗的主要采集數(shù)據(jù)對象。
2 系統(tǒng)軟件設(shè)計
本實驗系統(tǒng)采用的軟件開發(fā)平臺為IAR Embedded Workbench,版本為MCS-51 7.51A。Z-Stack版本為ZStack-CC2530-2.2.2-1.3.0[4]。注意:采用不同版本的Z-Stack對應(yīng)的IAR軟件版本也不同,如ZStack-CC2530-2.5.0推薦使用IAR 8.10版本,否則會出現(xiàn)編譯問題。
2.1 Z-Stack協(xié)議棧
Z-Stack是TI公司推出的ZigBee協(xié)議棧,是一個使用C語言編寫的軟件包。除了與無線通信有關(guān)的實現(xiàn)代碼外,它內(nèi)部還包含了一個簡易多任務(wù)操作系統(tǒng),稱為操作系統(tǒng)抽象層OSAL。用戶可以使用協(xié)議棧提供的API進行應(yīng)用程序的開發(fā),在開發(fā)過程中不必關(guān)心ZigBee協(xié)議的具體實現(xiàn)細(xì)節(jié)。Z-Stack采用任務(wù)輪詢的機制,如果有任務(wù)事件發(fā)生,OSAL會根據(jù)事件類型將其分配給能處理該事件的具體任務(wù),并對事件加以處理,然后進入下一次輪詢[5]。
2.2 Z-Stack無線收發(fā)程序的設(shè)計與實現(xiàn)
首先安裝好ZStack-CC2530-2.2.2-1.3.0,然后打開工程目錄。本次實驗基于SampleApp框架,找到SampleApp.eww文件,用IAR軟件打開。打開之后選中工程列表中的App文件夾,所有代碼都在SampleApp.c和SampleApp.h中實現(xiàn)。本文默認(rèn)讀者有Z-Stack協(xié)議棧開發(fā)的基礎(chǔ),對系統(tǒng)框架已經(jīng)有了一定了解,已經(jīng)掌握協(xié)議棧的串口收發(fā)功能。
2.2.1 目的地址的定義與初始化
本實驗中,數(shù)據(jù)是由路由節(jié)點采集,發(fā)送給協(xié)調(diào)器,因此可以采用單播的方式發(fā)送。首先定義一個目的地址的變量,然后對其進行單播方式的初始化,初始化位于void SampleApp_Init( uint8 task_id )函數(shù)。具體實現(xiàn)過程如下:
1)afAddrType_t DataCollect_DestAddr;
2)DataCollect_DestAddr.addrMode = (afAddrMode_t)Addr16Bit;
3)DataCollect_DestAddr.endPoint = SAMPLEAPP_ENDPOINT;
4)DataCollect_DestAddr.addr.shortAddr = 0x0000;
2.2.2 數(shù)據(jù)簇號的定義與初始化
定義一個新的簇ID號,作為本次采集數(shù)據(jù)的簇號,并將它加入簇列表初始化數(shù)組const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS]中。同時更改最大簇號(默認(rèn)是2,改為3)。
1.#define SAMPLEAPP_MAX_CLUSTERS 3
2.#define DATA_COLLECT_CLUSTERID 3
2.2.3 添加周期性事件
周期性事件用于電壓數(shù)據(jù)的采集,并將該數(shù)據(jù)周期性發(fā)送到協(xié)調(diào)器的過程。在本次實驗中,當(dāng)路由器節(jié)點加入網(wǎng)絡(luò)后,每隔2秒,路由節(jié)點會采集一次電壓值發(fā)送給協(xié)調(diào)器。因此,首先需要定義一個事件DATA_COLLECT_EVT完成周期數(shù)據(jù)采集,然后定義一個采集間隔變量DATA_COLLECT_PERIODIC_INTERVAL。
1)#define DATA_COLLECT_EVT 0x0002
2) #define DATA_COLLECT_PERIODIC_INTER
VAL 2000
定義好上述變量后,完善應(yīng)用層事件處理函數(shù)SampleApp_ProcessEvent( uint8 task_id, uint16 events )。
1)case ZDO_STATE_CHANGE:
2)SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
3)if (SampleApp_NwkState == DEV_ROUTER)
4){
5)osal_start_timerEx(SampleApp_TaskID,
6)DATA_COLLECT_EVT,
7)DATA_COLLECT_PERIODIC_INTERVAL); //每隔2秒,就啟動采集事件
8) }
9)break;
2.2.4 數(shù)據(jù)采集事件的實現(xiàn)
接下來實現(xiàn)數(shù)據(jù)采集事件,該事件需要在SampleApp_ProcessEvent( uint8 task_id, uint16 events )函數(shù)中添加并完善。在該事件中,主要有2個功能:電壓數(shù)據(jù)的采集和事件的周期性執(zhí)行,即每隔2秒觸發(fā)一次該自定義事件。
1)if ( events & DATA_COLLECT_EVT ) //數(shù)據(jù)采集事件的處理
2){
3)Voltage_Data_Collect(); //調(diào)用數(shù)據(jù)采集函數(shù)
4)osal_start_timerEx(SampleApp_TaskID,
5)DATA_COLLECT_EVT,
6)DATA_COLLECT_PERIODIC_INTERVAL);
7)return (events ^ DATA_COLLECT_EVT);
8)}
2.2.5 數(shù)據(jù)采集函數(shù)的實現(xiàn)
該函數(shù)調(diào)用讀取電壓值函數(shù)(實現(xiàn)過程見第6部分),經(jīng)過數(shù)據(jù)轉(zhuǎn)換后,調(diào)用AF_DataRequest()函數(shù)轉(zhuǎn)發(fā)數(shù)據(jù)包到協(xié)調(diào)器。其實現(xiàn)過程如下。
1)uint8 Collect_Data[10] = {0x20}; //用于保存電壓值的數(shù)組
2)void Voltage_Data_Collect( void )
3){
4)uint16 VoltageValue;
5)VoltageValue = ReadAdcCheckVdd(); //調(diào)用讀取電壓值函數(shù)
6)Collect_Data[0] = VoltageValue / 10000 + 0x30;
7) Collect_Data[1] = VoltageValue / 1000 % 10 + 0x30;
8)Collect_Data[2] = VoltageValue / 100 % 10 + 0x30;
9)Collect_Data[3] = VoltageValue / 10 % 10 + 0x30;
10)AF_DataRequest( &DataCollect_DestAddr, &SampleApp_epDesc,
11)DATA_COLLECT_CLUSTERID,
12)10,
13) Collect_Data, //用戶數(shù)據(jù),電壓值
14)&SampleApp_TransID,
15)AF_DISCV_ROUTE,
16)AF_DEFAULT_RADIUS );
17)}
2.2.6 讀取電壓值函數(shù)的實現(xiàn)
讀取電壓值的函數(shù)uint16 ReadAdcCheckVdd (void)比較容易實現(xiàn),配置好ADC相關(guān)寄存器就可以進行數(shù)據(jù)采集。該函數(shù)的實現(xiàn)過程如下。
1)uint16 value;
2)ADCIF = 0;
3)ADCCON3 = 0x0F;
4)while ( !ADCIF );
5)value = ADCL;
6)value |= ((uint16) ADCH) << 8;
7)return value;
2.2.7 數(shù)據(jù)的無線接收并串口顯示
無線數(shù)據(jù)的接收會觸發(fā)系統(tǒng)事件集中的AF_INCOMING_MSG_CMD事件,默認(rèn)會調(diào)用回調(diào)函數(shù)SampleApp_MessageMSGCB( MSGpkt )來執(zhí)行相應(yīng)的操作。因此,只需要完善該函數(shù)的內(nèi)容即可。定義數(shù)組變量Recv_Buf[16]來保存接收到的數(shù)據(jù)。
1)memcpy(Recv_Buf, pkt->cmd.Data, pkt->cmd.DataLength); //保存接收到的用戶數(shù)據(jù)
2)switch(pkt->clusterId)
3)case DATA_COLLECT_CLUSTERID:
4)HalUARTWrite(MT_UART_DEFAULT_PORT, "Voltage is: ", 12);
5)HalUARTWrite(MT_UART_DEFAULT_PORT, Recv_Buf, 1);
6)HalUARTWrite(MT_UART_DEFAULT_PORT, ".", 1);
7)HalUARTWrite(MT_UART_DEFAULT_PORT, &Recv_Buf[1], 1);
8)HalUARTWrite(MT_UART_DEFAULT_PORT, &Recv_Buf[2], 1);
9)HalUARTWrite(MT_UART_DEFAULT_PORT, &Recv_Buf[3], 1);
10)HalUARTWrite(MT_UART_DEFAULT_PORT, "V\n", 2);
11)break;
3 實驗結(jié)果
在所有的操作完成后,就可以通過串口助手查看實驗結(jié)果。把協(xié)調(diào)器和電腦用串口線連接,打開串口助手,設(shè)置波特率等參數(shù),可以觀察到采集到的數(shù)據(jù)。
圖1 串口顯示的電壓采集值
4 結(jié)語
本文從一個典型的無線數(shù)據(jù)采集實驗為例,剖析了Z-Stack快速開發(fā)的過程,并將代碼的實現(xiàn)以片段的形式展現(xiàn)出來,重點希望讀者能夠在看完本文的同時熟悉并實現(xiàn)最簡單的數(shù)據(jù)采集工程。由于在本文的描述中忽略了大量介紹性的陳述,因此需要讀者在之前就接觸過Z-Stack,熟悉各個接口函數(shù)的含義,了解系統(tǒng)的結(jié)構(gòu),這樣才能在正確的位置找到需要添加和更改的代碼,從而理解各段代碼的意義。
參考文獻(xiàn):
[1] 青島東合信息技術(shù)有限公司. Zigbee開發(fā)技術(shù)及實踐[M]. 西安:西安電子科技大學(xué)出版社,2014.
[2] 李延,張發(fā)生. 基于Z-Stack的室內(nèi)溫濕度檢測系統(tǒng)設(shè)計[J]. 軟件導(dǎo)刊,2015(2):94-96.
[3] 馬昆,姚竹亭. 基于Zigbee的溫度采集系統(tǒng)設(shè)計[J]. 電子技術(shù),2014:26-27.
[4] Texas Instruments. http:http://www.ti.com.cn.
[5] 李樹丹,張從松. 基于ZigBee協(xié)議的溫濕度檢測系統(tǒng)設(shè)計與實現(xiàn)[J]. 電子科技,2014-12(27):37-40.