求助,关于CC2530在osal调度下PM2模式休眠和工作时间问题?
请教一个问题
cc2530(zstack-2.2.2-1.3.0),osal调度的PM2模式,如何自定义休眠时间和工作时间?
我现在是在ZED的
void zb_HandleOsalEvent( uint16 event )
{
.................
if ( event & MY_PERSONAL_ENTERPM2_EVT )
{
//P1_1 ^= 1;
myApp_StopReporting();
NLME_SetPollRate(myEnterpm2Period); // 60 000ms = 1 min
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_ENTERPM2_EVT, myEnterpm2Period );
}
}
static uint16 myEnterpm2Period = 30000; 的时候,休眠30s,发送20s
static uint16 myEnterpm2Period = 40000; 的时候,休眠40s, 还是 发送20s
static uint16 myEnterpm2Period = 60000; 貌似直接就乱套了,也不休眠了,总是在发送
休眠时间 和 工作的时间,究竟怎么来做限制?
而在osal下,最大的休眠时间应该是65ms左右才对啊?
那工作时间,又该怎么来约束?
OSAL调度系统的休眠时间并不是自己随便可以设置的,而是osal调度系统每次都是以最近一次要发生事件的timeout作为本次的休眠时间,如果你的系统有一个最小的30ms事件的周期性的发生,那么你的休眠时间只能是30ms了。
您说的我都明白,但是我在ZED的void zb_HandleOsalEvent( uint16 event )里面。
有一个20ms的事件MY_PERSONAL_COLLECT_345_EVT,
我还有一个200ms的事件MY_PERSONAL_REPORT_345_EVT,
我还设置了另外一个事件MY_PERSONAL_ENTERPM2_EVT(比如说设置为40s),用于进入pm2状态。进入MY_PERSONAL_ENTERPM2_EVT事件以后,我利用myApp_StopReporting();来关掉20ms和200ms的定时器事件,但是不关40s的定时器事件。然后设置三个全部为0,这样让osal自动进入任务调度,按照您的说法,现在获取的休眠时间就应该是40s了。
当唤醒以后,我在hal_sleep.c里面HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);之后,设置正常的poll_rate值(1000,100,100),并且开启myApp_StartReporting();来开启20ms和200ms的定时器事件。然后等40s还有,再次进入我的MY_PERSONAL_ENTERPM2_EVT(40s)事件,由此循环。
按照这个逻辑,如果我的MY_PERSONAL_ENTERPM2_EVT设置为40s,那是不是应该工作40s,然后进入pm2模式休眠40s,唤醒后再工作40s,由此循环?
但事实上,如果这个值设置为40s了,实际上是工作20s,然后休眠40s。如果这个值设置为60s了,完全就没有休眠了,基本上都是工作状态。这是为什么呢?
--------------------------------------------------------------------------------------------------------------------------------------------------------
void zb_HandleOsalEvent( uint16 event )
{
static uint8 pData[2];
uint8 pDataForExtAdc[2];
if ( event & MY_START_EVT )
{
zb_StartRequest();
}
if ( event & MY_REPORT_TEMP_EVT )
{
// Read and report temperature value
pData[0] = TEMP_REPORT;
pData[1] = myApp_ReadTemperature();
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 2, pData, 0, AF_ACK_REQUEST, 0 );
osal_start_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod );
}
if ( event & MY_REPORT_BATT_EVT )
{
// Read battery value
// If battery level low, report battery value
pData[0] = BATTERY_REPORT;
pData[1] = myApp_ReadExtBattery(); // myApp_ReadBattery();
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 2, pData, 0, AF_ACK_REQUEST, 0 );
osal_start_timerEx( sapi_TaskID, MY_REPORT_BATT_EVT, myBatteryCheckPeriod );
}
/*-------------------------------------------*/
if ( event & MY_PERSONAL_COLLECT_345_EVT )
{
myApp_Read345();
P0DIR |= 0x20;
P0SEL &= ~0x20;
P0_5 ^= 1;
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT, myAdxl345CollectPeriod );
}
if ( event & MY_PERSONAL_REPORT_345_EVT )
{
// Read battery value
// If battery level low, report battery value
if( InitTimerFlag == 0x00 )
{
InitTimerFlag = 0x01;
P1DIR |= 0x02;
P1SEL &= ~0x02;
//P1_1 = 0;
P0DIR |= 0x40;
P0SEL &= ~0x40;
//P0_6 = 0;
}
// P1_1 ^= 1;
if ( ( (BufHead - BufTail) > 10) || ( ( (BufHead - BufTail)&0x7F) > 10) )
{
osal_memcpy(PacketData+1,&PreSendValue.PreSend[BufTail*4],40);
PacketData[0]= ADXL345_REPORT;
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 41, PacketData , 0,AF_ACK_REQUEST , 0 ); //AF_ACK_REQUEST
BufTail += 10;
BufTail %= 512;
P0DIR |= 0x40;
P0SEL &= ~0x40;
P0_6 ^= 1;
}
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT, myAdxl345ReportPeriod );
Delay_1u(1);
//不发这个了,发一个counter
sprintf(SendCnt,"%d\r",SendCounter);//将数值格式化为字符串
HalUARTWrite(0, (unsigned char*)&SendCnt,(unsigned char)osal_strlen( (void*)SendCnt ));
SendCounter += 40;
SendCounter %= 0xFFFF ;
}
if ( event & MY_PERSONAL_ENTERPM2_EVT ) // stop里面,不设置此事件(undo)
{
P0DIR |= 0x10;
P0SEL &= ~0x10;
P0_4 ^= 1;
myApp_StopReporting();
NLME_SetPollRate( 0 ); // 60 000ms = 1 min
NLME_SetQueuedPollRate( 0 );
NLME_SetResponseRate( 0 );
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_ENTERPM2_EVT, myEnterpm2Period );
}
/*-------------------------------------------*/
if ( event & MY_FIND_COLLECTOR_EVT )
{
// Find and bind to a collector device
zb_BindDevice( TRUE, SENSOR_REPORT_ADC_CMD_ID2, (uint8 *)NULL );
}
} // void zb_HandleOsalEvent( uint16 event )
#define MY_PERSONAL_REPORT_VOLTAGE_EVT 0x0010 // 上报的采集电压值
#define MY_PERSONAL_COLLECT_345_EVT 0x0020
#define MY_PERSONAL_REPORT_345_EVT 0x0040 // 上报的345值
#define MY_PERSONAL_ENTERPM2_EVT 0x0080
static uint16 myAdxl345CollectPeriod = 20;
static uint16 myAdxl345ReportPeriod = 200; // milliseconds毫秒
static uint16 myEnterpm2Period = 60000;
void myApp_StopReporting( void )
{
osal_stop_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT );
osal_stop_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT );
}
void halSleep( uint16 osal_timeout )
{
static uint32 timeout; // add static for debug
uint32 macTimeout = 0;
halAccumulatedSleepTime = 0;
/* get next OSAL timer expiration converted to 320 usec units */
timeout = HAL_SLEEP_MS_TO_320US(osal_timeout);
if (timeout == 0)
{
timeout = MAC_PwrNextTimeout();
}
else
{
/* get next MAC timer expiration */
macTimeout = MAC_PwrNextTimeout();
/* get lesser of two timeouts */
if ((macTimeout != 0) && (macTimeout < timeout))
{
timeout = macTimeout;
}
}
/* HAL_SLEEP_PM2 is entered only if the timeout is zero and
* the device is a stimulated device.
*/
halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;
/* DEEP sleep can only be entered when zgPollRate == 0.
* This is to eliminate any possibility of entering PM3 between
* two network timers.
*/
#if !defined (RTR_NWK) && defined (NWK_AUTO_POLL)
if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
(timeout == 0 && zgPollRate == 0))
#else
if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
(timeout == 0))
#endif
{
halIntState_t ien0, ien1, ien2;
HAL_ASSERT(HAL_INTERRUPTS_ARE_ENABLED());
HAL_DISABLE_INTERRUPTS();
/* always use "deep sleep" to turn off radio VREG on CC2530 */
if (MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS)
{
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
/* get peripherals ready for sleep */
HalKeyEnterSleep();
#endif
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_OFF_LED3();
#else
/* use this to turn LEDs off during sleep */
HalLedEnterSleep();
#endif
/* enable sleep timer interrupt */
if (timeout != 0)
{
if (timeout > HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ))
{
timeout -= HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME );
halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ));
}
else
{
/* set sleep timer */
halSleepSetTimer(timeout);
}
/* set up sleep timer interrupt */
HAL_SLEEP_TIMER_CLEAR_INT();
HAL_SLEEP_TIMER_ENABLE_INT();
}
#ifdef HAL_SLEEP_DEBUG_LED
if (halPwrMgtMode == CC2530_PM1)
{
HAL_TURN_ON_LED1();
}
else
{
HAL_TURN_OFF_LED1();
}
#endif
/* save interrupt enable registers and disable all interrupts */
HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);
HAL_ENABLE_INTERRUPTS();
/*---------------------------------*/
// P1DIR |= 0x02;
// P1SEL &= ~0x02;
// P1_1 ^= 1;
/*P2口*/
P2SEL &= ~0x07; // 通用io
P2DIR &= ~0x09; // 设置为输入
P2INP |= 0x19;
P2 = 0x00;
/*P1口*/
P1SEL &= ~0xFF; // 通用io
P1DIR &= ~0xFF; // 设置为输入
P1INP |= 0xFC;
P1 = 0x00;
/*P0口*/
P0SEL &= ~0xFF; // 通用io
P0DIR &= ~0xFF; // 设置为输入
P0INP |= 0xFF;
P0 = 0x00;
// P1DIR |= 0x03;
// P1SEL &= ~0x03;
// P1_0 = 0;
// P1_1 = 0;
// P0DIR &= ~0x03;
// P0SEL &= ~0x03;
// P0INP |= 0x03;
// P2INP &= ~0x20; //P0口bu拉
// P0_0 = 1;
// P0_1 = 1;
OBSSEL1 |= 0x80;
OBSSEL2 |= 0x80;
OBSSEL3 |= 0x80;
OBSSEL4 |= 0x80;
OBSSEL5 |= 0x80;
//
// TR0 |= 0x01;
/*---------------------------------*/
/* set CC2530 power mode, interrupt is disabled after this function */
HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);
/*The macro HAL_SLEEP_SET_POWER_MODE() shuts down the radio and core.
Try setting a breakpoint at this location to determine if sleep is being
disallowed at some earlier point.*/
/* the interrupt is disabled - see halSetSleepMode() */
/* restore interrupt enable registers */
HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);
/* disable sleep timer interrupt */
HAL_SLEEP_TIMER_DISABLE_INT();
/* Calculate timer elasped */
halAccumulatedSleepTime += (HalTimerElapsed() / TICK_COUNT);
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_ON_LED3();
#else
/* use this to turn LEDs back on after sleep */
HalLedExitSleep();
#endif
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
/* handle peripherals */
(void)HalKeyExitSleep();
#endif
/* power on the MAC; blocks until completion */
MAC_PwrOnReq();
HAL_ENABLE_INTERRUPTS();
/* For CC2530, T2 interrupt won抰 be generated when the current count is greater than
* the comparator. The interrupt is only generated when the current count is equal to
* the comparator. When the CC2530 is waking up from sleep, there is a small window
* that the count may be grater than the comparator, therefore, missing the interrupt.
* This workaround will call the T2 ISR when the current T2 count is greater than the
* comparator. The problem only occurs when POWER_SAVING is turned on, i.e. the 32KHz
* drives the chip in sleep and SYNC start is used.
*/
macMcuTimer2OverflowWorkaround();
/*----------------------*/
P1DIR |= 0x02;
P1SEL &= ~0x02;
P1_1 ^= 1;
NLME_SetPollRate( 1000 ); // 休眠完了设置为正常的poll时间间隔
NLME_SetQueuedPollRate( 100 );
NLME_SetResponseRate( 100 );
/*重新初始化每个引脚*/
/*P0口上有P0.0、P0.1拨码开关使用时初始化|P0.2(RX)、P0.3(TX)【需要】初始化|P0.4(校准ADXL345外部中断按键)使用时初始化|
P0.5、P0.6、P0.7未使用空闲【unused pins 处理】*/
P0SEL |= 0x0C;
P0DIR &= ~0xE0;
P0SEL &= ~0xE0;
P0INP &= ~0xE0;
P2INP &= ~0x20;
/*P2口上有个LED灯*/
P1DIR |= 0x01;
P1SEL &= ~0x01;
/*P1口上P1.0(ADXL345 Supply)、P1.1、P1.2(SCL)、P1.3(SDA)使用时初始化|P1.4~P1.7作为sniffer引脚使用,可不自行初始化*/
myApp_StartReporting(); //解决外部定义问题
/*----------------------*/
}
else
{
HAL_ENABLE_INTERRUPTS();
}
}
}
void myApp_StartReporting( void )
{
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT, myAdxl345CollectPeriod );
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT, myAdxl345ReportPeriod );
}
如果你开启了power_saving功能以后,在20ms 200ms的工作过程中也会再休眠和活动状态间切换的。
能否把时间改短一点,测试下?
您好,我有个问题,在对ZStack的SampleApp的终端节点设置进入PM2工作模式时,测得的工作电流始终无法降低,正常工作时测得的电流为12mA,休眠时测得的电流为11mA或者12mA(测试方法是用万用表串入电源输入电路中,观察电流值)。
我设置终端节点设置进入PM2工作模式的步骤如下:
1.打开POWER_SAVING 预编译
2.f8wConfig_cfg 中的RFD_RCVC_ALWAYS_ON=FALSE
3.f8wConfig_cfg中四个DPoll_RATE设为0
4.ZGlobals.c中三个PollRate设为0
5.Onboard.c文件中,OnboardKeyIntEnable=HAL_KEY_INTERUPT_ENABLE
6.hal_drivers.c中if(!Hal_KeyIntEnable)中的语句关掉
7.osal_pwrmgr_init(void)中pwrmgr_attribute.pwrmgr_device=PWRMGR_BATTERY
在网上搜了不少方法,也参考了TI官方的文档“Power Management For The CC2530.pdf”,以及“Measuring Power Consumption of CC2530 with Z-Stack(swra292AN079).PDF”。
按照上述设置,感觉终端节点并未进入睡眠状态,能不能给一个比较详细的设置方法呢?
大侠,能不能给个简要的设置进入PM2模式的步骤啊?我按照下面的步骤设置,测试结果仍然是12mA左右,不知道为什么无法进入低功耗模式。
1.开启POWER_SAVING 预编译
2.f8wConfig_cfg 中的RFD_RCVC_ALWAYS_ON=FALSE
3.f8wConfig_cfg中四个DPoll_RATE设为0
4.ZGlobals.c中三个PollRate设为0
5.Onboard.c文件中,OnboardKeyIntEnable=HAL_KEY_INTERUPT_ENABLE
6.hal_drivers.c中if(!Hal_KeyIntEnable)中的语句关掉
7.osal_pwrmgr_init(void)中pwrmgr_attribute.pwrmgr_device=PWRMGR_BATTERY
你的做法太不可取了,我的问题也并没有解决!目前我在出差中,十一放假后才会上班!
在我看来,只能给你一些建议,比如你先确定是不是真的进入了pm2模式,有对应的官方参照。如果你用的是cc2530的芯片,那用仿真器打个断点试一试,看看是不是真的进入了pm2模式。这里有一段TI工程师回复的原话
/* set CC2530 power mode, interrupt is disabled after this function */
HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);
/*The macro HAL_SLEEP_SET_POWER_MODE() shuts down the radio and core.
Try setting a breakpoint at this location to determine if sleep is being
disallowed at some earlier point.*/
谢谢你的回复!
我按照你说的方法设置了断点,发现可以进入睡眠模式PM2。我用万用表的电流档测得睡眠时的电流在0.4mA-0.5mA左右,醒来发射数据的电流在1.8-3.5mA之间。
请问你测得的消耗电流是这个级别的吗?
我按照0.5mA的数值来计算,700mAh的电池,最多只能支持700/0.5=1400h=58.333天,这个时间也不像网上宣称的那样能够工作1-2年啊。
是不是我的设置方法不对?大侠你是怎么设置的呢?
发射数据的电流只有1.8-3.5mA?
不同产品的休眠功耗都不一样,取决于你的外设,我们数据手册的休眠电流PM2只代表,最小系统1uA
是否进入休眠,一方面你可以通过程序断点调试,另外你可以通过示波器测32M晶振是否间歇工作
对于休眠电流测试,最好用在供电电路中串联10欧电阻,测量两端电压。用万用表测不太准。
第一,我最后的休眠就是连两节南孚,串联万用表,电流是0.8uA
第二,把下面这段加上。虽然我没有用PA ,但我发现,它会耗电230uA左右。
OBSSEL1 |= 0x80;
OBSSEL2 |= 0x80;
OBSSEL3 |= 0x80;
OBSSEL4 |= 0x80;
OBSSEL5 |= 0x80;
第三,你看下我休眠之前的一些设置,主要就是防止引脚耗电。但不推荐放在hal_sleep.c里面
/*---------------------------------*/
// P1DIR |= 0x02;
// P1SEL &= ~0x02;
// P1_1 ^= 1;
/*P2口*/
P2SEL &= ~0x07; // 通用io
P2DIR &= ~0x09; // 设置为输入
P2INP |= 0x19;
P2 = 0x00;
/*P1口*/
P1SEL &= ~0xFF; // 通用io
P1DIR &= ~0xFF; // 设置为输入
P1INP |= 0xFC;
P1 = 0x00;
/*P0口*/
P0SEL &= ~0xFF; // 通用io
P0DIR &= ~0xFF; // 设置为输入
P0INP |= 0xFF;
P0 = 0x00;
// P1DIR |= 0x03;
// P1SEL &= ~0x03;
// P1_0 = 0;
// P1_1 = 0;
// P0DIR &= ~0x03;
// P0SEL &= ~0x03;
// P0INP |= 0x03;
// P2INP &= ~0x20; //P0口bu拉
// P0_0 = 1;
// P0_1 = 1;
OBSSEL1 |= 0x80;
OBSSEL2 |= 0x80;
OBSSEL3 |= 0x80;
OBSSEL4 |= 0x80;
OBSSEL5 |= 0x80;
//
// TR0 |= 0x01;
/*---------------------------------*/
第四 ,引脚或者外设耗电。比如说我当初有个3K的电阻上拉电源,下面接地,设计为拨码开关,这样的话,也会耗电。看看你的引脚吧
你也可以按照VV的说法,毕竟人家是万人景仰的TI大神,这个最权威了!真心的
请问一下VV,pm2模式唤醒之后,程序运行的哪里呢?是reset了吗?
@wing burst
能不能留个联系方式?或则你加我的
现在时间是2015年8月13日。我刚刚费了好大劲才把密码找回来,登了上来。我已经辞职两年了,现在转行了在送快递。留了QQ号码实在是不堪其忧,如果大家要是有送快递的,也请不要联系我了!希望我的帖子,能对新人有所启发,研发永远不要见了!
@阳春三月
休眠定时器到的时候有两种方式,一种是中断,一种检测标志位
在协议栈里面HAL_SLEEP_PREP_POWER_MODE这个函数中在检测标志位,
休眠结束,程序往后执行。
OSAL的Timer时间是并行,你要自己安排好EVENT的时间队列,最好用笔画一个时间轴出来。
目前我做的程序就是你说的那种时间控制的,我就是通过EVENT的TIMEOUT来控制休眠的,没有发现时间会误差的。
PM2模式完全可以做到休眠的:中断唤醒,睡眠唤醒,我已经实现了,当没有event要触发的时候就进入中断唤醒了,我看过PM2的代码,里面有这方面的控制代码,很好理解。
@Fred Wang
您能详细说一下什么是“EVENT的时间队列”吗?
我的sapi任务有三个event。
第一个event只是用来采集,周期20ms。第二个event只是用来发送,周期200ms。第三个event进入后,关掉前两个事件,然后设置三个poll_rate为0(因为我理解的poll_rate也是属于timer),周期是30s。
这样,让他自动进去休眠,然后在hal_sleep.c里面唤醒以后,我再将poll_rate设置为正常值(1000,100,100),然后使用myApp_StartReporting();再次设置sapi的前两个event,让系统执行。
我在进入第三个event以后,已经关掉了前两个event了啊?怎么还会有,你说的“时间队列”了呢?
我这样设置的时候发现,休眠时间确实是30s,但是工作时间是30s-8s=22s。如果做一次累加计数,他的工作时间是2*30s-8s=52s。不知道这个8s是为什么?
如果我把这个周期设置为60s,休眠时间也是60s,但是工作时间大部分时间是60s-8s=52s,或者就成了2*60s-8s=112s,给人感觉好像第三个进入休眠的event没有响应。
首先非常感谢你的回复,万分感谢。我说的有点长,问题已经卡住半个月了,我也很苦恼。如果您方便,还请再给一些指点,感激不尽
@VV
我刚看了一下,我用的协议栈zstack-2.2.2-1.3.0真的没有HAL_SLEEP_PREP_POWER_MODE这个函数
但是在休眠的时候,我Breakpoint,发现会经常停在
void halSetSleepMode(void)
{
PCON = PCON_IDLE;
HAL_DISABLE_INTERRUPTS();
}
不知道,是不是你所说的那个,检测标志位呢?
非常感激 @VV
用EVENT画一个时间轴出来,通过osal_start_timerEx和osal_stop_timerEx来控制EVENT触发的时间。
首先你要确保没有其他EVENT在执行了,可以通过不启动这三个事件来测试,正常情况模块应该完全休眠,休眠也同时会断开连接,下一周期的连接需要重新通过广播来建立。(可以通过常亮一个LED来观察,休眠LED灭,工作LED是亮,HAL_LED里有休眠关闭的代码)
时间轴规划:
EVENT 周期开始 周期结束
采集 start 20ms
发送 start 200ms
下一周期 end 采集,发送,start 40s 超时后会下一周期
osal timer是一个简单的定时器,好比是一个倒计时秒表,计时超时后,就向EventProcess事件发送EVENT消息,时间轴规划好就行了。
@Fred Wang
首先,我关闭了三个事件来测试,模块确实是完全休眠了。
其次,按照您的说法,我规划了一个时间轴如下:
Event 周期开始 周期结束
-----------------------------------------------------------------第一个周期
采集 start① 20ms
发送 start① 200ms
休眠 start① 40s end①采集,发送。获取唯一剩下的休眠事件,时间为40s。休眠40s
-----------------------------------------------------------------下一个周期,休眠40s后开始
采集 start② 20ms
发送 start② 200ms
休眠 start② 40s end②采集,发送。获取唯一剩下的休眠事件,时间为40s。休眠40s
-----------------------------------------------------------------下一个周期,休眠40s后开始
......以此类推
像你说的,三个event是并行的,而且40s一定是20ms和200ms的公倍数。按照这么来说,工作的时间一定就是40s了,可是他是不准确的,并且是不可控的。
这几天放假我也在想这个问题,一直是没想通。如果您看到了回复,还请多给些指点,恕我愚笨多有打扰
你好,我想请问下您的休眠时间是怎么设置的。我的节点休眠时间设置20s以上就无法正常收到数据。 如果您有空,帮我解决一下这个问题,谢谢了。我是在sample例程上修改的。 具体修改如下:
1.编译增加POWER_SAVING
2.在f8wConfig.cfg中修改四个POLL为0
3.在OnBoard.c中修改
OnboardKeyIntEnable=HAL_KEY_INTERUPT_ENABLE
4. 在程序中加入
osal_pwrmgr_device(PWRMGR_BATTERY);
osal_pwrmgr_task_state(GenericApp_TaskID,PWRMGR_CONSERVE);
5.用osal_start_timerEx(GenericApp_TaskID,SEND_DATA_EVENT,10000);来定休眠时间。
我也没做出来,我辞职了,这辈子再不干研发了!
现在时间是2015年8月13日。我刚刚费了好大劲才把密码找回来,登了上来。我已经辞职两年了,现在转行了在送快递。留了QQ号码实在是不堪其忧,如果大家要是有需要快递的,也请不要联系我了!希望我的帖子,能对新人有所启发,研发永远不要见了!
研发的确有些苦逼。。T T 不过还是继续努力看下怎么弄好了。
@阳春三月
osal_timer是系统时钟,是一个RTC,timeout是从开始时开始计算的,所以事件周期是依据你的代码进行的。
各个事件看似是并行的线程,其实只是通过RTC系统虚拟出来的,如果两个事件在同一个Real Time触发了,那肯定会有一个事件晚了一点,不过这并不影响其他不冲突事件的执行时间,所以我们可以近似把他们看成是并行线程。
@jack
设置了POWER_SAVING就是开启了PM2模式,系统在没有事件需要执行的时候会自动进入休眠,不需要再增加睡眠事件,你只需要调整好需要执行的事件就行了,比如:周期性唤醒事件,广播事件等等。注意,此模式下如果 没有下一次周期事件,会自动进入PM3模式,然后就只能通过IO中断唤醒了,而且osal_clock会停止计时,所以最好写一个周期性唤醒任务,周期可以设置的比较长,事件不需要执行什么特殊指令,只要能唤醒芯片,维持时钟计时就行了。
居然没有后文了。VV大神怎么没有出来解决
原因在于早期版本的协议栈osal timer函数参数是16bit的,现在改成32bit,应该不会出现这个问题了
嗯,有可能是这个问题,就是zstack-2.5.1a都改过来了对吧?
另外想问一下VV大神,用zstack-2.5.1a的终端节点和用zstack-2.0(或者更老的版本)的协调器通信会不会出现问题?在对比文件的过程中,发现zstack-2.5.1a比老版本修改了很多。
最后感谢VV大神给我每个提问都回复了。
2.5.1a也是好几年前的协议栈了,现在最新的是2.6.1.x
你可以下载Z-Stack Home 1.2.0 就可以看到了
通信不好有问题,但是协议栈是在不断的添加新的功能,以及bug的修复的,所以建议使用最新版本的。
还有一个问题,考虑到把现有程序改到新协议栈比较麻烦,我想问下是否可以在旧版本里面把osal time函数参数16bit改成32bit?如果可以需要修改哪些文件?
嗯,最新版本是2.6.x,昨天下载了Z-Stack Home 1.2.0看了一下,在版本更新信息里面提到了需要IAR更高的版本,和RF05EB;结果确实无法打开工程,烧录器也只是RF04EB的,短时间能软硬件环境无法跟上。所以求助一下,看能否在现有版本进行一些修改。
你好,假如我调用这个函数osal_start_timerEx(GenericApp_TaskID,SEND_DATA_EVENT,10000);每隔10s去激活一次SEND_DATA_EVENT事件爱你,我系统中只有这一个事件,处理完之后,在等待下一次事件发生时会自动进入休眠模式吗?然后10S时间到了,会自动进入自动模式处理SEND_DATA_EVENT,如此反复执行吗?
只要10s钟的这个事件,是所有事件里面最短的一个,休眠时间就是10s。下次唤醒会自动执行该事件!
请教TI工程师和各位大神们:
我在终端设备的协议栈程序中通过函数
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF) ));来实现定时广播数据,在HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode);加断点程序会运行到此处,指示联网状态的LED在入网后熄灭,只有定时广播数据时才会闪烁(程序设置发送时闪烁),看起来是进入PM2状态了吧,电流我还没有测量。现在有个问题就是,我需要按键唤醒,同时广播一条数据给路由器,然后等待路由器广播回复。设置了POWER_SAVING之后,终端设备就接收不到数据了,这是什么原因呢?我该怎么设置?
我只是宏定义了POWER_SAVING,-DRFD_RCVC_ALWAYS_ON=FALSE,还有几个POLL_RATE都设成了0,路由器宏定义了NV_RESTORE。
我看了有资料说终端设备在定时器或外部中断唤醒后会去有一个DataRequest的原语去向父节点询问是否有发给自己的数据,我这里是父节点直接广播应答不是有目的地址的点对点发送数据,不知道问题是出在这里吗?
广播的地址是0xFFFF,对于Power Saving的end device来说也是indirect message,广播的数据也是保存在父节点的buffer里面,当子节点发送来data request的时候把广播数据发给它,你现在把POLL_RATE改成了0,相当于没有data request了。
请问 终端睡眠问题你解决了嘛
现在没什么问题了 协议栈正常休眠
为什么协议栈睡眠啊 一般协议栈都是通电的 节能的话 没必要啊
我是想问问终端睡眠的 一些问题
就是睡眠时间的问题
你好,你是怎么设置断点进入PM2模式的啊?
您好,在这个论坛里看到您解决了CC2530休眠的问题,想跟您请教一下,我想利用定时器,让终端定时休眠,比如工作5s,休眠10s,可是现在进入休眠之后,一直唤醒不了了,您是怎么解决的?方便告知一下吗?谢谢
你进入的是PM2模式还是PM3模式?如果是通过协议栈休眠,只要在预编译里定义POWER_SAVING,协议栈会判断操作系统是否有Task要处理,如果有并且到时间,就唤醒处理,如果有Task但没到时间,就进入PM2休眠。如果没有Task就进入PM3休眠。一旦进入PM3,就需要外部IO中断或定时器中断来唤醒。
你需要添加的Task可以用下面这个函数定时来执行,参数是我的工程里的,你自己定义:
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF) ));
十分感谢您的回答,可以再问一下需要在Onboard.c中做以下更改吗?
将OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;改为OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;
我参照了一下TI的Power Management For The CC2530.pdf这个文档,上面说需要将OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;,但是我改过之后数据就再也收不到了
这个参数只是按键轮询检测还是中断检测的设置,应该不会影响休眠
好的 谢谢~
大神 能不能一起讨论下 ,我现在做睡眠
对于设置低功耗的问题困惑了好久,不知道它是怎么进入睡眠的,睡眠后又是怎样唤醒的(有唤醒函数吗),方便的话,给个学习的例程吧
@阳春三月,你好!我设置断点了,HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode);查看halPwrMgtMode等于0x02;但是好像设置其他断点,这个值一直不变,那就是没有唤醒了吧
@wing burst
您好,我的方法设置协议栈进入PM2之后,功耗为1.4uA噢。
Fred Wang 你好,有个问题请教一下:我的任务也有三个周期性事件,20ms,200ms,和3s的,但是发现pwrmgr_attribute.pwrmgr_task_state==2,进不到osal_set_cpu_into_sleep(next);怎么回事啊??谢谢
阳春三月:你这个协议栈代码方便发我一份么?
遇到同样的问题了,太纠结了,
谢谢,1021256354@qq.com,再次谢谢
@roger huang1
你好!可以加我QQ麽,402732326. 我现在也遇到一个需要在协议栈上修改进入PM2模式的问题困扰。具体要设置哪些参数?
你好,请问你的终端节点休眠的问题解决了么?可否加我QQ:402732326.
我现在需要你的帮助呢。谢谢!
W大侠,您好。我现在设备进入低功耗OK,每隔10秒钟唤醒一次,并发送1包32字节的数据,然后再次进入休眠。想请教下,如何计算出发送32字节所需要的功耗或电流之类的参数?我现在需要这个参数来确定设备的电池容量选型。如果无法计算,采用什么样的方式进行测量比较可行,需要什么设备?谢谢!
@huang shangjian 你好。你是怎么进去的?可以加你QQ求教麽?谢谢!我的QQ:402732326
我写了操作总结,不是很复杂,有问题再沟通吧。
http://www.deyisupport.com/questione/f/104/t/105541.aspx_answer/wireless_connectivity/zigbe
@huang shangjian 链接打开了显示找不到论坛已删除。
to:Sir Lee1 ,http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/105541.aspx
我设置了PM2模式,可是还是有10~20uA的功耗,大神,能否交流下呢?
@阳春三月,大虾,求做朋友!邮箱:1791322858@qq.com
你好:
我想问问你,CC2530芯片,用的2007Pro协议栈,传感器终端我让他终端睡眠唤醒,(PM2) 他从睡眠到唤醒发送数据,再接收协调器的确认数据,然后再休眠,这段时间是多少mS , 需要怎么做才能知道呢 这是我的邮箱892781037@qq.com
@ VV
请问 一下, 一个设备 做了以下操作:
1. POWER_SAVING
2. ISR_KEYINTERRUPT
3. -DRFD_RCVC_ALWAYS_ON=FALSE
-DPOLL_RATE=0
-DQUEUED_POLL_RATE=0
-DRESPONSE_POLL_RATE=0
是不是 就意味 着 设备 进入了 PM3 ???
进入PM3 的设备 在消息发出之后没有收到ACK ,超出重复次数后, 它是否会开启寻网?
如果应用程序中 调用了osal_start_timerEx(), 而且osal_start_timerEx() 的事件已经到时 执行完了。 那么 设备是否会从新就进入 PM3?
还是说 一旦调用osal_start_timerEx(),设备就 永远进不了 PM3 ?
你好@huang shangjian
请问您知道怎么设休眠时间为500s,我现在用osal_start_timerEx();只能延时65s,这个问题困扰我好几天了,能够加你qq请教一下吗?我的qq是1714040125