关于CC2530休眠进入PM2设置问题?方法?完整解说?
官方提供的设置方法:
5,如何让End Device进入低功耗状态,休眠时间是如何设定的?
在协议栈宏定义中使能POWER_SAVING后,然后在f8wConfig.cfg文件里面把-DRFD_RCVC_ALWAYS_ON=FALSE,就可以让End Device进入休眠状态。
关于休眠的时间是有OSAL操作系统的调度来决定,每次休眠时间都是按照最新会发生的一个Event Timeout作为休眠时间。具体在协议栈hal_sleep函数中有说明。
这个timeout主要分为两类,一类是应用层事件的timeout,另外一类是MAC层事件的timeout,
1)应用层的timeout的时间,是在osal_pwrmgr_powerconserve( void )函数中,通过osal_next_timeout();获得的。
2)MAC层的timeout时间,是通过halSleep( uint16 osal_timeout )函数里面,通过MAC_PwrNextTimeout();来获得的。
好了,按上面要求我都设置了为什么进不了休眠,问题就出现这里,最大问题,你不知道有那些任务在执行,以为自己定义一个事件在运行,然后根据上面设置OK?想得太简单了,人家就是不提供一个简单的例程给你,慢慢看资料,找资料,这样给开发者花费时间不少,反正我还没有解决,也不知道怎么解决。
我整理一下网上一些设置方法?一起学习吧。
CC2530有3种睡眠模式,pm2模式比较省功耗而且可以被定时唤醒;pm3模式最省电但是只能被外部中断唤醒
1、sensordemo的sensor在入网以后,为什么灯在不断地闪?
其实,闪一次就是睡眠了一次:亮的时候睡过来,灭的时候睡下去。具体代码在halSleep函数里。要做的,就是读懂这个机制是怎么运作的。
2、为什么闪的频率那么高?
zstack的睡眠机制就是在操作系统没事干的时候才睡眠,频率高说明应用程序让操作系统不断做事。你想让它长时间睡眠,那要做的就是不要不断地给操作系统事情做,找到分配系统任务的地方。
要设置低功耗模式,先确认:
1.f8wConfig.cfg文件中DRFD_RCVC_ALWAYS_ON定义为FALSE
2.Options->C/C++Compiler->Defined symbols中添加预编译“POWER_SAVING”;
重要函数void halSleep( uint16 osal_timeout )
1.首先将osal_timeout转成以320US为单位
2.获取下一次MAC定时器到期时间
3. halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;
//为PM2,PM3模式。 没有任务要执行就进入PM3深度睡眠,否则进入PM2睡眠,可以定时器唤醒。
4.唤醒
OSAL机制的ZigBee低功耗管理(CC2530)
涉及文件
OSAL_PwrMgr.h OSAL电源管理的API头文件
OSAL_PwrMgr.C OSAL电源管理的API C文件
hal_sleep.c 底层的电源管理文件
电源管理结构体
typedef struct
{
uint16 pwrmgr_task_state; //任务状态
uint16 pwrmgr_next_timeout; //下一次超时
uint16 accumulated_sleep_time; //睡眠时间
uint8 pwrmgr_device; //电源管理设备属性,有PWRMGR_ALWAYS_ON 和 PWRMGR_BATTERY两种
} pwrmgr_attribute_t;
#define PWRMGR_ALWAYS_ON 0
#define PWRMGR_BATTERY 1
选择PWRMGR_ALWAYS_ON的话将不会进入睡眠模式,选择PWRMGR_BATTERY将允许HAL管理CPU进入SLEEP LITE或者SLEEP DEEP状态。
#define PWRMGR_CONSERVE 0
#define PWRMGR_HOLD 1
低功耗标志,主要用于osal_pwrmgr_task_state()这个函数中,用于标志每一任务是否需要低功耗。
extern pwrmgr_attribute_t pwrmgr_attribute
定义一个电源管理的全局变量。
/*********************************************************************
* @brief 初始化电源管理函数,这个函数在OSAL.C里面的osal_init_system( )调用,
也就是在OSAL系统初始化的时候将电源管理模式调成了不会进入睡眠模式的状态。
*/
void osal_pwrmgr_init( void )
{
pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; //默认没有睡眠模式
pwrmgr_attribute.pwrmgr_task_state = 0; //清零
}
OSAL系统在检查完所有的任务事件之后发现没有事件需要处理,这样在POWER_SAVING宏定义打开的情况下将调用osal_pwrmgr_powerconserve();函数,在这函数中将会根据选择系统进入休眠。
退出休眠
当出现IO中断或者复位时候会退出休眠,或者在休眠定时器中断时候也将会退出休眠。如果是IO中断或者休眠定时器中断退出之后将回到进入休眠的地方继续向下执行,复位退出的话进入程序的初部分执行。
找到一个例程:http://blog.163.com/a_hui8/blog/static/205830307201263011569606/
http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/45598.aspx
上面这帖子哦,都回复这么多了,解决了?也许吧。。。
CC2530 OSAL进入省电模式注意事项总结
在淘宝搞了几个CC2530模块回来玩,其中比较感兴趣的是低功耗这块功能,目前测试的结果是PM2模式下,纽扣电池2.8V电压,工作电流1.1uA(FLUKE F18B),符合规格书中描述的典型值1uA,总结如下:
前言:
1. OSAL是一个不错的操作系统,不要老是想着自己进入低功耗模式,应用任务没事干了,OSAL自己会进入低功耗模式。
2. 进入PM2不困难,真正困难的是真正低功耗并且通信正常。
3. 低功耗和代码有关,和硬件也有关,必要的时候,把板子除了最小系统所需之外的期间函调,一遍排查是代码问题还是硬件设计问题。
实际操作方法:(我基于淘宝卖家的例程进行操作,每个人的例程或协议栈版本不一样可能存在一定的差异)
1. 在编译器预编译那里定义:POWER_SAVING
2. f8wConfig.cfg文件中,DPOLL_RATE\DQUEUED_POLL_RATE\DRESPONSE_POLL_RATE\DREJOIN_POLL_RATE这几个全部赋值0。
3. 在你的任务初始化中增加这么一句osal_pwrmgr_device(PWRMGR_BATTERY);否则,OS不会进入省电模式。注意所有的用户任务都必须执行这么一句,否则无法进入省电模式。
做完以上3点,恭喜你,已经可以进入省电模式了。
但是,到底是PM1或PM2或PM3,要继续往下走
4. 找到void halSetSleepMode(void)函数,PCON = halSleepPconValue;这句决定你进入哪种省电模式,找到它定义的地方,我这边赋值是PCON_IDLE,将其改成HAL_SLEEP_TIMER或CC2530_PM2,即可进入PM2模式。想进入PM3同理。
作为第4点,即可进入PM2模式,但是并不以为则真的省电,可能几百个uA也可能若干个mA甚至几十个mA和没进入PM2一样。原因是,有其他任务在不停的唤醒CPU,导致电流下不来,需要注意哪几点?
1. 键盘,如果采用扫描模式则,则不停唤醒CPU,需设置成中断模式,或加大扫描周期。
2. LED,LED也有个任务,看看你的LED是不是频繁闪烁,如果是停掉。
3. ADC,我听别人说的,有个电池检测的任务不停进行电压采样,我这里没有。
4. 协议栈、协议栈、协议栈,重要的事情说三遍。
4.1 终端上电后或者断网后,会主动查找网络,导致无法进入省电模式。解决办法:http://blog.csdn.net/shjhuang/article/details/51171369,TI论坛也有,我忘记链接了。
4.2 VV大侠的http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/75525.aspx 当中的第4点。
以上做完了,我就实现了1.1uA的目标。
以上如有疑问,欢迎补充。
http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/105541.aspx
有完整的解说方法
接着继续喷吧。。我会每天来回复一条吧,喷喷。。。
IAR版本:8.20
zigbee协议:2.5.1a
1o8KBCD0
例子地址:https://pan.baidu.com/s/1o8KBCD0
这个例子,还没有进行添加休眠。我试着,但是不成功。
程序中还没有对LED进行处理。是不能进入休眠的。仿真看一看
有进入这一步
然后点下一步:
不成立。。好了,在刚才IO中,我们再添加一代码:
#include "OSAL_PwrMgr.h"
osal_pwrmgr_device(PWRMGR_BATTERY);
再次仿真一下:
刚才iar,挂了,重新来
进入了。我们一步步运行。
上图可以看出,等于0
然后,再执行下一步:
next=98??
1MS都不到。。。
全速运行,看看能不能再一次进入void osal_pwrmgr_powerconserve( void )
还是进来的,
从这里说明在应用层添加osal_pwrmgr_device(PWRMGR_BATTERY); 是有用的。
不过新问题来的。
next得到的值很小很小,,说明系统是有任务在执行。。怎么解决呢。等会直接把网络关闭。
在GenericApp.c;;;;;;;;添加 ZDApp_StopJoiningCycle();
仿真一下吧
我的IAR又挂了,我重启一下电脑吧
重新仿真了,
next = osal_next_timeout(); 值 还是不变,
看来问题出现在那里?我感觉是有任务在执行,是不是接受部分呢?我们来看看
先把有可能的任务先关闭吧,比如串口,给XO。
@ED LG
非常感谢你的经历和经验分享!加油!