首页 > 代码库 > 「ZigBee模块」组网实验-无线点灯

「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_rf23     //硬件抽象层的RF进行初始化24     if(halRfInit()==FAILED) {25       HAL_ASSERT(FALSE);26     }27 28     // Indicate that device is powered29     //把两个灯都打开,表示下通电啦30     halLedSet(2);      //关闭LED231     halLedSet(1);      //打开LED132     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_040     41     // Role is undefined. This code should not be reached42     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 BasicRF14     //初始化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是自己在上面定义的,024     pTxData[0] = LIGHT_TOGGLE_CMD;             25 26     // Keep Receiver off when not needed to save power27     //把模块的接收部分关掉,可以省点电!28     basicRfReceiveOff();29 30     // Main loop31     //以上都算是设初值吧,这里进去就出不来啦,死循环!32     while (TRUE) {33         //if( halJoystickPushed() )**********************by boo34       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 interrupt41             //摇杆,忽略!!!42             halIntOff();43             halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global            44             // interrupt enable45             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 BasicRF14     //Basic RF设置地址15     basicRfConfig.myAddr = LIGHT_ADDR;16     if(basicRfInit(&basicRfConfig)==FAILED) {17       HAL_ASSERT(FALSE);18     }19     basicRfReceiveOn();    //打开无线接收功能20 21     // Main loop22     //死循环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的地址部分

②打开无线接收功能

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

 

 

 

 

 

 

 

 

 

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