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
①Hardware layer 硬件层
实现数据传输的基础
②Hardware Abstraction layer 硬件抽象层
提供接口以访问TIMER,GPIO,UART,ADC等,这些接口都通过函数实现。
③Basic RF
为双向无线通信提供一种简单的协议
④Application layer 用户应用层
它相当于一个接口,方便用户使用Basic RF层和HAL,就是说在Application层就可以使用封装好的Basic RF和HAL函数
2. Basic RF layer 简介
Basic RF 由TI公司提供,包含IEEE 802.15.4标准的数据包收发功能但不使用协议栈,仅让两个结点进行简单通信。
Basic RF layer 为双向无线通信提供了一个简单的协议,通过这个协议能够进行数据的发送和接收
四、Basic RF 工作过程分析
Basic RF的工作过程分为三个部分:启动、发射、接收
启动:
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。
接收:
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的地址部分
②打开无线接收功能
③循环,收到东西就改变灯状态
原文:http://www.cnblogs.com/Donut/p/4132324.html