本文参考:STM32F10XXX参考手册,具体细节可自行去官网下载查看。
1. 为什么要使用低功耗模式?
- 延长电池寿命(例如:传感器节点、可穿戴设备)
- 降低系统发热量
- 在非关键任务阶段减少能耗,提高整体能效
2. STM32F10x系统电源框图
STM32的工作电压(VDD)为2.0~3.6V。通过内置的电压调节器提供所需的1.8V电源 。
当主电源VDD掉电后,通过VBAT脚为实时时钟(RTC)和备份寄存器提供电源。

3. PWR电源控制寄存器简介
PWR(Power Control)电源控制负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。
可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务。

电源控制/状态寄存器(PWR_CSR)中的PVDO标志用来表明VDD是高于还是低于PVD的电压阀值。该事件在内部连接到外部中断的第16线,如果该中断在外部中断寄存器中是使能的,该事件就会产生中断。
4. STM32 的低功耗模式分类
在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。
STM32F10xxx有三种低功耗模式:
● 睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)
● 停止模式(所有的时钟都已停止)
● 待机模式(1.8V电源关闭)
此外,在运行模式下,可以通过以下方式中的一种降低功耗:
● 降低系统时钟
● 关闭APB和AHB总线上未被使用的外设时钟。
使用下面三种方式之前务必需要打开PWR的时钟。
c
__HAL_RCC_PWR_CLK_ENABLE();
4.1 睡眠模式
- 执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
- SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠
- 在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态
- WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
- WFE指令进入睡眠模式,可被唤醒事件唤醒
c
/**
* @brief Enters Sleep mode.
* @note In Sleep mode, all I/O pins keep the same state as in Run mode.
* @param Regulator: Regulator state as no effect in SLEEP mode - allows to support portability from legacy software
* @param SLEEPEntry: Specifies if SLEEP mode is entered with WFI or WFE instruction.
* When WFI entry is used, tick interrupt have to be disabled if not desired as
* the interrupt wake up source.
* This parameter can be one of the following values:
* @arg PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
* @arg PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
* @retval None
*/
void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
其中在该接口上,Regulator并没有使用,SLEEPEntry可以选择WFI(等待中断)或者WFE(等待事件)两种模式,一般使用配置WFI即可。
4.2 停止模式
- 执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
- 1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来
- 在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态
- 当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟
- 当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
- WFI指令进入停止模式,可被任意一个EXTI中断唤醒
- WFE指令进入停止模式,可被任意一个EXTI事件唤醒
c
/**
* @brief Enters Stop mode.
* @note In Stop mode, all I/O pins keep the same state as in Run mode.
* @note When exiting Stop mode by using an interrupt or a wakeup event,
* HSI RC oscillator is selected as system clock.
* @note When the voltage regulator operates in low power mode, an additional
* startup delay is incurred when waking up from Stop mode.
* By keeping the internal regulator ON during Stop mode, the consumption
* is higher although the startup time is reduced.
* @param Regulator: Specifies the regulator state in Stop mode.
* This parameter can be one of the following values:
* @arg PWR_MAINREGULATOR_ON: Stop mode with regulator ON
* @arg PWR_LOWPOWERREGULATOR_ON: Stop mode with low power regulator ON
* @param STOPEntry: Specifies if Stop mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg PWR_STOPENTRY_WFI: Enter Stop mode with WFI instruction
* @arg PWR_STOPENTRY_WFE: Enter Stop mode with WFE instruction
* @retval None
*/
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
//example
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
停止模式可以选择电压调节器开启或者是低功耗,使用过程没有什么差别,两种方式差别主要是低功耗消耗能量更少,并且同样有WFI和WFE两种模式。
当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟,因此当退出停止模式的时候,需要在唤醒的中断或者事件回调函数中重新初始化系统主频,否则会导致系统工作异常。
4.3 待机模式
- 执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
- 整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电
- 在待机模式下,所有的I/O引脚变为高阻态(浮空输入)
- WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式
c
/**
* @brief Enters Standby mode.
* @note In Standby mode, all I/O pins are high impedance except for:
* - Reset pad (still available)
* - TAMPER pin if configured for tamper or calibration out.
* - WKUP pin (PA0) if enabled.
* @retval None
*/
void HAL_PWR_EnterSTANDBYMode(void)
直接调用该接口即可进行待机模式,待机模式只有四种事件能够将其唤醒,如上一句话所说,因此需要配置所需的唤醒方式。
实际测试采用WKUP上升沿以及RTC闹钟事件两种方式。
- WKUP上升沿
c
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
该接口会模式配置WKUP引脚为输入下拉模式,当获取到上升沿即会自动唤醒MCU。
- RTC闹钟模式
c
HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
使用该模式需要对RTC进行初始化以及配置RTC_Alarm中断事件,使能NVIC等操作,RTC_Alarm事件是挂在EXTI线中断上的。
- ! 注意使用待机模式,由于1.8V供电区域会断电,SRAM和寄存器内容会丢失,因此MCU会重新复位,不会继续向下运行,实测发现需要在程序开头手动清除唤醒和Standby标志,接口如下,否则下一次调用HAL_PWR_EnterSTANDBYMode程序就直接复位重启了,不会进入休眠。
c
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // 清除唤醒标志
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); // 清除 Standby 标志
猜测可能是PWR寄存器不在1.8V供电区域内,而在VDD供电区域,因此1.8V掉电不影响PWR寄存器,需要手动进行清除,否则会影响下一次进入/退出低功耗。