微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI Zigbee设计交流 > 求助,关于CC2530在osal调度下PM2模式休眠和工作时间问题?

求助,关于CC2530在osal调度下PM2模式休眠和工作时间问题?

时间:10-02 整理:3721RD 点击:

请教一个问题
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

        

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top