ZigBee開發(10)--組網實驗無線電點燈

關於ZigBee協議棧的介紹,先不寫,網上不少編程

無線點燈是你們入門 ZigBee一個很好的經典例子,裏面雖然尚未用到協議棧但它體現出來的數據發送、接收和用協議棧是差很少的,安全

並且 TI 公司的 Basic RF 的代碼容易看懂,若是把這個實驗掌握了(不要只是下載程序而後看試現象),到後面的協議棧就比較好入手了。數據結構

瞭解一下下面的關鍵字:app

CCM - Counter with CBC-MAC (mode of operation)
HAL - Hardware Abstraction Layer (硬件抽象層)
PAN - Personal Area Network (我的局域網)
RF - Radio Frequency (射頻)
RSSI - Received Signal Strength Indicator (接收信號強度指示
)
ide

實驗現象: 兩塊 WeBee 模塊通訊,一個模塊做發射,另一個模塊接收,發射模塊依次按下按鍵 S1,改變接收模塊 LED1 的亮滅的狀態。實現無線點燈功能。
模塊化

例程的源代碼 CC2530 BasicRF.rar TI 官網上下載的,用戶能夠去 TI 官網註冊並下載。下載連接:https://pan.baidu.com/s/1vXJ4eV25A_w0EslrhwXEFA函數

首先說明, TI 官網的程序的開發平臺是 TI 官網的開發板,硬件資料有所不一樣,因此要在 WeBee 板上實現無線點燈功能,必須對其代碼稍做修改。 oop

實驗代碼以前,仍是先來看看這些看到有點頭暈的文件夾吧!學習

文件夾結構大至以下,僅列出 CC2530 BasicRF 目錄一些相關的的文件夾:每一個文件夾裏面放着什麼東西,若是缺乏其中某些,咱們的燈仍是否能夠點亮呢?ui

咱們來一一探討:

docs 文件夾:
打開文件夾裏面僅有一個名爲 CC2530_Software_Examples PDF 文檔,文檔的主要內容是介紹 BasicRF 的特色、結構及使用,

若是讀者有 TI 的開發板的話閱讀這個文檔就能夠作 Basic RF 裏面的實驗了,從中咱們能夠知道,

裏面Basic RF 包含三個實驗例程: 無線點燈、傳輸質量檢測、譜分析應用。下面講解的內容中也有部份內容是從這個文檔中翻譯所得,是一份至關有價值的參考資料。
Ide 文件夾:

    打開文件夾後會有三個文件夾,及一個 cc2530_sw_examples.eww 工程,其中這個工程是上面說起的三個實驗例程工程的集合,

  固然也包含了咱們無線點燈的實驗工程!在 IAR 環境中打開,在 workspace 看到
Ide\Settings 文件夾:
  是在每一個基礎實驗的文件夾裏面都會有的,它主要保存有讀者本身的 IAR環境裏面的設置。
Ide\srf05_CC2530 文件夾:
  裏面放有三個工程, light_switch.ewwper_test.ewwspectrum_analyzer.eww若是讀者不習慣幾個工程集合在一塊兒看,也能夠在這裏直接打開你想要用的實驗工程。
Source 文件夾:
  打開文件夾裏面有 apps 文件夾和 components 文件夾
Source\apps 文件夾:
  存放 BasicRF 三個實驗的應用實現的源代碼
Source\components 文件夾:
  包含着 BasicRF 的應用程序使用不一樣組件的源代碼

 


打開實驗工程:
  打開文件夾 CC2530 BasicRF\ide\srf05_cc2530\iar 路徑裏面的工程light_switch.eww(無線點燈)。 咱們的實驗就是對它進行修改的。

  並點擊application light_switch.c 用戶的應用程序就是在裏面的了

2、 Basic RF layer 介紹及其工做過程:
在介紹 Basic RF 以前,來看看這個實驗例程設計的大致結構,如圖所示 BasicRF 例程的軟件設計框圖就如一座建築物,
Hardware layer
  放在最底,確定是你實現數據傳輸的基礎了。
Hardware Abstraction layer
  它提供了一種接口來訪問 TIMERGPIOUARTADC 等。這些接口都經過相應的函數進行實現。
Basic RF layer
  爲雙向無線傳輸提供一種簡單的協議

Application layer
  是用戶應用層,它至關於用戶使用 Basic RF 層和 HAL 的接口,也就是說咱們經過在 Application layer 就可使用到封裝好的 Basic RF HAL 的函數。

本例程的要求就是讀者理解掌握 Basic RF
Basic RF layer 簡介:
Basic RF TI 公司提供,它包含了 IEEE 802.15.4 標準的數據包的收發功能但並無使用到協議棧,

它僅僅是是讓兩個結點進行簡單的通訊,也就是說Basic RF 僅僅是包含着 IEEE 802.15.4 標準的一小部分而已。其主要特色有:
  1、不會自動加入協議、也不會自動掃描其餘節點也沒有組網指示燈(LED3)。
  2、沒有協議棧裏面所說的協調器、路由器或者終端的區分,節點的地位都是相等的。
  3、沒有自動重發的功能。
Basic RF layer 爲雙向無線通訊提供了一個簡單的協議,經過這個協議可以進行數據的發送和接收。

Basic RF 還提供了安全通訊所使用的 CCM-64 身份驗證 和 數 據 加 密 , 它 的 安 全 性 讀 者 可 以 通 過 在 工 程 文 件 裏 面 定 義SECURITY_CCM

      圖 3.8 註釋 SECURITY_CCM 

Project->Option 裏面就能夠選擇,本次實驗並非什麼高度機密,因此在 SECURITY_CCM 前面帶 了。

Basic RF 的工做過程:啓動、發射、接收 (請你們按照代碼走)
啓動
  1、確保外圍器件沒有問題
  2建立一個 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 //是否加密,預約義裏取消了加密118
    uint8* securityKey; uint8* securityNonce; #endif } basicRfCfg_t;

  3.調用 basicRfInit()函數進行協議的初始化,在 basic_rf.c 代碼中能夠找到

uint8 basicRfInit(basicRfCfg_t* pRfConfig)   /***函數功能: 對 Basic RF 的數據結構初始化,設置模塊的傳輸通道,短地址,PAD ID。**/

發送
  5. 建立一個 buffer,把 payload 放入其中。 Payload 最大爲 103 個字節
  6. 調用 basicRfSendPacket()函數發送,並查看其返回值 。basic_rf.c 中能夠找到

uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length) /**** destAddr 目的短地址 pPayload 指向發送緩衝區的指針 length 發送數據長度   函數功能: 給目的短地址發送指定長度的數據,發送成功剛返回 SUCCESS,失敗則返回 FAILED ******/

接收

  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 實現無線傳輸只要學會使用這些函數就能夠了 。

可是具體的實現過程遠沒有那麼簡單的,你們能夠到….\CC2530BasicRF\docs 裏面查看 CC2530_Software_Examples 中的 5.2.4 Basic RF operation這個章節的內容,

裏面詳細介紹了 Basic RF 的初始化過程、 Basic RF 的發射過程、 Basic RF 的接收過程,具體到每一個層的功能函數。

  WeBee 原本想將這部分的內容也詳細的和讀者們講解清楚,但後來再仔細考慮仍是不放上來了。由於它的具體實現過程你們看文檔的那個章節就能夠大概明白的了,

另外一方面,實驗例程的模塊化編程作得很好,你們只須要明白函數的做用,學會使用它就好了,至於它內部是怎麼樣一層一層的實現,咱們也不用太過關心。

3、 light_switch.c 代碼詳解:

不管你看哪一個實驗的代碼,首先要找的就是 main 函數。從 main 函數開始:(部分已經屏蔽的代碼並未貼出,詳細的代碼請看打開工程) 

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

2425 行: 關閉 WeBee 底板的 LED2 LED1halLedSet(x)1 是使燈點亮,halLedClear(x)是使燈熄滅。
第 30~31 行: 選擇其中的一行,並把另一行屏蔽掉;

        這兩行重要啦,一個是實現發射按鍵信息的功能,另外一個是接收按鍵信息並改變 LED狀態的功能。分別爲 Basic RF 發射和接收。不一樣模塊在燒寫程序時選擇不一樣功能。

注意: 程序會在 appSwitch(); 或者 appLight();裏面循環或者等待,不會執行到第 29 行。

  接下來看看 appSwitch()函數,它是如何實現數據發送的呢?

 1 static void appSwitch()  2 {  3     halLcdWriteLine(HAL_LCD_LINE_1, " W e B e e ");  4     halLcdWriteLine(HAL_LCD_LINE_2, " ZigBee CC2530 ");  5     halLcdWriteLine(HAL_LCD_LINE_4, " SWITCH ");  6     
 7 #ifdef ASSY_EXP4618_CC2420  8     halLcdClearLine(1);  9     halLcdWriteSymbol(HAL_LCD_SYMBOL_TX, 1); 10 #endif
11 
12 
13     // Initialize BasicRF
14     basicRfConfig.myAddr = SWITCH_ADDR; 15     if(basicRfInit(&basicRfConfig)==FAILED) { 16  HAL_ASSERT(FALSE); 17  } 18     
19     pTxData[0] = LIGHT_TOGGLE_CMD; 20 
21     // Keep Receiver off when not needed to save power
22  basicRfReceiveOff(); 23 
24     // Main loop
25     while (TRUE) { 26         //if( halJoystickPushed() )**********************by boo
27       if(halButtonPushed()==HAL_BUTTON_1)//**************by boo
28  { 29 
30  basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH); 31 
32             // Put MCU to sleep. It will wake up on joystick interrupt
33  halIntOff(); 34             halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global 35             // interrupt enable
36  halIntOn(); 37 
38  } 39  } 40 }

36 行: TI 學習板上的液晶模塊的定義,咱們不用管他
第 717 行: Basic RF 啓動中的初始化,就是上面所講的 Basic RF 啓動的第 3
19 行: Basic RF 發射第 1 步,把要發射的數據或者命令放入一個數據 buffer,此處把燈狀態改變的命令 LIGHT_TOGGLE_CMD 放到 pTxData 中。
第 22 行: 因爲模塊只須要發射,因此把接收屏蔽掉以下降功耗。
18 行: if(halButtonPushed()==HAL_BUTTON_1)判斷是否 S1 按下,函數halButtonPushed()halButton.c 裏面的,

    它的功能是:按鍵 S1 有被按 動 時 , 就 回 返 回 true , 則 進 入basicRfSendPacket(LIGHT_ADDR, pTxData,APP_PAYLOAD_LENGTH);
第 30 行: Basic RF 發射第 2 , 也是發送數據最關鍵的一步,函數功能在前面已經講述。

basicRfSendPacket(LIGHT_ADDR,pTxData,APP_PAYLOAD_LENGTH) /***
就是說:將 LIGHT_ADDR、 pTxData、APP_PAYLOAD_LENGTH 的 實 參 寫 出 來
就是basicRfSendPacket(0xBEEF ,pTxData[0] ,1 )
把字節長度爲 1 的命令,發送到地址 0xBEEF
****
*/


第 33~34 行: WeBee 開發板暫時尚未 joystick(多方向按鍵),不用理它先。

第 36 行: 使能中斷

  發送的 appSwitch()講解完畢,接下來就到咱們的接收 appLight()函數了

 1 static void appLight()  2 {  3 
 4     halLcdWriteLine(HAL_LCD_LINE_1, " W e B e e ");  5     halLcdWriteLine(HAL_LCD_LINE_2, " ZigBee CC2530 ");  6     halLcdWriteLine(HAL_LCD_LINE_4, " LIGHT ");  7 
 8 #ifdef ASSY_EXP4618_CC2420  9     halLcdClearLine(1); 10     halLcdWriteSymbol(HAL_LCD_SYMBOL_RX, 1); 11 #endif
12 
13     // Initialize BasicRF
14     basicRfConfig.myAddr = LIGHT_ADDR; 15     if(basicRfInit(&basicRfConfig)==FAILED) { 16  HAL_ASSERT(FALSE); 17  } 18  basicRfReceiveOn(); 19 
20     // Main loop
21     while (TRUE) { 22         while(!basicRfPacketIsReady()); 23 
24         if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)>0) { 25             if(pRxData[0] == LIGHT_TOGGLE_CMD) { 26                 halLedToggle(1); 27                 halLedToggle(2); 28                 halLedToggle(3); 29  } 30  } 31  } 32 }

第 4~6 行: LCD 內容暫時不用理它
1417行: Basic RF 啓動中的初始化,上面 Basic RF 啓動的第 3
18 行:函數 basicRfReceiveOn(),開啓無線接收功能,調用這個函數後模塊一直會接收,除非再調用 basicRfReceiveOff()使它關閉接收。
第 21 行:程序開始進行不斷掃描的循環
22行: Basic RF 接收的第 1 while(!basicRfPacketIsReady()) 檢查是否接收上層數據,
24 行 : Basic RF 接 收 的 第 2 if(basicRfReceive(pRxData,APP_PAYLOAD_LENGTH, NULL)>0)判斷否接收到有數據
215行: if(pRxData[0] == LIGHT_TOGGLE_CMD)判斷接收到的數據是否就是發送函數裏面的 LIGHT_TOGGLE_CMD 若是是,執行第 22
26~28 行: halLedToggle(1),改變 Led1,2,3 的狀態。


實驗操做:
  第一步:打開….\CC2530 BasicRF\ide 文件夾下面的工程 在 light_switch.c 裏面找到 main 函數,找到下面內容,把 appLight(); 註釋掉,下載到發射模塊。
  /************Select one and shield to another************/
    appSwitch(); //節點爲按鍵 S1 P0_0
    // appLight(); //節點爲指示燈 LED1 P1_0
  第二步:找到相同位置,此次把 appSwitch();註釋掉,下載到接收模塊。

125


  /************Select one and shield to another***********by boo*/
    //appSwitch(); //節點爲按鍵 S1 P0_0
    appLight(); //節點爲指示燈 LED1 P1_0
完成燒寫後上電,按下發射模塊的 S1 按鍵,能夠看到接收模塊的 LED1 被點亮。

 

上面咱們說到,這個實驗例程用的是TI官網的開發板,我們買的就可可能跟他們硬件鏈接不同

會出現按鍵和燈的引腳不匹配現象

引腳定義在srf05_soc文件夾下的hal_board.h文件中定義,根據本身板子的硬件連結進行修改便可

// SPI
#define HAL_BOARD_IO_SPI_MISO_PORT     1
#define HAL_BOARD_IO_SPI_MISO_PIN      7
#define HAL_BOARD_IO_SPI_MOSI_PORT     1
#define HAL_BOARD_IO_SPI_MOSI_PIN      6
#define HAL_BOARD_IO_SPI_CLK_PORT      1
#define HAL_BOARD_IO_SPI_CLK_PIN       5
#define HAL_BOARD_IO_EM_CS_PORT        1
#define HAL_BOARD_IO_EM_CS_PIN         4

// LCD
#define HAL_BOARD_IO_LCD_CS_PORT       1
#define HAL_BOARD_IO_LCD_CS_PIN        2
#define HAL_BOARD_IO_LCD_MODE_PORT     0
#define HAL_BOARD_IO_LCD_MODE_PIN      0

// LEDs
#define HAL_BOARD_IO_LED_1_PORT        1   // Green************LED1 by boo
#define HAL_BOARD_IO_LED_1_PIN         0
#define HAL_BOARD_IO_LED_2_PORT        1   // Red**************LED2 by boo
#define HAL_BOARD_IO_LED_2_PIN         1
#define HAL_BOARD_IO_LED_3_PORT        1   // Yellow
#define HAL_BOARD_IO_LED_3_PIN         4
#define HAL_BOARD_IO_LED_4_PORT        0   // Orange
#define HAL_BOARD_IO_LED_4_PIN         1


// Buttons
#define HAL_BOARD_IO_BTN_1_PORT        0   // Button S1
#define HAL_BOARD_IO_BTN_1_PIN         1

// Potmeter
#define HAL_POTMETER_ADC_PORT               0
#define HAL_POTMETER_ADC_CH                 7

// Joystick
#define HAL_BOARD_IO_JOYSTICK_ADC_PORT      0
#define HAL_BOARD_IO_JOYSTICK_ADC_PIN       6
#define HAL_BOARD_IO_JOY_MOVE_PORT          2
#define HAL_BOARD_IO_JOY_MOVE_PIN           0

// UART
#define HAL_BOARD_IO_UART_RTS_PORT          0
#define HAL_BOARD_IO_UART_RTS_PIN           5

搞定!!!

相關文章
相關標籤/搜索