殷松瑜
摘 要:文中基于ZigBee2007協議棧設計開發了一個應用層ZigBee協議,實現了協調器和終端模塊之間雙向傳輸預設格式的數據。ZigBee協議通過對無線模塊內的各種硬件資源標準化編碼,實現了使用統一的方法來訪問控制模塊內部的相關資源。串口控制協議提供了對模塊有效的控制訪問途徑,用戶設備可通過統一的串口協議對無線通信進行控制,訪問相關設備,傳遞各種測量控制數據等。
關鍵詞:紫蜂;協議棧;串口通信;傳感器
中圖分類號:TP39;TN925 文獻標識碼:A 文章編號:2095-1302(2017)10-00-05
0 引 言
ZigBee技術是一種近距離,擁有低復雜度、低功耗、低速率、低成本的雙向無線通信技術,主要適合短距離無線通信、組網、自動控制和遠程控制等領域,同時還可嵌入各種設備中。ZigBee協議是專用于ZigBee網絡的通信協議,通過好的算法能最大限度節省網絡中的能量,可接入大量節點,具有高容錯性,強魯棒性。由傳感器和ZigBee系統組成的ZigBee無線傳感器網絡可自動采集、分析和處理各個節點的數據,同時,ZigBee技術具有很強的網絡擴展能力,適合于各種自動組網領域,具有廣闊的應用領域和較高的研究價值[1]。ZigBee管理系統通信模型如圖1所示。
文中ZigBee應用層協議的預期目標是能夠在協調器和終端模塊之間進行雙向傳遞數據,實驗過程參考了北京賽佰特科技有限公司的相關設備資料。實驗環境的硬件采用ZigBee(CC2530)模塊(4個),ZigBee下載調試板,USB仿真器,PC機。軟件采用IAR Embedded Workbench for MCS-51,ZigBee2007協議棧ZStack-2.3.0-1.4.0。
1 Z-Stack協議棧
本文以Z-Stack協議棧自帶的SampleApp樣例作為模板,SampleApp實現了協調器自動組建星形網,節點設備申請加入網絡后兩者建立無線通信過程。協調器終端節點之間數據傳送方式主要為周期性定時自動發送消息和通過按鍵事件觸發傳送數據。本文協議實現采用第一種數據傳送方式,即周期定時自動發送信息。
2 相關通信協議
傳感器串口通信協議見表1所列[2]。
其中,SOF固定為0xEE 0xCC,標志一幀的開始,SensorType見傳感器說明,SensorId固定為0x01,CmdId固定為0x01,Data為6 B傳感器數據域,見傳感器說明,ExtenData為2 B 擴展數據域,END固定為0xFF,標志一幀的結束。一幀數據為定長16 B。傳感器說明(測量型)見表2所列,傳感器說明(控制型)見表3所列。
ZigBee通信協議如下所示:
uint8DataHeadH; //包頭0xEE
uint8DataDeadL; //包頭0xCC
uint8NetID; //所屬網絡標識00(zigbee) 01(藍牙)02(WiFi)
03(IPv6)
uint8NodeAddress[4]; //節點網絡地址
uint8FamilyAddress[4]; //根節點網絡地址
uint8NodeState; //節點狀態
uint8NodeChannel; //ZigBee物理信道(預留,固定為0x0B)
uint8ConnectPort; //ZigBee ENDPOINT ID
uint8SensorType; //傳感器類型編號
uint8SensorID; //相同類型傳感器設備號
uint8SensorCMD; //節點命令序號
uint8 Sensordata1; //節點數據1
uint8 Sensordata2; //節點數據2
uint8 Sensordata3; //節點數據3
uint8 Sensordata4; //節點數據4
uint8 Sensordata5; //節點數據5
uint8 Sensordata6; //節點數據6
uint8 Resv1; //保留字節1
uint8 Resv2; //保留字節2
uint8DataEnd; //節點包尾0xFF
其中,一幀數據為定長26 B。
3 ZigBee通信協議功能實現代碼
ZigBee協議實現代碼按照數據傳輸方向和發送接受節點不同,可分為6個不同的數據傳送過程,如圖2所示。其中,過程1表示傳感器通過串口把測量數據傳送給終端節點;過程2表示終端節點通過串口把接收的控制數據傳送給傳感器;過程3表示協調器通過無線射頻把接收的控制數據傳送給終端節點;過程4表示終端節點通過無線射頻把傳感器測量數據傳送給協調器;過程5表示上位機通過串口把控制數據傳送給協調器;過程6表示協調器通過串口把接收的測量數據傳送給上位機。
為了實現ZigBee通信協議傳輸數據,在協議實現代碼中添加終端與協調器通信相關的消息處理函數,在SampleApp.c文件中進行修改。
(1)定義所屬網絡標識
#define ZigBee 0;// 所屬網絡標識
(2)添加自定義的應用程序命令號:
constcId_tSampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] =
{ SAMPLEAPP_PERIODIC_CLUSTERID,//發給協調器endprint
SAMPLEAPP_CTRL_CLUSTERID //發給終端節點
};
(3)由于協議棧串口通信過程現在正在MT層實現處理,所以使用ZigBee串口通信要在編譯選項里加入MT層支持ZAPP_P1:
#if defined (ZAPP_P1)
MT_UartRegisterTaskID(SampleApp_TaskID);//注冊任務優先級
MT_UartZAppBufferLengthRegister(100);//注冊緩存區長度
#end if
(4)當設備加入到網絡后,其設備狀態就會發生變化,對所有任務觸發ZDO_STATE_CHANGE事件,開啟一個定時器。定時時間到,觸發廣播Periodic消息事件,相應任務為SampleApp_TaskID,事件處理函數處理SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,調用函數SampleApp_SendPeriodicMessage()來周期性自動發送信息。
(5)ZigBee協議功能實現代碼中添加與協調器終端相互通信相關的消息處理函數。
SampleApp_ProcessEvent()事件處理函數代碼如下:
/* 根據不同的事件調用相應的事件處理函數 */
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{ afIncomingMSGPacket_t *MSGpkt;//指向接收消息結構體的指針
(void)task_id; // 任務優先級由OSAL分配
if ( events & SYS_EVENT_MSG )
{//從消息隊列接收消息,其中包含接收到的無線數據包的指針
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{switch ( MSGpkt->hdr.event )//對接收的事件進行判斷
{case AF_INCOMING_MSG_CMD://接收無線數據
SampleApp_MessageMSGCB(MSGpkt);//接收消息處理函數
break;
#if defined (ZAPP_P1)
case SPI_INCOMING_ZAPP_DATA://接收到串口數據
SampleApp_ProcessMTMessage(MSGpkt);//監控調試層串口消息處理函數
MT_UartAppFlowControl (MT_UART_ZAPP_RX_READY);//串口流控制
break;
#end if
case ZDO_STATE_CHANGE://節點設備類型發生變化
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); //讀取節點設備類型
if ( (SampleApp_NwkState == DEV_ZB_COORD)//協調器
|| (SampleApp_NwkState == DEV_ROUTER)//型路由器
|| (SampleApp_NwkState == DEV_END_DEVICE) )//終端節點
{HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);//LED_1點亮
if(SampleApp_NwkState == DEV_ZB_COORD) //設備類型協調器
{//周期定時發送消息
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_COORD_AUTO_SEND_MSG_EVT,
COORD_AUTO_MSG_TIMEOUT);
} }
else
……
}
//處理完接收的消息,需釋放消息占用的堆內存,防止內存泄漏
osal_msg_deallocate( (uint8 *)MSGpkt );
……
}
//定時器當預設時間到達之后設置周期性消息發送事件
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{SampleApp_SendPeriodicMessage();// 定時發送周期性消息
// 設置發送消息時間為固定周期再附加隨機時間延遲,防止訪問碰撞沖突
osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
……
}/*協調器自動發送消息事件*/
if ( events & SAMPLEAPP_COORD_AUTO_SEND_MSG_EVT )
{ osal_start_timerEx(SampleApp_TaskID,SAMPLEAPP_COORD_AUTO_SEND_MSG_EVT,COORD_AUTO_MSG_TIMEOUT);endprint
SampleApp_atuo_send_msg();//自動發送信息
……
}
……
}
SampleApp_MessageMSGCB()接收消息處理函數代碼如下:
/* 對接收到的消息調用相應的消息處理函數 */
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{ switch ( pkt->clusterId )//判斷發給不同應用領域特定對象的命令
{ case SAMPLEAPP_PERIODIC_CLUSTERID://發給協調器
……
SampleApp_ProcessAFMessage(pkt);//調用應用層消息處理函數
break;
case SAMPLEAPP_CTRL_CLUSTERID://發給終端節點
……
SampleApp_ProcessCtrMessage(pkt);//調用傳感器控制消息處理函數
break; }
}
SampleApp_ProcessMTMessage()監控調試層串口通信處理函數代碼如下:
/*實現協調器通過無線信道接收終端節點16 B傳感器數據包后,提取出傳感器測量數據,構造ZigBee通信協議數據包,再通過串口向上位機發送測量數據;協調器從串口接收上位機發送的ZigBee協議格式數據包,數據包內容是傳感器控制數據,通過無線信道發送給相應的終端節點*/
void SampleApp_ProcessMTMessage( afIncomingMSGPacket_t *pckt )
{ uint8 len;//數據包長度
uint16 FamilyAddr;//根節點16位短地址
unsigned char * buf = ((unsigned char *)pckt+2);//接受 應用層發送的消息
unsigned char data[16];//存放終端節點發送給協調器消息的發送緩沖區
len = pckt->hdr.status; //接收的消息長度
unsigned char data_buf[26]; //發送給協調器消息的發送緩沖區
osal_memcpy(data_buf,buf,26); //復制應用層消息到協調器消息的緩沖區
if(SampleApp_NwkState != DEV_ZB_COORD){// 終端節點接收串口傳來的傳感器數據
//檢驗傳感器數據包的長度,包頭,包尾是否正確
if((len == 14)&&(buf[0]==0xEE)&&(buf[1]==0xCC)&&(buf[13]==0xFF)){
osal_memcpy(data,buf,14); //獲取傳感器的數據
FamilyAddr=NLME_GetCoordShortAddr();//獲取協調器的16位地址
data[14]=FamilyAddr>>8; //協調器16位短地址的低8位
data[15]=FamilyAddr; //協調器16位短地址的高8位
len = 16; //發送數據包的長度
//設置單播模式和設備16位短地址
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
//通信節點端口號
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
//發送目的地是協調器地址0x0000
SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0000;
//Z-Stack協議棧提供的數據發送函數AF_DataRequest()
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr,
//目的地地址
&SampleApp_epDesc,//設備節點描述符
SAMPLEAPP_PERIODIC_CLUSTERID,//周期自動發送消息命令
len,//數據包長度
data,//數據緩沖區指針
&SampleApp_TransID,//數據發送序列號
AF_DISCV_ROUTE,//數據發送路由
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{//向協調器周期性發送消息成功}
else
{//發生錯誤發送消息不成功}
HalLedBlink( HAL_LED_2, 2, 50, (1000 / 4) );
} }
//協調器接受到從串口傳送過來的上位機控制數據
if(SampleApp_NwkState == DEV_ZB_COORD)
{//檢驗控制數據包的長度,包頭,所屬網絡標識,包尾是否正確
if((len== 26)&&(buf[0]==0xEE)&&(buf[1]==0xCC)&&(buf[2]==0x0)&&(buf[25]==0xFF))endprint
{ SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
//根據傳送傳感器數據的終端節點地址反向確定控制消息發送的目的地地址
SampleApp_Periodic_DstAddr.addr.shortAddr = BUILD_UINT16(buf[6], buf[5]);
if (AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,//傳送傳感器控制數據簇命令
SAMPLEAPP_CTRL_CLUSTERID,len,buf,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{//向終端節點周期性發送消息成功}
else
{ //發生錯誤發送消息不成功}
HalLedBlink( HAL_LED_2, 2, 50, (1000 / 4) );} }}
SampleApp_ProcessAFMessage()應用層消息處理函數代碼如下:
/*協調器通過無線信道接受終端節點16 B傳感器數據包后,從中提取出傳感器測量數據,構造ZigBee通信協議數據包,再通過串口向上位機傳送測量數據*/
void SampleApp_ProcessAFMessage( afIncomingMSGPacket_t *pckt )
{unsigned char buffer[16]={0x00};//接受緩沖區
int i=0;unsigned char uartbuf[26]={0x00};//串口發送緩沖區
osal_memcpy(buffer, pckt->cmd.Data, 16);//接受到消息數據復制到接受緩沖區
uartbuf[0]=0xEE;//包頭0xEE
uartbuf[1]=0xCC;//包頭0xCC
uartbuf[2]=ZigBee; //所屬網絡標識00(ZigBee)
//發送消息的終端節點的源地址(16位短地址)高8位
uartbuf[5]=HI_UINT16(pckt->srcAddr.addr.shortAddr);
//發送消息的終端節點的源地址(16位地址)低8位
uartbuf[6]=LO_UINT16(pckt->srcAddr.addr.shortAddr);
uartbuf[9]=buffer[14];//根節點16位短地址的高8位
uartbuf[10]=buffer[15];//根節點16位短地址的低8位
uartbuf[11]=0X01; //節點狀態在線(01)
uartbuf[12]=0X0B;//ZigBee物理信道(預留,固定為0x0B)
uartbuf[13]=pckt->endPoint; //ZigBee通信節點的對應端點號
//傳感器測量數據復制到ZigBee通信協議數據發送緩沖區相對應的位置
for(i=14;i<26;i++)
{uartbuf[i]=buffer[i-12];}
//協調器通過串口向上位機傳送ZigBee通信協議數據包
HalUARTWrite(0,uartbuf,26);
}
SampleApp_ProcessCtrMessage()傳感器控制消息處理函數代碼如下:
/*終端節點通過無線信道接受協調器26 B數據包后,提取出控制型傳感器相關數據14 B,構造串口通信協議數據包,在通過串口向傳感器傳送控制數據,完成控制任務。*/
void SampleApp_ProcessCtrMessage(afIncomingMSGPacket_t *pckt )
{unsigned char uartbuf[14];// //構造ZigBee通信協議數據包長度26 B
uartbuf[0]=0xEE;//包頭0xEE
uartbuf[1]=0xCC; //包頭0xCC
uartbuf[2]=pckt->cmd.Data[14];//傳感器類型編號
uartbuf[3]=pckt->cmd.Data[15];//相同類型傳感器設備號
uartbuf[4]=pckt->cmd.Data[16];//節點命令序號
uartbuf[5]=pckt->cmd.Data[17];//節點數據1
uartbuf[6]=pckt->cmd.Data[18];//節點數據2
uartbuf[7]=pckt->cmd.Data[19];//節點數據3
uartbuf[8]=pckt->cmd.Data[20]; //節點數據4
uartbuf[9]=pckt->cmd.Data[21];//節點數據5
uartbuf[10]=pckt->cmd.Data[22]; //節點數據6
uartbuf[11]=0x00;//保留字節1endprint
uartbuf[12]=0x00;//保留字節2
uartbuf[13]=0xFF; //節點包尾0xFF
HalLedBlink( HAL_LED_2, 2, 50, (1000 / 4) ); // LED燈閃爍指示接受完成狀態
HalUARTWrite(0,uartbuf,14);// 終端節點通過串口向傳感器傳輸控制數據包
}
SampleApp_atuo_send_msg()協調器自動發送消息函數代碼如下:
/*上位機構造26 B通信協議數據包,通過串口發給協調器,周期性自動向外發布消息*/
void SampleApp_atuo_send_msg()
{unsigned char uartbuf[26];//構造ZigBee通信協議數據包,長度26 B
osal_memset(uartbuf,0,sizeof(unsigned char)*26);//自動清除原來的舊數據
uartbuf[0]=0xEE;//包頭0xEE
uartbuf[1]=0xCC;//包頭0xCC
uartbuf[2]=ZigBee; //所屬網絡標識00(ZigBee)
uartbuf[11]=0x01; //節點狀態在線(01)
uartbuf[12]=0x0B; //ZigBee物理信道(預留,固定為0x0B)
uartbuf[25]=0xFF; //節點包尾0xFF
HalUARTWrite(0,uartbuf,26);// 上位機通過串口向協調器傳輸通信協議數據包
}
ZigBee協議運行結果如圖3所示。
4 結 語
實驗證明,該ZigBee應用層協議運行穩定可靠,能夠在協調器和終端模塊之間快速高效地雙向傳輸預定格式的數據內容,充分發揮了ZigBee強大的網絡擴展能力,可以運用到各種自動組網領域,具有很好的應用推廣前景。
參考文獻
[1]原羿,蘇鴻根.基于ZigBee技術的無線網絡應用研究[J].計算機應用與軟件,2004,21(6): 89-91.
[2]北京賽佰特科技有限公司.CBT 模塊通訊協議V1.2[Z].2014.
[3]吳清秀.基于ZigBee協議棧的網絡管理研究[J].物聯網技術,2016,6(7):66-67.
[4]楊諾,胡必玲,黃志煒.基于物聯網核心技術的智能考勤系統[J].物聯網技術,2016,6(10):85-89.
[5]查爽.基于ZigBee技術的無線傳感器網絡網關研究與實現[D].大連:大連理工大學,2007.
[6]王彤.基于Z-Stack協議棧的ZigBee網絡組網研究與實現[D].保定:河北大學,2012.
[7]賀東梅.基于ZigBee協議的無線通信網關的設計[J].物聯網技術,2017,7(1):45-47.
[8]吳清秀.基于ZigBee協議棧的PHY服務研究[J].物聯網技術,2015,5(6):44-45.endprint