第4章 低功耗模式概览:五种模式的特点与切换

做嵌入式开发,尤其是电池供电的项目,功耗管理是绕不开的坎。STM32 提供了五种功耗模式,从「全速跑」到「几乎关机」,各有各的用武之地。我刚开始接触低功耗设计时,总觉得模式越多越复杂,后来才发现——选对模式,比写一堆优化代码更管用。

这一章,咱们把这五种模式掰开揉碎,看看它们各自的特点、适用场景,以及怎么在代码里切换。

5种模式,一张表说清楚

先来个全景图。我习惯把 STM32 的功耗模式想象成「五档变速」:

模式 CPU状态 SRAM/寄存器 外设时钟 唤醒源 典型功耗
运行 (Run) 运行 全部保留 全开 — ~100μA/MHz
睡眠 (Sleep) 暂停 全部保留 全开 任何中断/事件 ~50μA/MHz
停止 (Stop) 关 全部保留 部分关闭 EXTI、RTC、USB等 ~2-10μA
待机 (Standby) 关 仅备份域 几乎全关 WKUP引脚、RTC、NRST ~0.3-2μA
关机 (Shutdown) 关 全部丢失 全关 WKUP引脚、NRST ~0.1μA

嗯,这张表值得你截图保存。后面每个模式我都会展开讲,但先记住一个原则:功耗越低,唤醒代价越大。

运行模式——默认状态,没什么好说的

运行模式就是芯片上电后的默认状态。CPU 全速跑,所有外设时钟都开着。说白了,这就是「不省电模式」。如果你的项目对功耗没要求,那就不用往下看了。

但实际项目中,大部分时间芯片其实不需要全速运行。比如一个温度传感器,每秒采集一次数据,剩下 999ms 都在空转——这就是浪费。

我的习惯: 在 main 函数里,做完初始化后,立刻根据当前任务需求切换到合适的低功耗模式。别让芯片在运行模式里「空转」。

睡眠模式——CPU 歇着,外设继续干活

睡眠模式是最轻量的低功耗模式。CPU 暂停执行指令,但 SRAM、寄存器、外设时钟都保持原样。任何中断都能把它唤醒,而且唤醒速度极快——几乎就是几个时钟周期的事。

怎么进睡眠?HAL 库提供了两个函数:

// 进入睡眠模式(WFI:等待中断)
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);

// 进入睡眠模式(WFE:等待事件)
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFE);

WFI 和 WFE 的区别?简单说:WFI 靠中断唤醒,WFE 靠事件唤醒。我一般用 WFI,因为中断模型更直观。

适用场景: 需要频繁响应中断,但 CPU 不需要持续计算的任务。比如按键扫描、串口接收等待。

停止模式——深度睡眠,但保留现场

停止模式就有点意思了。CPU 停了,主时钟也停了,但 SRAM 和寄存器内容全部保留。这意味着你醒来后,程序可以接着往下跑,就像什么都没发生过。

进入停止模式时,可以选择电压调节器的工作模式:

  • MR(主调节器):唤醒快,功耗稍高
  • LPR(低功耗调节器):唤醒慢,功耗更低

代码示例:

// 进入停止模式,使用低功耗调节器
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

唤醒停止模式,需要配置 EXTI 中断。比如用 RTC 闹钟唤醒:

// 配置 RTC 闹钟(略)
// 进入停止模式
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

// 醒来后,需要重新配置系统时钟
SystemClock_Config();
我曾经踩过的坑: 从停止模式唤醒后,HSE、PLL 等时钟源都停了。如果不调用 SystemClock_Config() 重新配置,芯片会以 HSI 低速运行,外设时序全乱。别问我怎么知道的……

待机模式——几乎关机,只留备份域

待机模式比停止模式更「狠」。CPU、SRAM、大部分外设都断电了,只保留备份域(RTC、备份寄存器、备份 SRAM)。唤醒后,程序会从头执行——就像按了复位键。

进入待机模式:

// 清除唤醒标志
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
HAL_PWREx_ClearPendingEvent();

// 进入待机模式
HAL_PWR_EnterSTANDBYMode();

唤醒方式有三种:

  • WKUP 引脚上升沿(PA0 等)
  • RTC 闹钟/唤醒事件
  • NRST 复位引脚

注意:待机模式唤醒后,程序从 Reset_Handler 开始执行。所以你需要一种方式来判断是「上电复位」还是「待机唤醒」。我一般用 RTC 备份寄存器来标记:

// 进入待机前,写标记
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0xA5A5);

// 醒来后,检查标记
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == 0xA5A5) {
    // 待机唤醒,恢复现场
} else {
    // 上电复位,完整初始化
}
我的经验: 待机模式适合「定时上报」的场景。比如传感器每小时采集一次数据,中间 59 分钟都在待机。功耗能降到 μA 级。

关机模式——真正的「断电」

关机模式是 STM32 功耗最低的模式。它比待机模式更进一步:连备份域的部分电路也断电了。唤醒后,芯片完全复位,所有 SRAM 和寄存器内容全部丢失。

进入关机模式:

// 进入关机模式
HAL_PWREx_EnterSHUTDOWNMode();

唤醒方式只有两种:

  • WKUP 引脚上升沿
  • NRST 复位引脚

RTC 闹钟?不行。关机模式下 RTC 也停了。

注意: 关机模式唤醒后,芯片执行完整的复位流程。你不能像待机模式那样「恢复现场」。所以,关机模式只适合「按一下开机,再按一下关机」的产品,比如遥控器、电子标签。

模式切换的核心逻辑

说了这么多,其实切换逻辑很简单。我画了张图,帮你理清思路:

STM32低功耗模式切换流程图 STM32 低功耗模式切换流程 运行模式 睡眠模式 停止模式 待机模式 关机模式 关键说明 • 向下箭头:功耗降低 • 向上箭头:唤醒恢复 • 睡眠:CPU暂停,外设全开 • 停止:CPU+时钟停,SRAM保留 • 待机:仅备份域供电 • 关机:几乎完全断电 唤醒后恢复方式: • 睡眠/停止:继续执行 • 待机:从头执行 • 关机:完全复位 唤醒(功耗越高,恢复越快)

这张图想表达的核心思想:越往下,功耗越低,但唤醒代价越大。你选哪个模式,取决于你的应用场景——是要求快速响应,还是追求极致续航。

实际项目中的选择策略

说了这么多理论,来点实际的。我总结了一个简单的选择矩阵:

  • 需要频繁响应中断(ms级) → 睡眠模式
  • 需要保留现场,但可以接受几十μs唤醒 → 停止模式
  • 定时唤醒,不需要保留现场 → 待机模式
  • 物理开关控制,完全断电 → 关机模式
我的建议: 别一上来就追求最低功耗。先跑通功能,再用电流表实测,逐步降低模式。我见过太多人一上来就搞待机,结果唤醒后外设初始化没做好,整个系统跑飞了。