大家都知道2430有3種睡眠模式,pm2模式比較省功耗而且可以被定時喚醒;pm3模式最省電但是只能被外部中斷喚醒。開啟睡眠功能很簡單:
首先確認(rèn)\Texas Instruments\ZStack-1.4.3-1.2.1\Projects\zstack\Tools\CC2430DB目錄下的f8wConfig.cfg文件中DRFD_RCVC_ALWAYS_ON定義為FALSE;
然后在IAR的Options->C/C++Compiler->Defined symbols中添加“POWER_SAVING”;
最后在Options->Linker->Linker command line里面把f8w2430.xcl改為f8w2430pm.xcl。 在定義“POWER_SAVING”宏以后OSAL.c中的osal_start_system()函數(shù)里面就會調(diào)用 osal_pwrmgr_powerconserve()函數(shù)。osal_pwrmgr_powerconserve()函數(shù)把獲取os層timer的下一次的到時時間作為參數(shù),調(diào)用hal_sleep()進(jìn)入pm2睡眠模式,如果當(dāng)前沒有任務(wù)那么將進(jìn)入pm3。所以說一旦啟用省電模式,系統(tǒng)將根據(jù)當(dāng)前的任務(wù)自動進(jìn)入睡眠,睡眠前設(shè)置sleeptimer,醒來的時間剛好等于下次任務(wù)到來的時間,當(dāng)完成任務(wù)后再次進(jìn)入睡眠。 ZStack中的hal_sleep()函數(shù)功能比較多,看著比較頭暈,所以我寫了一個簡化版本供大家來討論:
01 void halSleep ( uint16 osal_timeout )
02 {
03 uint32 timeout = 0 ;
04 halIntState_t intState , ien0 , ien1 , ien2 ;
05
06 /* 把osal_timeout 轉(zhuǎn)換為320微秒為單位 */
07 timeout = HAL_SLEEP_MS_TO_320US (osal_timeout );
08
09 /*如果osal_timeout 小于最小安全睡眠時間*/
10 if (timeout < HAL_SLEEP_MS_TO_320US (PM_MIN_SLEEP_TIME ))
11 {
12 return ;
13 }
14 /*如果osal_timeout 大于sleeptimer最大范圍*/
15 else if (timeout > HAL_SLEEP_MS_TO_320US ( MAX_SLEEP_TIME ))
16 {
17 timeout = HAL_SLEEP_MS_TO_320US ( MAX_SLEEP_TIME );
18 }
19
20
21 HAL_ENTER_CRITICAL_SECTION (intState );
22 if (MAC_PwrOffReq (MAC_PWR_SLEEP_DEEP ) == MAC_SUCCESS )/* 關(guān)閉RF*/
23 {
24 /* 切換外部時鐘*/
25 HAL_SLEEP_SET_MAIN_CLOCK_RC ();
26
27 /* 設(shè)置sleeptimer到時時間 */
28 halSleepSetTimer (timeout );
29 /* 設(shè)置sleeptimer中斷 */
30 HAL_SLEEP_TIMER_CLEAR_INT ();
31 HAL_SLEEP_TIMER_ENABLE_INT ();
32
33 /* 保存其他所有中斷,并屏蔽 */
34 HAL_SLEEP_IE_BACKUP_AND_DISABLE (ien0 , ien1 , ien2 );
35
36 /* This is to check if the stack is exceeding the disappearing
37 * RAM boundary of 0xF000. If the stack does exceed the boundary
38 * (unlikely), do not enter sleep until the stack is back to normal.
39 *保證棧在異常邊界不進(jìn)入睡眠模式,具體原因不是很清楚,為了安全還是加上
40 */
41 if ( ((uint16 )(* ( __idata uint16 * )(CSTK_PTR )) >= 0xF000 ) )
42 {
43 HAL_EXIT_CRITICAL_SECTION (intState );
44
45 /* 此處直接進(jìn)入pm2,程序運行在此處停止,直到sleeptimer到時,再接著向下運行 */
46 HAL_SLEEP_SET_POWER_MODE (CC2430_PM2 );
47
48 HAL_ENTER_CRITICAL_SECTION (intState );
49 }
50
51 /* 恢復(fù)中斷 */
52 HAL_SLEEP_IE_RESTORE (ien0 , ien1 , ien2 );
53
54 /* 關(guān)掉sleeptimer中斷 */
55 HAL_SLEEP_TIMER_DISABLE_INT ();
56
57 /* 設(shè)置晶振*/
58 HAL_SLEEP_SET_MAIN_CLOCK_CRYSTAL ();
59
60 /* 打開RF*/
61 MAC_PwrOnReq ();
62
63 /*調(diào)整回系統(tǒng)時間*/
64 osal_adjust_timers (osal_timeout );
65
66 }
67
68 HAL_EXIT_CRITICAL_SECTION (intState );
69 }
在應(yīng)用方面,以Samples中的GenericApp為例。在GenericApp.c中,GenericApp_ProcessEvent里面有一個 GENERICAPP_SEND_MSG_EVT消息,該消息會用GenericApp_SendTheMessage()給coordinater發(fā)送一個“Hello World”字符串。發(fā)送后設(shè)置Timer來再次觸發(fā)此消息,時間間隔為5秒鐘。我們可以把下面這句添加進(jìn) GenericApp_Init()函數(shù)里,這樣的話系統(tǒng)上電后就啟動此任務(wù),5秒發(fā)送一次“Hello World”:
osal_start_timerEx( GenericApp_TaskID,GENERICAPP_SEND_MSG_EVT,GENERICAPP_SEND_MSG_TIMEOUT );
我們可以按照上面的方法寫一個自己需要的任務(wù)來完成某種功能,比如說隔一段時間采集溫度,然后把數(shù)據(jù)發(fā)送出來。
|