ZigBee案例笔记 - 无线点灯

文章目录

      • 无线点灯实验概述
      • 工程关键字
      • 工程文件夹介绍
      • Basic RF软件设计框图简单说明
      • 工程操作
        • Basic RF启动流程
        • Basic RF发送流程
        • Basic RF接收流程
      • 无线点灯案例
      • 无线点灯现象

无线点灯实验概述

ZigBee无线点灯实验(即Basic RF工程),由TI公司提供的学习例程,是入门ZigBee无线通讯的经典实验,暂时没有用到协议栈,但实验所体现出来的数据发送、接收和使用协议栈的数据通讯模式是差不多的,而且 TI 公司的 Basic RF 工程代码段都有进行注释容易看懂及运用,将这个实验掌握后,将可以更好的过渡到协议栈的内容学习

工程关键字

学习无线控制实验需要线简单了解以下几个关键字

  • 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 工程源码CC2530 BasicRF.rar需要用户到TI官网注册下载,所下载的案例源码仅针对TI公司的ZigBee开发板进行配置的,烧录到其他ZigBee开发板需要修改配置后才能正常使用

工程文件夹介绍

Basic RF工程下载连接 TI官网Basic RF工程压缩包下载
拿到工程源码CC2530 BasicRF.rar解压后可以看到目录下有3个文件夹,如图分别是docs文件夹、ide文件夹和source文件夹
在这里插入图片描述
将docs文件夹、ide文件夹和source文件夹展开后如下
在这里插入图片描述
docs文件夹
打开文件夹里面仅有一个名为 CC2530_Software_Examples 的 PDF 文档,文档的主要内容是介绍 BasicRF 的特点、结构及使用,如果使用 TI 的开发板的话阅读这个文档就可以做 Basic RF 里面的实验了,阅读文档可以知道,Basic RF工程包含三个实验例程:无线点灯、传输质量检测、谱分析应用
ide文件夹
打开文件夹后会有三个文件夹和一个 cc2530_sw_examples.eww 工程,这个工程是上面提及的三个实验例程工程的集合,也包含了无线点灯的实验工程,在IAR 环境中打开,在 workspace 看到3个实验工程如图
在这里插入图片描述
ide\settings文件夹
在每个基础实验的文件夹里面都会有的,主要保存用户工程的 IAR 环境配置

ide\srf05_cc2530\iar文件夹
这里放有三个工程,light_switch.eww、per_test.eww、spectrum_analyzer.eww,如果不习惯cc2530_sw_examples.eww 工程中几个工程集合在一起看,可以在这里直接对应的实验工程

source文件夹
文件夹里面有 apps 文件夹和 components 文件夹

source\apps文件夹
存放 Basic RF 三个实验(light_switch、per_test、spectrum_analyzer)的应用实现的源代码,即用户代码存放的地方

source\components文件夹
包含 BasicRF 的应用程序使用不同组件的源代码

Basic RF软件设计框图简单说明

在这里插入图片描述
Hardware layer
硬件层,在最底下,是实现数据传输的基础

Hardware Abstraction layer
它提供了一种接口来访问 TIMER,GPIO,UART,ADC 等硬件资源,这些接口都通过相应的函数进行实现

Basic RF layer
为双向无线传输提供一种简单的协议,Basic RF 由 TI 公司提供,它包含了 IEEE 802.15.4 标准的数据包的收发功能但并没有使用到协议栈,它仅仅是是让两个结点进行简单的通信,也就是说Basic RF 仅仅是包含着 IEEE 802.15.4 标准的一小部分而已。其主要特点有:

  • 不会自动加入协议、也不会自动扫描其他节点也没有组网指示灯(LED3)。
  • 没有协议栈里面所说的协调器、路由器或者终端的区分,节点的地位都是相等的。
  • 没有自动重发的功能。

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

Application layer
是用户应用层,它相当于用户使用 Basic RF 层和 HAL 的接口,也就是说我们通过在 Application layer 就可以使用到封装好的 Basic RF 和 HAL 的函数

工程操作

TI的Basic RF工程目录下CC2530 BasicRF\ide\srf05_cc2530\iar\light_switch.eww打开无线点灯工程
在这里插入图片描述
Basic RF 还提供了安全通信所使用的 CCM-64 身份验证和数据加密,它的安全性可以通过在工程文件里面定义 SECURITY_CCM,右键工程列表打开Option,如图工程中不需要启用安全通信加密,在SECURITY_CCM前面加上x,取消加密
在这里插入图片描述

Basic RF启动流程

确保外围器件没有问题,创建一个 basicRfCfg_t 的数据结构,并初始化其中的成员,在basic_rf.h 代码中可以找到结构体定义

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

调用 basicRfInit()函数进行RF无线通信协议的初始化,在 basic_rf.c 代码中可以找到函数定义,函数对 Basic RF 的数据结构初始化,设置节点的传输通道,短地址,PAN ID

uint8 basicRfInit(basicRfCfg_t* pRfConfig)
{if (halRfInit()==FAILED)return FAILED;halIntOff();// Set the protocol configurationpConfig = pRfConfig;rxi.pPayload   = NULL;txState.receiveOn = TRUE;txState.frameCounter = 0;// Set channelhalRfSetChannel(pConfig->channel);// Write the short address and the PAN ID to the CC2520 RAMhalRfSetShortAddr(pConfig->myAddr);halRfSetPanId(pConfig->panId);// if security is enabled, write key and nonce#ifdef SECURITY_CCMbasicRfSecurityInit(pConfig);#endif// Set up receive interrupt (received data or acknowlegment)halRfRxInterruptConfig(basicRfRxFrmDoneIsr);halIntOn();return SUCCESS;
}
Basic RF发送流程

创建一个buffer存放无线发送的指令,调用 basicRfSendPacket()函数发送,并查看其返回值,在 basic_rf.c 中可以找到函数定义,其中传参为目标节点的短地址 destAddr,发送的buffer指针 pPayload 和buffer长度 length,调用函数给目的短地址发送指定长度的数据,发送成功时返回 SUCCESS,失败则返回 FAILED

uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length)
{uint8 mpduLength;uint8 status;// Turn on receiver if its not onif(!txState.receiveOn) {halRfReceiveOn();}// Check packet lengthlength = min(length, BASIC_RF_MAX_PAYLOAD_SIZE);// Wait until the transceiver is idlehalRfWaitTransceiverReady();// Turn off RX frame done interrupt to avoid interference on the SPI interfacehalRfDisableRxInterrupt();mpduLength = basicRfBuildMpdu(destAddr, pPayload, length);#ifdef SECURITY_CCMhalRfWriteTxBufSecure(txMpdu, mpduLength, length, BASIC_RF_LEN_AUTH, BASIC_RF_SECURITY_M);txState.frameCounter++;     // Increment frame counter field#elsehalRfWriteTxBuf(txMpdu, mpduLength);#endif// Turn on RX frame done interrupt for ACK receptionhalRfEnableRxInterrupt();// Send frame with CCA. return FAILED if not successfulif(halRfTransmit() != SUCCESS) {status = FAILED;}// Wait for the acknowledge to be received, if anyif (pConfig->ackRequest) {txState.ackReceived = FALSE;// We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished// The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small marginhalMcuWaitUs((12 * BASIC_RF_SYMBOL_DURATION) + (BASIC_RF_ACK_DURATION) + (2 * BASIC_RF_SYMBOL_DURATION) + 10);// If an acknowledgment has been received (by RxFrmDoneIsr), the ackReceived flag should be setstatus = txState.ackReceived ? SUCCESS : FAILED;} else {status = SUCCESS;}// Turn off the receiver if it should not continue to be enabledif (!txState.receiveOn) {halRfReceiveOff();}if(status == SUCCESS) {txState.txSeqNumber++;}#ifdef SECURITY_CCMhalRfIncNonceTx();          // Increment nonce value
#endifreturn status;
}
Basic RF接收流程

调用basicRfPacketIsReady()函数检测节点是否准备好读取新的数据包,在 basic_rf.c 中可以找到函数定义,如果准备好则返回TURE

uint8 basicRfPacketIsReady(void)
{return rxi.isReady;
}

调用 basicRfReceive()函数,把收到的数据复制到接收节点的buffer 中,代码可以在 basic_rf.c 中可以找到函数定义,函数接收来自 Basic RF 层的数据包,并为所接收的数据和 RSSI 值配置缓冲区

uint8 basicRfReceive(uint8* pRxData, uint8 len, int16* pRssi)
{// Accessing shared variables -> this is a critical region// Critical region starthalIntOff();memcpy(pRxData, rxi.pPayload, min(rxi.length, len));if(pRssi != NULL) {if(rxi.rssi < 128){*pRssi = rxi.rssi - halRfGetRssiOffset();}else{*pRssi = (rxi.rssi - 256) - halRfGetRssiOffset();}}rxi.isReady = FALSE;halIntOn();// Critical region endreturn min(rxi.length, len);
}

无线点灯案例

上面的配置流程了解了无线点灯的代码配置流程后,开始修改工程源码,无线点灯实验需要用到2块ZigBee节点板,一块作为ZigBee无线发送节点(按键发送无线指令),另一块作为ZigBee无线接收节点(接收无线指令控灯),在Basic RF工程中功能实现的代码都在light_switch.c文件中,开头用宏定义配置了节点主要参数,包含发送节点和接收节点的16位短地址、RF通道、PAN ID等关键参数

/***********************************************************************************
* CONSTANTS
*/
// Application parameters
#define RF_CHANNEL                25      // 2.4 GHz RF channel// BasicRF address definitions
#define PAN_ID                0x2007
#define SWITCH_ADDR           0x2520
#define LIGHT_ADDR            0xBEEF
#define APP_PAYLOAD_LENGTH        1
#define LIGHT_TOGGLE_CMD          0// Application states
#define IDLE                      0
#define SEND_CMD                  1// Application role
#define NONE                      0
#define SWITCH                    1
#define LIGHT                     2
#define APP_MODES                 2

创建发送节点和接收节点的buffer,创建节点结构体

/***********************************************************************************
* LOCAL VARIABLES
*/
static uint8 pTxData[APP_PAYLOAD_LENGTH];
static uint8 pRxData[APP_PAYLOAD_LENGTH];
static basicRfCfg_t basicRfConfig;

在main函数里有很多配置是实验中用不到的,比如LCD屏幕显示、遥感按键操作等,可以直接屏蔽不需要的代码部分,修改后的main函数如下(屏蔽部分已删除,详细可自行查看工程),main函数中配置了发送节点/接收节点的结构体共同部分(PAN_ID、RF_CHANNEL、TRUE),初始化板级硬件和RF无线功能、关闭板载LED,然后是按照不同节点进入不同的节点函数进行循环(发送节点进入appSwitch()函数,屏蔽appLight()函数,接收节点进入appLight()函数,屏蔽appSwitch()函数),工程不会运行到HAL_ASSERT(FALSE)函数,以下为发送节点的main函数

void main(void)
{// Config basicRFbasicRfConfig.panId = PAN_ID;basicRfConfig.channel = RF_CHANNEL;basicRfConfig.ackRequest = TRUE;
#ifdef SECURITY_CCMbasicRfConfig.securityKey = key;
#endif// Initalise board peripheralshalBoardInit();// Initalise hal_rfif(halRfInit()==FAILED) {HAL_ASSERT(FALSE);}// Indicate that device is poweredhalLedClear(1);halLedClear(2);//无线点灯核心函数appSwitch();
//    appLight();// Role is undefined. This code should not be reachedHAL_ASSERT(FALSE);
}

发送节点函数appSwitch(),将点灯指令放到pTxData发送数组中,配置发送节点短地址后初始化节点结构体,发送节点不需要做无线接收调用basicRfReceiveOff()函数关闭无线接收功能;在while循环中判断按键是否按下,按下则调用basicRfSendPacket()函数发送无线信息,LED2闪烁提示无线信息已发送,随后进入低功耗模式等待按键再次按下

static void appSwitch()
{
#ifdef ASSY_EXP4618_CC2420halLcdClearLine(1);halLcdWriteSymbol(HAL_LCD_SYMBOL_TX, 1);
#endifpTxData[0] = LIGHT_TOGGLE_CMD;// Initialize BasicRFbasicRfConfig.myAddr = SWITCH_ADDR;if(basicRfInit(&basicRfConfig)==FAILED) {HAL_ASSERT(FALSE);}// Keep Receiver off when not needed to save powerbasicRfReceiveOff();// Main loop
while (TRUE) {
// 按键判断if( halButtonPushed() == HAL_BUTTON_1 ) {basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH);HAL_LED_TGL_2();halMcuWaitMs(50);HAL_LED_TGL_2();// Put MCU to sleep. It will wake up on joystick interrupthalIntOff();halMcuSetLowPowerMode(HAL_MCU_LPM_3); // Will turn on global// interrupt enablehalIntOn();}}
}

接收节点函数appLight()(需要屏蔽main函数中的appSwitch()),配置接收节点短地址后初始化节点结构体,basicRfReceiveOn()函数打开无线接收功能,在while循环中检测接收节点是否做好接收无线数据包的准备,然后判断是否收到数据包;在收到数据包后判断无线指令是否为点灯指令,是的话闪烁LED2提示成功接收无线消息,将LED1状态进行反转完成控灯操作

static void appLight()
{
//    halLcdWriteLine(HAL_LCD_LINE_1, "Light");
//    halLcdWriteLine(HAL_LCD_LINE_2, "Ready");#ifdef ASSY_EXP4618_CC2420halLcdClearLine(1);halLcdWriteSymbol(HAL_LCD_SYMBOL_RX, 1);
#endif// Initialize BasicRFbasicRfConfig.myAddr = LIGHT_ADDR;if(basicRfInit(&basicRfConfig)==FAILED) {HAL_ASSERT(FALSE);}basicRfReceiveOn();// Main loopwhile (TRUE) {while(!basicRfPacketIsReady());if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)>0) {if(pRxData[0] == LIGHT_TOGGLE_CMD) {HAL_LED_TGL_2();halMcuWaitMs(50);HAL_LED_TGL_2();halLedToggle(1);}}}
}

如果所用到的ZigBee开发板并不是TI公司的开发板,需要检查工程中的按键引脚和LED引脚定义是否可以直接应用到所用的ZigBee开发板上,在hal_board.h文件中找到LED和按键的端口引脚宏定义,按照ZigBee开发板原理图做对应修改

// LEDs
#define HAL_BOARD_IO_LED_1_PORT        1   // Green
#define HAL_BOARD_IO_LED_1_PIN         0
#define HAL_BOARD_IO_LED_2_PORT        1   // Red
#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        1   // Button S1 by YUAN
#define HAL_BOARD_IO_BTN_1_PIN         2

无线点灯现象

工程编译成功后分别上传至ZigBee发送节点和ZigBee接收节点
在这里插入图片描述
按下发送节点的按键进行控制指令发送,观察接收节点板的LED1状态
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/586139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言实验3:函数的定义

目录 一、实验要求 二、实验原理 1.函数头 2.函数体 3.函数的定义及使用 三、实验内容 1. sum函数 代码 截图 分析 2. sum函数 代码 截图 分析 3. rank_grade函数 代码 截图 分析 4. rank_grade函数 代码 截图 分析 5. 函数的嵌套使用 代码 截图 分析…

uniapp中uview组件库的丰富Upload 上传上午用法

目录 基础用法 #上传视频 #文件预览 #隐藏上传按钮 #限制上传数量 #自定义上传样式 API #Props #Methods #Slot #Events 基础用法 可以通过设置fileList参数(数组&#xff0c;元素为对象)&#xff0c;显示预置的图片。其中元素的url属性为图片路径 <template>…

python文件打包实战技巧

众所周知&#xff0c;python是一种脚本语言&#xff0c;python程序必须在python环境下运行&#xff0c;所以如果想把自己写的程序给别人看的话&#xff0c;就比较麻烦&#xff0c;他需要先配置python环境&#xff0c;对于电脑小白来说这是“要命”的事情。而且如果是客户的话&a…

PulseGAN

研究背景 远程光电容积描记术 (rPPG) 是一种非接触式技术&#xff0c;用于测量面部视频中的心脏信号。健康监测和情绪识别等许多领域都迫切需要高质量的 rPPG 脉冲信号。然而&#xff0c;由于脉搏信号不准确的限制&#xff0c;现有的大多数rPPG方法只能用于获取平均心率&#…

AD域组策略

题目&#xff1a; 除manager 组和IT组&#xff0c;所有用户隐藏C盘&#xff1b;除manager 组和IT组&#xff0c;所有普通给用户禁止使用cmdIT01用户登陆域后&#xff0c;会自动增加驱动器X&#xff0c;该驱动器自动关联DC1的C:\tools文件夹&#xff1b;sales用户组的InternetE…

ESP32S3+HX8347+3线SPI运行LVGL例程

一、clone lv_port_esp32到本地 git clone https://github.com/lvgl/lv_port_esp32.git 二、增加hx8347.c、hx8347.h components\lvgl_esp32_drivers\lvgl_tft下新增2个文件&#xff1a;hx8347.c、hx8347.h。因为lv_port_esp32中没有hx8347的驱动&#xff0c;需要自己写。这两个…

1.2.0 IGP高级特性之FRR

理论部分参考文档&#xff1a;Segment Routing TI-LFA FRR保护技术 - 华为 一、快速重路由技术 FRR(Fast Reroute)快速重路由 实现备份链路的快速切换&#xff0c;也可以与BFD联动实现对故障的快速感知。 随着网络的不断发展&#xff0c;VoIP和在线视频等业务对实时性的要求越…

web:[BJDCTF2020]The mystery of ip(ssti模板注入、Smarty 模板引擎)

题目 进入页面显示如下 点击flag页面得到ip 点击hint页面 在hint.php的源代码页面中发现 由题目可以知道要从ip入手 这里尝试抓包加上X-Forwarded-For请求头修改为127.0.0.1 因为直接将127.0.0.1输出到页面&#xff0c;可以猜测是ssti模板注入 可以继续验证 这里发现输入什么…

【数据结构】八、查找

一、基本概念 静态查找&#xff1a;只查找&#xff0c;不改变集合内数据元素 动态查找&#xff1a;有则输出元素&#xff0c;无则添加元素 二、静态查找表 2.1顺序查找 在线性表、链表、树中依次查找 2.2折半查找&#xff08;二分查找&#xff09; 在有序的线性表中&…

macos下转换.dmg文件为 .iso .cdr文件的简单方法

为了让镜像文件在mac 和windows平台通用, 所以需要将.dmg格式的镜像文件转换为.iso文件, 转换方法也非常简单, 一行命令即可 hdiutil convert /path/to/example.dmg -format UDTO -o /path/to/example.iso 转换完成后的文件名称默认是 example.iso.cdr 这里直接将.cdr后缀删…

C#高级 08Json操作

1.概念 Json是存储和交换文本信息的语法。类似于XML。Json比XML更小、更快、更易解析。Json与XML一样是一种数据格式。Json是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。Json采取完全独立于语言的文本格式&#xff0c; 但是也使用了类似于C语言的习惯。这些特性使…

2047过滤空格(C语言)

目录 一&#xff1a;题目 二&#xff1a;思路分析 三&#xff1a;代码 一&#xff1a;题目 二&#xff1a;思路分析 1.首先&#xff0c;这道题是一个字符串的问题&#xff0c;我们要先知道字符串存放在char类型的数组中的&#xff0c;并不是一个变量就可直接存放的下一个完整…

1.Linux快速入门

Linux快速入门 Linux操作系统简介Linux操作系统优点Linux操作系统发行版1. Red Hat Linux2. CentOS3. Ubuntu4. SUSE Linux5. Fedora Linux 32位与64位操作系统的区别Linux内核命名规则 Linux操作系统简介 Linux操作系统是基于UNIX以网络为核心的设计思想&#xff0c;是一个性…

云计算:OpenStack 配置云主机实例的存储挂载并实现外网互通

目录 一、实验 1. 环境 2.配置存储挂载 3.云主机实例连接外部网络&#xff08;SNAT&#xff09; 4.外部网络连接云主机实例&#xff08;DNAT&#xff09; 二、问题 1.云主机 ping 不通外部网络 2.nova list 查看云主机列表报错 3.nova list 与 virsh list --all有何区…

【代码随想录】刷题笔记Day42

前言 这两天机器狗终于搞定了&#xff0c;一个控制ROS大佬&#xff0c;一个计院编程大佬&#xff0c;竟然真把创新点这个弄出来了&#xff0c;牛牛牛牛&#xff08;菜鸡我只能负责在旁边喊加油&#xff09;。下午翘了自辩课来刷题&#xff0c;这次应该是元旦前最后一刷了&…

行车记录仪变清晰,变高清的办法一定要收藏

有时候我们会发现行车记录仪拍摄的视频不够清晰&#xff0c;特别是出现事故需要视频为证的时候&#xff0c;如果视频太模糊&#xff0c;很难获得交警的支持&#xff0c;那么如何让行车记录仪拍摄的视频变得更加清晰呢&#xff1f; 小编给大家分享几个办法&#xff0c;建议收藏…

Android实验:contentprovider 实验+SQLite 数据库的实现

目录 SQLite实验目的实验内容实验要求项目结构代码实现结果展示 SQLite SQLite 是一个开源的嵌入式关系数据库&#xff0c;实现了自给自足的、无服务器的、配置无需的、事务性的 SQL 数据库引擎。它是一个零配置的数据库&#xff0c;这意味着与其他数据库系统不同&#xff0c;…

轻松实现iphone截图传电脑

目录 摘要 引言 用户登录工具和连接设备 生成截图 摘要 本篇博文介绍了克魔助手这款工具&#xff0c;解决了iPhone与Windows系统下图片传输的烦恼。通过连接同一Wi-Fi&#xff0c;使用克魔助手轻松实现了iPhone截图传输到电脑上的便捷操作。用户只需简单地下载并安装克魔助…

前端优化 - 防抖和节流

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

Harmony全局应用生命周期 EntryAbility.ts 讲解

之前 我们说过 page页面的生命周期 组件的生命周期 其实他和uni一样有一个整个应用的生命周期 我们如下图打开EntryAbility.ts 这是我们整个程序app的状态控制 他这里也有几个全局的生命周期 比如 我们手机 点开当前 App 启动 app 会触发 它的 onCreate 生命周期 当我们从手…