这是一个AVR的例子: #include <libRain_Base.h> #include <libRain_M169.h>
#include "DriverLcdDrvLcdDrv.h" #include "DriverDADA.h" #include "DriverLEDLED.h" #include "DriverSysIdleSysIdle.h"
#include "TaskTask.h"
//-------------------------------------------------------- //主初始化 //-------------------------------------------------------- void Main_Init( void ) { ACSR |= (1<<ACD);
Memory_InitDefault(); SysTimer_Query_Init( SYSTIMER_QUERY_FREQ_3M6864 );
//驱动 LcdDrv_Init(); DA_Init(); ADC_Init( ADC_REF_AVCC, ADC_3p6864MHz_115p2KHz ); LED_Init(); SysIdle_Init();
Msg_InitDefault( 30 ); DdFilter_Init();
//Task Task_Init(); }
//-------------------------------------------------------- //主析构 //-------------------------------------------------------- void Main_Destory( void ) { cli(); Task_Destory();
DdFilter_Destory(); Msg_Destory();
//驱动 SysIdle_Destory(); LED_Destory(); ADC_Destory(); DA_Destory(); LcdDrv_Destory();
SysTimer_Query_Destory(); Memory_Destory(); }
//-------------------------------------------------------- //主程序 //-------------------------------------------------------- int main( void ) { Main_Init();
Lcd_LowPower_Enable();
sei(); while(1){ Memory_MainLoop();
Msg_MainLoop(); SysTimer_Query_MainLoop(); //必须放在此处,紧接消息和系统时间模块 SysIdle_MainLoop();
//驱动 ADC_MainLoop(); DA_MainLoop(); LcdDrv_MainLoop(); LED_MainLoop();
DdFilter_MainLoop();
//Task Task_MainLoop(); } }
因为是事件驱动,所以无事件和中断时自动进入IDLE省电。只要遵守事件驱动原则,任何规模的程序都可以这样简单的省电操作。 事件驱动:状态变化时触发处理。这里采用消息队列存储发生的事件。
SysIdle.c:
//------------------------------------------------------------- //运行中空闲模式 //------------------------------------------------------------- #include <libRain_Base.h> #include <libRain_M169.h>
//------------------------------------------------------------- //省电模式 //------------------------------------------------------------- void InSysIdle_Idle( void ) { U8 mTemp; mTemp = TIMSK0; TIMSK0 |= ( 1<<OCIE0A ); SMCR = (1<<SE) | (0<<SM2)|(0<<SM1)|(0<<SM0); //空闲模式 __asm__ __volatile__("SLEEP"); TIMSK0 = mTemp; }
//------------------------------------------------------------- //运行中空闲 //消息空且系统时间未触发,进入。中断退出。 //------------------------------------------------------------- void SysIdle_Loop( void ) { if( ( sMsg.aReadMsgBuffer[0] == 0 ) && ( !sSysTimer.bSysTouch ) ) { //无消息发出, 无系统时间触发,开始进入空闲模式 InSysIdle_Idle(); } }
//------------------------------------------------------------- //T0中断 //因系统时间使用T0查询,退出省电模式需中断,故有此函数.中断产生不用. //------------------------------------------------------------- SIGNAL( SIG_OUTPUT_COMPARE0 ) { sSysTimer.bSysTouch = true; TIMSK0 &= ~( 1<<OCIE0A ); } |