「ZigBee模块」组网实验-无线点灯

ZigBee入门小实验——无线点灯

 

 

写在前面:无线点灯实验不涉及协议栈,只是对Basic RF的应用,但是其中关于数据收发的思想和协议栈类似,可以借鉴。这个代码和实验过程都是参考某教程的,然后有加上自己的理解......欢迎纠错(*^__^*) 

 

 

一、设备

两个ZigBee模块

一个方口USB线(这个只是供电用,要看自己模块用什么接口,不一定是方口的,用电池也行)

一个编译器

 

二、几个名词解释

CCM -Counter with CBC-MAC(mode of operation) 就知道和加密有关,具体不明白...有人能解释下吗?

HAL -Hardware Abstraction Layer (硬件抽象层)

PAN -Personal Area Network (个人局域网)

RF -Radio Frequency (射频)

RSSI -Received Signal Strength Indicator (接收信号强度指示)

 

 

三、关于Basic RF

 

  1. 在介绍Basic RF之前先看一下该实验例程的大体结构,图见下方

 

  ①Hardware layer 硬件层

 

  实现数据传输的基础

 

 

 

  ②Hardware Abstraction layer 硬件抽象层

 

  提供接口以访问TIMERGPIOUARTADC等,这些接口都通过函数实现。

 

 

 

  ③Basic RF

 

  为双向无线通信提供一种简单的协议

 

 

 

  ④Application layer 用户应用层

 

  它相当于一个接口,方便用户使用Basic RF层和HAL,就是说在Application层就可以使用封装好的Basic RFHAL函数

 

 

  2. Basic RF layer 简介

  Basic RF TI公司提供,包含IEEE 802.15.4标准的数据包收发功能但不使用协议栈,仅让两个结点进行简单通信。

  Basic RF layer 为双向无线通信提供了一个简单的协议,通过这个协议能够进行数据的发送和接收

 

 

四、Basic RF 工作过程分析

 

     Basic RF的工作过程分为三个部分:启动、发射、接收

 

启动:

 

  1. 确保外围器件没有问题

  2. 定义一个新的结构体类型,变量名为basicRfCfg_t,打开basic_rf.h可以找到该结构体。

 

typedef struct {
    uint16 myAddr;             //16位的短地址,就是结点的地址
    uint16 panId;              //结点的PAN ID
    uint8 channel;             //PF通道(必须在11-26之间)
    uint8 ackRequest;          //目标确认就置true
    #ifdef SECURITY_CCM        //是否加密,预定义里取消了加密
    uint8* securityKey;
    uint8* securityNonce;
    #endif
} basicRfCfg_t;

 

  3. 调用basicRfInit()函数进行协议的初始化,在basic_rf.h中可以找到函数声明

  Unit8 basicRfInit(basicRfCfg_t* pRfConfig);

  函数功能:对basicRfCfg_t进行初始化,设置模块的传输通道,短地址,PAN ID

 

 

发送:

 

  1. 创建一个buffer,把payload放入其中。Payload最大为103个字节

 

  2. 调用basicRfSendPacket()函数发送,并查看其返回值

 

  在basic_rf.h中可以找到函数声明

 

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

 

  destAddr  目的短地址

 

  pPayload 指向发送缓冲区的指针

 

  length 发送数据长度

 

  函数功能:给目的短地址发送指定长度的数据,发送成功返回SUCCESS,失败返回FAILED

 

 

接收:

 

  1. 上层通过basicRfPacketIsReady()函数来检查是否收到一个新数据包,在basic_rf.h中可以找到函数声明

 

  uint8 basicRfPacketIsReady(void);

 

  函数功能:检查模块是否已经可以接收下一个数据,如果准备好返回TRUE

 

  2. 调用basicRfReceive()函数,把收到的数据复制到buffer中,在basic_rf.h中可以找到该函数声明

 

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

 

  函数功能:接收来自Basic RF层的数据包,并为所接收的数据和RSSI值配缓冲区

 

 

 

  据说只要能看懂启动、发送、接收就基本上能使用这个无线模块了......加油~

 

 

五、Light_switch.c 代码详解

 

这个代码其实是对上面那些函数的应用

 

主要分为三个部分:主函数,按键函数,点灯函数

 

 

 

先看主函数吧

 1 void main(void)
 2 {
 3     //不设置模块的模式,代码本意是通过这个来选择这个模块是按键还是点灯模块
 4     //但是因为代码被改过了,其实这个已经没有用啦 
 5     uint8 appMode = NONE;               
 6 
 7     // Config basicRF
 8     //这里的basicRfConfig就是之前提到的basicRFCfg_t,只是重新定义了下
 9     //以下是给各成员赋值
10     basicRfConfig.panId = PAN_ID;       //设置panId的值 PAN_ID是自己定义的一个16位地址,程序开头可以改
11     basicRfConfig.channel = RF_CHANNEL; //通道值,RF_CHANNEL也是自己定义的,开头可以修改
12     basicRfConfig.ackRequest = TRUE;    //目标确认为TRUE 这个应该不用改吧...
13 #ifdef SECURITY_CCM                     //加密的东西,暂时忽略
14     basicRfConfig.securityKey = key;    //|
15 #endif                                  //|
16 
17     // Initalise board peripherals     
18     //初始化外围设备
19     halBoardInit();                     //这个我暂时不知道是什么,以后补上,求解答
20     halJoystickInit();                  //游戏摇杆,据说国外用比较多...我确定这个程序不需要这个...
21 
22     // Initalise hal_rf
23     //硬件抽象层的RF进行初始化
24     if(halRfInit()==FAILED) {
25       HAL_ASSERT(FALSE);
26     }
27 
28     // Indicate that device is powered
29     //把两个灯都打开,表示下通电啦
30     halLedSet(2);      //关闭LED2
31     halLedSet(1);      //打开LED1
32     
33     /************Select one and shield to another***********by boo*/
34     //这个端口怎么改? hal_board.h里面的
35     //HAL_BOARD_IO_BTN_1_PORT 和 HAL_BOARD_IO_BTN_1_PIN 改按键端口
36     //HAL_BOARD_IO_LED_1_PORT 和 HAL_BOARD_IO_LED_1_PIN 改灯的端口
37     //问我怎么找出来的?一直go 头 definition吧~ 笑...
38     appSwitch();          //节点为按键S1      P0_0 
39     //appLight();         //节点为指示灯LED1   P1_0
40     
41     // Role is undefined. This code should not be reached
42     HAL_ASSERT(FALSE);
43 }

主函数其实就三步

①启动(初始化)Basic RF

②初始化其余外围设备(按键、灯之类的)

③选择是按键还是灯的函数(手动选择啦,就是把另一行函数注释掉!)

 

然后看下按键函数:

 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     //初始化Basic RF 为什么又初始化??
15     //其实就是刚才main函数里部分没初始化的继续初始化下
16     //因为点灯和按键的部分要求不一样,应该是这样的...
17     basicRfConfig.myAddr = SWITCH_ADDR;        //确实,点灯和按键设置的地址怎么能一样?!
18     if(basicRfInit(&basicRfConfig)==FAILED) {
19       HAL_ASSERT(FALSE);
20     }
21     
22     //把要发送的数据写到buffer里面去,这里buffer就1位
23     //LIGHT_TOGGLE_CMD是自己在上面定义的,0
24     pTxData[0] = LIGHT_TOGGLE_CMD;             
25 
26     // Keep Receiver off when not needed to save power
27     //把模块的接收部分关掉,可以省点电!
28     basicRfReceiveOff();
29 
30     // Main loop
31     //以上都算是设初值吧,这里进去就出不来啦,死循环!
32     while (TRUE) {
33         //if( halJoystickPushed() )**********************by boo
34       if(halButtonPushed()==HAL_BUTTON_1)//**************by boo检查按键S1是否按下!
35         {
36             //按下就发送数据(发给谁, 发的数据, 数据长度)
37             //这个应该很重要吧!
38             basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH); 
39 
40             // Put MCU to sleep. It will wake up on joystick interrupt
41             //摇杆,忽略!!!
42             halIntOff();
43             halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global            
44             // interrupt enable
45             halIntOn();
46 
47         }
48     }
49 }

按键也是三步......

①初始化Basic RF的地址部分

②初始化条件触发后要发送的数据,就是把要发送的数据先准备好,等要发送了就直接发出去就可以了,不需要重复赋值啦

③循环检查按键是否按下,按下就发数据出去

 

最后还剩点灯啦,这个和按键差不多的呢

 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     //Basic RF设置地址
15     basicRfConfig.myAddr = LIGHT_ADDR;
16     if(basicRfInit(&basicRfConfig)==FAILED) {
17       HAL_ASSERT(FALSE);
18     }
19     basicRfReceiveOn();    //打开无线接收功能
20 
21     // Main loop
22     //死循环
23     while (TRUE) {
24         while(!basicRfPacketIsReady());      //接收到东西了再继续,不然循环
25 
26         if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)>0) {  //判断是否有接收到有效数据
27             if(pRxData[0] == LIGHT_TOGGLE_CMD) {                   //如果接收到刚才发的信号
28                 halLedToggle(1);                                   //改变灯的状态(开变关,关变开)
29             }
30         }
31     }
32 }

点灯也是三步,和按键差不多啦~

①初始化Basic RF的地址部分

②打开无线接收功能

③循环,收到东西就改变灯状态

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/Donut/p/4132324.html