1. 程式人生 > >ZIGBEEZ通過協議棧點對點通訊流程

ZIGBEEZ通過協議棧點對點通訊流程

通過ZigBee2007 的協議棧 Z-Stack-CC2530-2.3.0。

一.實現一個無線資料通訊時的一般步驟

1、組網:呼叫協議棧的組網函式、加入網路函式,實現網路的建立與節點的加入。

2、傳送:傳送節點呼叫協議棧的無線資料傳送函式,實現無線資料傳送。

3、接收:接收節點呼叫協議棧的無線資料接收函式,實現無線資料接收。 看起來是不是很簡單呢,是不是有動手試試的衝動。具體的例程講解在這裡就不說先了,在接下來的教程裡面會詳細地和大家一起討論 ZigBee 協議棧架構中每個層所包含的內容和功能及 Z-stack 的軟體架構。

二:關鍵字

CCM  - Counter with CBC-MAC (mode of operation) 

HAL   - Hardware Abstraction Layer       (硬體抽象層)

PAN   - Personal Area Network          (個人區域網)

RF      - Radio Frequency                (射頻)

RSSI  - Received Signal Strength Indicator   (接收訊號強度指示)

三:協議的結構

-Hardware layer

放在最底,實現資料傳輸的基礎。

-Hardware Abstraction layer

提供了一種介面來訪問 TIMER,GPIO,UART,ADC 等。這些介面都通過相應的函式進行實現。

-Basic RF layer

為雙向無線傳輸提供一種簡單的協議。

-Application layer

使用者應用層,它相當於使用者使用 Basic RF 層和 HAL 的介面,也就是說我們通過在 Application layer 就可以使用到封裝好的 Basic RF 和 HAL 的函式。

四:Basic RF layer 簡介:

Basic RF 由 TI 公司提供,它包含了 IEEE 802.15.4 標準的資料包的收發功能但並沒有使用到協議棧,它僅僅是是讓兩個結點進行簡單的通訊,也就是說Basic RF 僅僅是包含著 IEEE 802.15.4 標準的一小部分而已。其主要特點有:

1、不會自動加入協議、也不會自動掃描其他節點也沒有組網指示燈(LED3)。

2、沒有協議棧裡面所說的協調器、路由器或者終端的區分,節點的地位都 是相等的。

3、沒有自動重發的功能。

-要理解掌握 Basic RF ,通過這個協議能夠進行資料的傳送和接收。

五:Basic RF 的工作過程:啟動、發射、接收 。

1、啟動 :



/*1、建立一個 basicRfCfg_t 的資料結構,並初始化其中的成員,在 basic_rf.h 程式碼中可以找到  */
 typedef struct {   
uint16 myAddr;               //16 位的短地址(就是節點的地址)   
uint16 panId;                //節點的 PAN ID   
uint8 channel;               //RF 通道(必須在 11-26 之間)   
uint8 ackRequest;            //目標確認就置 true   
#ifdef SECURITY_CCM          //是否加密,預定義裡取消了加密   
uint8* securityKey;       
uint8* securityNonce; 
       #endif 
    } basicRfCfg_t; 


/*2.呼叫 basicRfInit()函式進行協議的初始化,在 basic_rf.c 程式碼中可以找到 */

   uint8 basicRfInit(basicRfCfg_t* pRfConfig) ;

/*函式功能:對 Basic RF 的資料結構初始化,設定模組的傳輸通道,短地址,PAD ID。*/

2、傳送

/*
1. 建立一個 buffer,把 payload 放入其中。Payload 最大為 103 個位元組.

2. 呼叫 basicRfSendPacket()函式傳送,並檢視其返回值 。
在 basic_rf.c 中可以找到 :
*/

uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length) ;

/*
destAddr 目的短地址 
pPayload 指向傳送緩衝區的指標 
length 傳送資料長度 
函式功能:給目的短地址傳送指定長度的資料,傳送成功剛返回 SUCCESS, 失敗則返回 FAILED 
*/

3、接收

/*
1、 上層通過 basicRfPacketIsReady()函式來檢查是否收到一個 新資料包 。
在 basic_rf.c 中可以找到 :
*/

uint8 basicRfPacketIsReady(void);

//函式功能:檢查模組是否已經可以接收下一個資料,如果準備好剛返回 TRUE 。

/*
2、  呼叫 basicRfReceive()函式,把收到的資料複製到 buffer 中。
程式碼可以在 basic_rf.c 中可以找到 :
*/

 uint8 basicRfReceive(uint8* pRxData, uint8 len, int16* pRssi) ;

//函式功能:接收來自 Basic RF 層的資料包,併為所接收的資料和 RSSI 值 配緩衝區。

使用 Basic RF 實現無線傳輸只要學會使用這些函式就可以了。

六:例程講解

light_switch.c 程式碼詳解:

無論你看哪個實驗的程式碼,首先要找的就是 main 函式。從 main 函式開始:

(部分已經遮蔽的程式碼並未貼出,詳細的程式碼請看開啟工程)

1. void main(void) 
2. { 
3.   uint8 appMode = NONE;                   //不設定模組的模式 
4.  // Config basicRF 
     basicRfConfig.panId = PAN_ID;           //上面講的 Basic RF 的啟動中的 
5.   basicRfConfig.channel = RF_CHANNEL;     //初始化 basicRfCfg_t  
6.   basicRfConfig.ackRequest = TRUE;        //結構體的成員。
7.  
8.   #ifdef SECURITY_CCM                     //金鑰安全通訊,本例程不加密 
9.   basicRfConfig.securityKey = key; 
10.   #endif 
11.  
12.   // Initalise board peripherals         初始化外圍裝置 
13.   halBoardInit(); 
14.   halJoystickInit(); 
15.  
16.   // Initalise hal_rf  硬體抽象層的 rf 進行初始化 
17.   if(halRfInit()= =FAILED)  
18.   { 
19.     HAL_ASSERT(FALSE); 
20.   } 
21.   /***********根據 WeBee 學習底板配置**********/ 
22.   halLedClear(2);                       // 關 LED2 
23.   halLedClear(1);                       // 關 LED1 
24.  
25.  /******選擇性下載程式,傳送模組和接收模組******/ 
26.   appSwitch();                          //節點為按鍵 S1        P0_0 
27.   appLight();                           //節點為指示燈 LED1    P1_0 
28.   // Role is undefined. This code should not be reached 
29.   HAL_ASSERT(FALSE); 
30. } 

/*第 22~23 行:關閉 WeBee 底板的 LED2 和 LED1。halLedSet(x)置 1 是使燈 點亮,halLedClear(x)是使燈熄滅。 第 26~27 行:選擇其中的一行,並把另外一行遮蔽掉;這兩行重要啦,一個是實現發射按鍵資訊的功能,另一個是接收按鍵資訊並改變 LED 狀態的功能。分別為 Basic RF 發射和接收。不同模組在 燒寫程式時選擇不同功能。 
注意:程式會在 appSwitch();  或者 appLight();裡面迴圈或者等待,不會執行到第 29 行。 
*/

//接下來看看 appSwitch()函式,它是如何實現資料傳送的呢? 
 
1. static void appSwitch() 
2. { 
3.   #ifdef ASSY_EXP4618_CC2420               //液晶模組的定義,我們不用管他 
4.   halLcdClearLine(1); 
5.   halLcdWriteSymbol(HAL_LCD_SYMBOL_TX, 1); 
6.   #endif 
7.   // Initialize BasicRF                   8~11 Basic RF 啟動中的初始化
8.   basicRfConfig.myAddr = SWITCH_ADDR; 
9.   if(basicRfInit(&basicRfConfig)==FAILED){ 
10.   HAL_ASSERT(FALSE); 
11.   } 

12.   pTxData[0] = LIGHT_TOGGLE_CMD; 
13.   /* Basic RF 發射第 1 步,把要發射的資料或者命令放入一個數據 buffer,
      此處把燈狀態改變的命令 LIGHT_TOGGLE_CMD 放到 pTxData 中。*/

14.   basicRfReceiveOff();                    //接收遮蔽掉以降低功耗

15.   // Main loop                              程式進入死迴圈 
16.   while (TRUE)  
17.   { 
          /*halButtonPushed()是 halButton.c 裡面的,它的功能是:按鍵 S1
          有被按動時,就回返回true */
18.     if(halButtonPushed()==HAL_BUTTON_1)    //判斷按鍵 S1 被按下 

19.     { 
20.     basicRfSendPacket(LIGHT_ADDR,pTxData,APP_PAYLOAD_LENGTH); 
21.     //Basic RF 發射第 2 步,傳送資料

22.     halIntOff(); 
23.     halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global 

24.     // interrupt enable                     使能中斷 
25.     halIntOn(); 
26.     } 
27.    }
28. } 
 
 
//傳送的 appSwitch()講解完畢,接下來就到我們的接收 appLight()函數了 
1. static void appLight() 
2. { 
3.  /************************************************* 
4.    halLcdWriteLine(HAL_LCD_LINE_1, “Light”); 
5.    halLcdWriteLine(HAL_LCD_LINE_2, “Ready”); 
6.  ***************************************************/   

7.   #ifdef ASSY_EXP4618_CC2420                     // LCD 內容
8.   halLcdClearLine(1); 
9.   halLcdWriteSymbol(HAL_LCD_SYMBOL_RX, 1); 
10.   #endif 

11.   // Initialize BasicRF                         Basic RF 啟動中的初始化
12.   basicRfConfig.myAddr = LIGHT_ADDR; 
13.   if(basicRfInit(&basicRfConfig)==FAILED) { 
14.   HAL_ASSERT(FALSE); 
15.   } 

/*開啟無線接收功能,呼叫這個函式後模組一直會接收,除非再呼叫 basicRfReceiveOff()使它關閉接收*/
16.   basicRfReceiveOn(); 

17.   // Main loop                                  程式開始進行不斷掃描的迴圈 
18.   while (TRUE) 
19.    {
20.      while(!basicRfPacketIsReady());           //檢查是否接收上層資料
21.      if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)>0) { //判斷否接收到有資料 
22.      if(pRxData[0] == LIGHT_TOGGLE_CMD)  
23.      { 
24.       halLedToggle(1);                         //改變 Led1 的狀態
25.       } 
26.     } 
27.   } 
28. }