打印
[Zigbee]

CC2530 BasicRF(无线点灯)

[复制链接]
1684|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gwsan|  楼主 | 2019-8-5 11:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gwsan 于 2019-8-5 11:45 编辑

1 理论分析
1.1 Light_Switch工作流程
无线点灯的工作过程:启动、发射、接收。【本实验的重点就在Application层】

        启动
(1)板载外设、射频IO、系统时钟、中断等初始化;确保外围器件没有问题;(halBoardInit()
(2)BasicRF数据结构体配置
要配置的数据结构体,就是位于basic_rf.h的basicRfCfg_t结构体,如图所示。
图1 basicRfCfg_t结构体
(3)BasicRF协议初始化;调用halRfInit();basicRfInit()函数进行协议的初始化, 在 basic_rf.c 代码中可以找到uint8 basicRfInit(basicRfCfg_t* pRfConfig)该函数对 Basic RF 的数据结构初始化,设置模块的传输通道,短地址,PAD ID。

        发射(按键程序appSwitch();)
(1)将刚才配置的BasicRF结构体数据进行初始化。
(2)如果按键按下,就调用basicRfSendPacket();将按键信息发送出去,控制LED灯亮灭状态。在 basic_rf.c 中可以找到
uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length)
destAddr 目的短地址
pPayload 指向发送缓冲区的指针
length 发送数据长度
函数功能: 给目的短地址发送指定长度的数据,发送成功刚返回 SUCCESS,失败则返回 FAILED

        接收(LED程序appLight();)
(1)将刚才配置的BasicRF结构体数据进行初始化。
(2)调用basicRfPacketIsReady();函数检测是否接收到数据;在 basic_rf.c 中可以找到

uint8 basicRfPacketIsReady(void)

函数功能: 检查模块是否已经可以接收下一个数据,如果准备好刚返回TRUE。
(3)如果接受到数据,调用basicRfReceive();函数接受数据,并根据接受到按键信息控制LED灯亮灭状态。在 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 的接收过程,具体到每个层的功能函数。具体实现过程大家看文档的那个章节就可以大概明白的了,另一方面,实验例程的模块化编程做得很好,大家只需要明白函数的作用,学会使用它就行了,至于它内部是怎么样一层一层的实现,我们也不用太过关心。


使用特权

评论回复

相关帖子

沙发
gwsan|  楼主 | 2019-8-5 11:45 | 只看该作者
1.2 Light_Switch流程图

下面是本实验的流程图,大家可以结合这个图来学习编写程序。

图2流程图

使用特权

评论回复
板凳
gwsan|  楼主 | 2019-8-5 11:46 | 只看该作者
2 实验详解
2.1实验目的
(1)掌握无线点灯的工作过程;
(2)初步熟悉基于BasicRF的开发应用。

2.2实验设备
硬件:PC 机一台,ZB2530(底板、核心板、仿真器、USB 线)两套;
软件:win7 系统,IAR 8.20 集成开发环境。

使用特权

评论回复
地板
gwsan|  楼主 | 2019-8-5 11:46 | 只看该作者
2.3实验相关电路图

图3 LED电路图

图4 按键电路图

使用特权

评论回复
5
gwsan|  楼主 | 2019-8-5 11:47 | 只看该作者
2.4 实验分析

本实验用到的通用 IO,只需要配置 PxSEL、PxDIR、PxINP 这几寄存器作用和配置方法如表1、2、3、4所示(以P1为例):

表1端口1


使用特权

评论回复
6
gwsan|  楼主 | 2019-8-5 11:49 | 只看该作者
表2 端口1的功能选择


使用特权

评论回复
7
gwsan|  楼主 | 2019-8-5 11:50 | 只看该作者
表3 端口1的方向


使用特权

评论回复
8
gwsan|  楼主 | 2019-8-5 11:50 | 只看该作者
表4 端口1的输入模式


使用特权

评论回复
9
gwsan|  楼主 | 2019-8-5 11:51 | 只看该作者
2.5实验代码分析
main 函数

1 void main(void)
2 {
3   uint8 appMode = NONE;//不设置模块的模式
4
5   //创建BasicRF数据结构体(basicRfCfg_t),并初始化其成员
6   basicRfConfig.panId = PAN_ID;//用户的PAN_ID
7   basicRfConfig.channel = RF_CHANNEL;//RF通道必须在-26之间
8   basicRfConfig.ackRequest = TRUE;//目标确认设置
9   
10 #ifdef SECURITY_CCM
11    basicRfConfig.securityKey = key;//密钥安全通信,本例程不加密
12 #endif
13
14    // Initalise board peripherals初始化外围设备
15    halBoardInit();//IO口、时钟、中断初始化
16    halJoystickInit();//BY QIUJIE
17
18    // Initalise hal_rf硬件抽象层的 rf 进行初始化
19    if(halRfInit()==FAILED) {
20      HAL_ASSERT(FALSE);
21    }
22
23  /*************底板配置**************/
24   halLedSet(2);// 关 LED2(P1_0=1)
25
26   halLedClear(1);// 开 LED1(P1_0=0)
27  
28  /******选择性下载程序,发送模块和接收模块******/
29    //注:函数appSwitch()和appLight()只能打开一个
30    //appSwitch();//节点为按键 S1 P0_1
31   
32    appLight(); //节点为指示灯 LED1 P1_0
33   
34    HAL_ASSERT(FALSE); //不会执行此函数
35 }

第15行:初始化配置,关于如何配置IO口,笔者会在后文具体讲解。
第 23~26 行: 关闭底板的 LED2,开 LED1。由于 LED 电路是低电平点亮的, 与 TI 不同,更符合以前大家学习单片机的习惯, 所以 halLedSet()置 1 是使灯熄灭,不过这个没关系,关键是掌握怎么使用就可以了。
第 28~32 行: 选择其中的一行,并把另外一行屏蔽掉;这两行重要啦,一个是实现发射按键信息的功能,另一个是接收按键信息并改变LED 状态的功能。分别为 Basic RF 发射和接收。不同模块在烧写程序时选择不同功能。
注意: 程序会在 appSwitch(); 或者 appLight();里面循环或者等待,不会执行到第 34 行。


使用特权

评论回复
10
gwsan|  楼主 | 2019-8-5 11:52 | 只看该作者
        LED初始化配置
在hal_board.c中halBoardInit()初始化函数,在57行会有LED的初始化,


下面具体讲解LED的初始化实现。

        MCU_IO_DIR_OUTPUT在hal_cc8051.h中有定义,




        HAL_BOARD_IO_LED_1_PORT和HAL_BOARD_IO_LED_1_PIN在hal_board.c有定义。


通过上面的配置就能配置LED的IO口。


使用特权

评论回复
11
gwsan|  楼主 | 2019-8-5 11:53 | 只看该作者

        KEY配置

当然啦,按键的IO口配置和LED的类似,笔者就不再赘述了。


使用特权

评论回复
12
gwsan|  楼主 | 2019-8-5 11:54 | 只看该作者
appSwitch()函数

1 static void appSwitch()
2 {
3
4 #ifdef ASSY_EXP4618_CC2420
5    halLcdClearLine(1);
6    halLcdWriteSymbol(HAL_LCD_SYMBOL_TX, 1);
7 #endif
8
9    pTxData[0] = LIGHT_TOGGLE_CMD;
10
11    // Initialize BasicRF
12    basicRfConfig.myAddr = SWITCH_ADDR; //BasicRF 数据结构体成员(短地址)初始化
13    if(basicRfInit(&basicRfConfig)==FAILED) {
14      HAL_ASSERT(FALSE); //初始化 basicRf 数据结构
15    }
16
17    // Keep Receiver off when not needed to save power
18    basicRfReceiveOff();//当用不到接收器的时候,将其关闭。
19
20    // Main loop程序进入死循环
21    while (TRUE) //查询方式判断按键是否按下
22    {
23      
24      if(halButtonPushed()==HAL_BUTTON_1)//按键 S1 被按下
25      {
26             //发送目的地址、缓冲区里的数据
27            basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH);
28
28            // Put MCU to sleep. It will wake up on joystick interrupt
30            halIntOff();
31            halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global
32            // interrupt enable
33            halIntOn();
34
35        }
36    }
37 }

第 4~7 行: TI 学习板上的液晶模块的定义,我们不用管他
第 9 行: Basic RF 发射第 1 步,把要发射的数据或者命令放入一个数据 buffer,此处把灯状态改变的命令 LIGHT_TOGGLE_CMD 放到 pTxData 中。
第 11~15 行: Basic RF 启动中的初始化,就是上面所讲的 Basic RF 启动的第 3步
第 18 行: 由于模块只需要发射,所以把接收屏蔽掉以降低功耗。
第24 行: if(halButtonPushed()==HAL_BUTTON_1)判断是否S1 按下,函数halButtonPushed()是 halButton.c 里面的,它的功能是:按键 S1有 被 按 动 时 ,就 回 返 回 true ,则入basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH);
第 27 行: Basic RF 发射第 2 步, 也是发送数据最关键的一步,函数功能在前面已经讲述。basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH)就是说:将 LIGHT_ADDR、 pTxData、 APP_PAYLOAD_LENGTH 的实参写出来就是 basicRfSendPacket(0xBEEF ,pTxData[1] ,1 )把字节长度为1 的命令,发送到地址 0xBEEF
第 30~31 行:开发板暂时还没有 joystick(多方向按键),不用理它先。
第 33 行: 使能中断



使用特权

评论回复
13
gwsan|  楼主 | 2019-8-5 11:55 | 只看该作者
appLight()函数

1 static void appLight()
2 {
3  /*************************************************
4   halLcdWriteLine(HAL_LCD_LINE_1, "Light");
5   halLcdWriteLine(HAL_LCD_LINE_2, "Ready");
6  *************************************************/
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); //初始化 basicRf 数据结构
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            }
28        }
29    }
30 }


第 8~11 行: LCD 内容暂时不用理它
第 13~17 行: 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)判断否接收到有数据
第 25 行: if(pRxData[0] == LIGHT_TOGGLE_CMD)判断接收到的数据是否就是发送函数里面的 LIGHT_TOGGLE_CMD 如果是,执行第 22 行
第 26 行: halLedToggle(1),改变 Led1 的状态。


使用特权

评论回复
14
gwsan|  楼主 | 2019-8-5 11:56 | 只看该作者
2.6实验现象
第一步: 打开….\CC2530 BasicRF\ide 文件夹下面的工程,在 light_switch.c 里面找到 main 函数,找到下面内容,把 appLight(); 注释掉,下载到发射模块。

第二步:找到相同位置,这次把 appSwitch();注释掉,下载到接收模块。

完成烧写后上电,按下发射模块的 S1按键,可以看到接收模块的 LED1被点亮。

注意:Zigbee开发板,可以由2处地方供电:
(1)USB/Battery,
(2)下载器;用户一次最好用一处供电,否则可能会烧坏电路。


使用特权

评论回复
15
gwsan|  楼主 | 2019-8-5 11:56 | 只看该作者
2.7实验拓展
拓展1:

或许你觉得点亮 LED 太没意思了,我们可以点亮台灯,只需把LED1的引脚外接到继电器上,控制继电器的开合即可。具体细节就不详细讲了,有兴趣的的可以试着做做,只是要注意安全,毕竟是控制市电。

拓展2:
本实验只给出了点亮一个灯,你会觉得点一个灯太大材小用,我们也可以点亮多个灯,那么你想点亮及格呢?本教程给出了两个按键控制两个灯的参考代码,你想一个按键控制多个灯,多个按键控制一个灯,那就看你的想怎么控制了,好了,通过本章讲解,你感觉到zigbee协议的神奇之处了吗!别走开,后面更精彩。


使用特权

评论回复
16
eddy2019| | 2019-8-5 15:56 | 只看该作者
楼楼厉害了 感谢分享

使用特权

评论回复
17
phosphate| | 2019-8-6 14:39 | 只看该作者
感谢分享!学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

3426

帖子

1

粉丝