STM32等类似Cortex-M3的MCU在系统或电源复位以后,MCU就会处于程序运行状态。当用户不需继续运行程序时,可以利用进入低功耗模式来节省电池电量,当需要重新运行时,可以通过特定条件进行唤醒程序继续或重新工作。特别是在电池供电的智能终端上有着比较广泛的应用。 STM32F103三种低功耗模式状态说明: 1、睡眠模式:内核停止运行,所有外设仍然处于工作状态。 2、停止模式:所有的时钟都已停止,调压器可以被置于普通模式或低功耗模式。 3、待机模式:所有的时钟都已停止,内部1.8V部分的供电被切断,电压调节器关闭。可以达到最低的电能消耗。
三种模式电流功耗大小排序为: 运行 > 睡眠 > 停止 > 待机。 其中运行模式与睡眠模式功耗为mA级,停止模式与待机模式为uA级,其中待机最小可以达到<5uA。 如何进入? 睡眠模式: 执行WFI或WFE指令可以使MCU进入睡眠状态。
停止模式: 在以下条件下执行WFI或WFE指令: 1、设置Cortex-M3系统控制寄存器中的SLEEPDEEP位; 2、清除电源控制寄存器(PWR_CR)中的PDDS位 进入; 3、通过设置PWR_CR中LPDS位选择电压调节器的模式;
待机模式: 在以下条件下执行WFI或WFE指令: 1、设置Cortex-M3系统控制寄存器中的SLEEPDEEP位; 2、设置电源控制寄存器(PWR_CR)中的PDDS位; 3、清除电源控制/状态寄存器(PWR_CSR)中的WUF位; 如何退出? 睡眠模式: 如果是执行WFI指令进入睡眠模式,任意一个外设中断都能将系统从睡眠模式唤醒。如果是执行WFE指令进入睡眠模式,一旦发生唤醒事件时,微处理器都将从睡眠模式退出。
停止模式: 如果是执行WFI进入停止模式,任一外部中断线为中断模式可以唤醒。如果是执行WFE进入停止模式。任一外部中断线为事件模式可以唤醒。
待机模式: 待机模式唤醒只有4种:外部复位、IWDG复位、WKUP引脚上的上升沿或RTC闹钟事件的上升沿。并且从待机唤醒后,除了电源控制/状态寄存器,所有寄存器被复位。唤醒后的代码执行等同于复位后的执行。
睡眠模式进入与退出:
停止模式进入与退出
待机模式进入与退出 待机模式是功耗最低的一种模式,外部复位、IWDG复位、WKUP引脚上的上升沿比较简单。主要实验RTC闹钟事件唤醒。RTC具有三个中断源:秒中断、闹钟中断与溢出中断。 首先配置开启中断分组与电源控制器时钟: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
然后配置RTC模块参数,由于使用的是外部32.768K的晶振: RTC_SetPrescaler(32767);可以实现1S1次计数。
开启RTC_IT_ALR闹钟中断: RTC_ITConfig(RTC_IT_ALR, ENABLE);
配置闹钟参数: RTC_SetAlarm(RTC_GetCounter() + SLEEP_TIME);SLEEP_TIME就是多长时间发生一次闹钟。 RTC配置代码: void RTC_Init(void)
{
u16 BKP_Value = 0x5A5A;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
if(BKP_ReadBackupRegister(BKP_DR1) != BKP_Value) {
PWR_BackupAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)IWDG_ReloadCounter();
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_SetCounter(0);
RTC_WaitForLastTask();
RTC_SetAlarm(RTC_GetCounter() + SLEEP_TIME);
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_WaitForLastTask();
BKP_WriteBackupRegister(BKP_DR1, BKP_Value);
RTC_WaitForLastTask();
PWR_BackupAccessCmd(DISABLE);
} else {
PWR_BackupAccessCmd(DISABLE);
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_WaitForLastTask();
}
}
RTC中断代码:在中断中重新清除相关标志并重新配置参数。 void RTC_IRQHandler(void)
{
IWDG_Feed();
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) {
RTC_ClearITPendingBit(RTC_IT_SEC);
}
if(RTC_GetITStatus(RTC_IT_ALR)!= RESET) {
RTC_ClearITPendingBit(RTC_IT_ALR);
PWR_BackupAccessCmd(ENABLE);
RTC_WaitForLastTask();
RTC_SetAlarm(RTC_GetCounter() + SLEEP_TIME);
RTC_WaitForLastTask();
PWR_BackupAccessCmd(DISABLE);
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET) {
PWR_ClearFlag(PWR_FLAG_WU);
}
if(PWR_GetFlagStatus(PWR_FLAG_SB) != RESET) {
PWR_ClearFlag(PWR_FLAG_SB);
}
}
这样就可以实现在任务代码中调用PWR_EnterSTANDBYMode();进入低功耗,MCU会在每隔SLEEP_TIME之后进行唤醒, 可以通过该办法周期性唤醒实现上电必要端口检测等条件来确定是否进入运行模式或者是继续进入低功耗模式来节约电池电量。 说明:RTC配置部分已经经过实验确定可以周期唤醒,有需要的可以直接使用。
|