CC2530 zigebee 实现低功耗
ZigBee网络低功耗运行一直是苦逼攻城狮们要解决的问题,TI的CC2530可以说已经把终端的休眠功耗降低到了极致,现在我们就来体验这颗芯片的魅力!文章末尾分享完整源码和PCB工程文件。
一、CC2530供电模式
CC2530芯片有五种运行模式,分别为主动模式、空闲模式、PM1、PM2和PM3。从参考手册上可以看到不同模式下的供电方式。
1. 主动模式是完全功能的运行模式,CPU、外设和RF 收发器都是活动的。数字稳压器是开启的
2. 空闲模式除了CPU内核停止运行外,其他和主动模式一样
3.PM1模式稳压器的数字部分开启。32MHz XOSC和 16MHz RCOSC都不运行。32kHz RCOSC或 32kHz XOSC运行。复位、外部中断或睡眠定时器过期时系统将转到主动模式
4.PM2模式稳压器的数字内核关闭。32MHz XOSC和 16MHz RCOSC都不运行。32kHz RCOSC或 32kHz XOSC运行。复位、外部中断或睡眠定时器过期时系统将转到主动模式
5.PM3模式稳压器的数字内核关闭。所有的振荡器都不运行。复位或外部中断时系统将转到主动模式
二、CC2530模式选择
PM1、PM2、PM3是低功耗运行模式,CC2530通过关闭不必要的部分和调整系统时钟来达到低功耗的效果。
在PM1模式下,高频振荡器(32MHz XOSC和16MHz RCOSC)是掉电的。稳压器和使能的32kHz振荡器是开启的。当进入PM1模式,就运行一个掉电序列。由于PM1使用的上电/掉电序列较快,等待唤醒事件的预期时间相对较短(小于3ms),就使用PM1。
PM2具有较低的功耗。在PM2下的上电复位时刻,外部中断、所选的32 kHz 振荡器和睡眠定时器外设是活动的。I/O引脚保留在进入PM2之前设置的I/O模式和输出值。所有其它内部电路是掉电的。稳压器也是关闭的。当进入PM2模式,就运行一个掉电序列。当使用睡眠定时器作为唤醒事件,并结合外部中断时,一般就会进入PM2模式。相比较PM1,当睡眠时间超过3ms 时,一般选择PM2。比起使用PM1,使用较少的睡眠时间不会降低系统功耗。
PM3用于获得最低功耗的运行模式。在PM3模式下,稳压器供电的所有内部电路都关闭(基本上是所有的数字模块,除了中断探测和POR电平传感)。内部稳压器和所有振荡器也都关闭。PM3模式可被外部中断和复位唤醒。
PM2模式其功耗是毫安级别的,多用于需要定时唤醒的场合,比如周期性地唤醒传感器来进行数据的采集,PM2模式可被睡眠定时器,外部中断和复位唤醒。PM3模式功耗最低,是微安级别的,多用于数据收发不频繁的场合。Z-STACK提供了两种低功耗运行模式,PM2和PM3。
三、CC2530低功耗代码设置
1.准备一份CC2530官方示例代码(也可使用本文已经修改好的代码),并打开
2.添加预编译项POWER_SAVING
ZigBee功耗主要是针对终端设备的,因此只需要修改终端设备代码即可,将IAR编译器的Workspace处选项改为EndDeviceEB,在项目名称上右键选择Options,如图添加预编译项POWER_SAVING来使能睡眠模式
3.修改f8wConfig.cfg文件
将以下参数修改(在文件的最后)
参数的作用代码中有注释,不过多解释了
-DRFD_RCVC_ALWAYS_ON=FALSE //default True -DPOLL_RATE=0 //default 1000 -DQUEUED_POLL_RATE=0 //default 100 -DRESPONSE_POLL_RATE=0 //default 100 -DREJOIN_POLL_RATE=0 //default 440
4.修改OnBoard.c文件
将函数InitBoard()改为如图所示
5.修改OSAL_PwrMgr.c文件
将函数osal_pwrmgr_init()改为如图所示
PWRMGR_BATTERY将允许HAL管理CPU进入SLEEP LITE或者SLEEP DEEP状态
6.周期性发送数据
每间隔3秒发送一次数据
void SampleApp_Send_P2P_Message( void ) { uint16 i = 0; uint8 data[10] = {0}; uint16 father_short_addr = 0; uint16 myself_short_addr = 0; static uint8 count = 0; father_short_addr = NLME_GetCoordShortAddr(); myself_short_addr = NLME_GetShortAddr(); data[0] = ( father_short_addr >> 8 ) & 0xff; data[1] = father_short_addr & 0xff; data[2] = ( myself_short_addr >> 8 ) & 0xff; data[3] = myself_short_addr & 0xff; data[4] = count; count++; if( AF_DataRequest( &SampleApp_P2P_DstAddr, &SampleApp_epDesc, SAMPLEAPP_P2P_CLUSTERID, 5, data, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { HAL_TURN_ON_LED1(); for (i=0; i<50400; i++) asm("NOP"); HAL_TURN_OFF_LED1(); } else { // Error occurred in request to send. } }
四、实验现象
代码编译完成,通过CCDebugger将程序烧写到芯片里,打开协调器,然后给终端上电,协调器打印数据如下:
使用万用表测量,其休眠功耗为1.1uA
使用电化学工作站测量其发送数据功耗,可以看出基本在12-18mA左右。
低功耗ZigBee协议栈 f8wConfig.cfg 文件配置介绍
1. DPOLL_RATE
是一个与数据轮询相关的宏定义,它通常用于设置端点(EndPoint)之间的数据轮询速率
(用于设置设备定期轮询其父设备以检查是否有数据要接收的频率。这个参数对于 Zigbee End Device 尤其重要,因为它们通常处于低功耗模式,并且需要定期唤醒以检查是否有待处理的数据。)
举例:
-DPOLL_RATE=1000 // 1000
,表示设备每秒轮询一次
-DPOLL_RATE=5000 // 每 5000 毫秒(5 秒)轮询一次
2. DQUEUED_POLL_RATE
是 TI 的 Zigbee 协议栈(如 Z-Stack)中的一个配置参数,用于配置设备在轮询队列中消息的频率。具体来说,它用于设置 End Device 以固定的时间间隔向其 Parent Device 请求数据,这对于低功耗设备非常重要,以平衡功耗和数据通信的及时性。
举例:
-DQUEUED_POLL_RATE=1000 //1000
,表示设备每秒轮询一次
-DQUEUED_POLL_RATE=2000 // 每 2000 毫秒(2 秒)轮询一次
3. DRESPONSE_POLL_RATE
是 TI 的 Zigbee 协议栈(如 Z-Stack)中的一个配置参数,用于设置设备在响应等待过程中轮询其父设备的频率。这个参数特别重要,当 End Device 发送一个请求并等待父设备的响应时,可以通过这个轮询频率检查是否有响应数据可接收。
举例:
-DRESPONSE_POLL_RATE=100 //100
,表示设备每 100 毫秒轮询一次。
-DRESPONSE_POLL_RATE=200 // 每 200 毫秒轮询一次
虽然 DRESPONSE_POLL_RATE
通常是在配置文件中定义的,但你也可以在代码中进行设置或调整。以下是一个简单的例子,展示如何在代码中设置轮询率:
#include "ZComDef.h" #include "OSAL.h" #include "ZMAC.h" #include "ZDApp.h" // 定义响应轮询率 #define MY_RESPONSE_POLL_RATE 200 // 每 200 毫秒轮询一次 void setResponsePollRate(uint16_t rate) { // 设置响应轮询率 _NIB.nwkResponsePollRate = rate; ZMacSetPollRate(rate); } void main(void) { // 初始化硬件和协议栈 osal_init_system(); ZMacInit(); ZDApp_Init(); // 设置自定义响应轮询率 setResponsePollRate(MY_RESPONSE_POLL_RATE); // 启动任务调度 osal_start_system(); // 此函数不会返回,系统开始调度任务 }
4.DREJOIN_POLL_RATE
是 TI 的 Zigbee 协议栈(如 Z-Stack)中的一个配置参数,用于设置设备在重新加入网络期间轮询其父设备的频率。这个参数在设备失去网络连接后尝试重新加入网络时非常重要。
举例:
-DREJOIN_POLL_RATE=1000 //1000
,表示设备每秒轮询一次。
-DREJOIN_POLL_RATE=2000 // 每 2000 毫秒(2 秒)轮询一次
在实际应用中,选择合适的 DREJOIN_POLL_RATE
需要考虑以下因素:
- 重新加入网络的速度:如果应用需要快速重新加入网络,较短的轮询间隔更适合。
- 功耗:对于电池供电的设备,较长的轮询间隔可以延长电池寿命。
- 网络负载:频繁的轮询会增加网络负载,特别是在大型网络中需要权衡。
等级:
如果只是终端定时发送 可以进到PM3.
如果接收发送 只能进到PM2,因为接收需要长连接