4. 电源管理模式详解:Run、Sleep、Low-power Run、Stop 0/1/2、Standby、Shutdown
说实话,STM32L4 的电源管理,是我见过最灵活也最容易踩坑的模块之一。它不像有些芯片只有「醒着」和「睡着」两种状态,而是给你准备了整整 7 种运行模式。每种模式都有自己的脾气,切换不对,功耗就下不去。
我个人习惯,拿到一个新项目,先不看外设,先把电源模式画个图理清楚。因为后面所有的低功耗优化,本质上都是在这些模式之间做选择和切换。
4.1 七种模式,一张图看懂
先看这张总览图,把 STM32L4 的电源模式家族串起来。你想想看,从最高功耗到最低功耗,其实是一条「功能逐步剥离」的链条。
核心思路: 功耗每降一级,你就得放弃一部分硬件功能。关键是在「够用」和「省电」之间找到平衡点。
4.2 Run 模式与 Sleep 模式
Run 模式,就是芯片全速工作的状态。CPU 跑着,所有外设都能用,时钟该开的都开着。这时候功耗最高,大概在 100μA/MHz 左右。没什么好说的,干活的时候就得这样。
Sleep 模式,说白了就是 CPU 暂停了,但外设还在跑。你想想看,如果你只是等一个串口数据,或者等一个定时器溢出,完全没必要让 CPU 空转。这时候进 Sleep,功耗能降一半左右。
我的经验: 很多初学者觉得 Sleep 模式没用,因为「反正很快就醒了」。但我在一个数据采集项目里,把主循环中所有等待都改成 Sleep + 事件唤醒,整体功耗降了 40%。积少成多,效果很可观。
// 进入 Sleep 模式的典型代码
HAL_SuspendTick(); // 暂停系统滴答定时器
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
// 醒来后继续执行
HAL_ResumeTick();
4.3 Low-power Run 模式
这个模式有点意思。CPU 还在跑,但只能跑 MSI 时钟,最高 2MHz。电压调节器也切到低功耗档。功耗能压到 8μA 左右。
我在一个手持仪表项目里用过这个模式。设备大部分时间在采集传感器数据,不需要高速处理。我就把主频降到 2MHz,用 Low-power Run 跑。等数据攒够了,再切回正常 Run 模式做运算。效果很好,电池续航直接翻倍。
注意: 进入 Low-power Run 之前,一定要先把系统时钟切换到 MSI。如果你还挂着 HSI 或 HSE,直接调用 HAL_PWREx_EnableLowPowerRunMode() 会失败。我刚开始就踩过这个坑,查了半天才发现是时钟源没切。
// 进入 Low-power Run 模式的步骤
// 1. 先切换到 MSI 时钟
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
// 2. 使能低功耗运行模式
HAL_PWREx_EnableLowPowerRunMode();
// 3. 现在可以降频到 2MHz 以下
// ... 执行低功耗任务 ...
// 4. 退出时先禁能低功耗运行模式
HAL_PWREx_DisableLowPowerRunMode();
4.4 Stop 0/1/2 模式:最常用的低功耗模式
Stop 模式是 STM32L4 低功耗设计的核心。它有三个子模式,差别在于电压调节器的状态和唤醒速度。
| 特性 | Stop 0 | Stop 1 | Stop 2 |
|---|---|---|---|
| 电压调节器 | MR(主调节器) | LPR(低功耗调节器) | LPR(低功耗调节器) |
| 典型功耗 | ~50μA | ~5μA | ~1μA |
| 唤醒时间 | ~3μs | ~5μs | ~7μs |
| RAM 保留 | 全部 | 全部 | 全部 |
| GPIO 状态 | 保持 | 保持 | 保持 |
| 适用场景 | 快速唤醒 | 平衡模式 | 超低功耗待机 |
你可能会问:「三个模式差别不大,我该用哪个?」
我的建议是:默认用 Stop 1。它功耗和唤醒时间都比较均衡。如果你需要频繁唤醒(比如 1ms 一次),用 Stop 0。如果你能接受稍慢的唤醒,比如 10ms 才需要响应一次,用 Stop 2。
关键点: Stop 模式下,所有时钟都停了,但 RAM 和寄存器内容全部保留。醒来后程序从原地继续执行,就像什么都没发生过。这是它和 Standby 最大的区别。
// 进入 Stop 2 模式
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
// 进入 Stop 1 模式
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
// 进入 Stop 0 模式(通过标准 Stop 函数)
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
4.5 Standby 模式与 Shutdown 模式
这两个模式是「狠角色」。进去之后,大部分电路都断电了。CPU 内核、大部分外设、甚至一部分 RAM 都没了。
Standby 模式,还保留着 2KB 的备份 SRAM 和备份寄存器。你可以把关键数据存在那里。唤醒后,程序从头开始执行(类似复位),但你可以通过检查复位标志来判断是从 Standby 醒来的。
Shutdown 模式,更彻底。连备份域的部分电路都断了。只留下几个唤醒引脚还能工作。功耗低到 30nA 左右。适合那种「一年换一次电池」的设备。
我曾经犯过的错: 在一个产品中,我把 RTC 闹钟配置为 Standby 唤醒源。结果发现设备每隔几秒就重启一次。查了两天才发现,RTC 闹钟标志在进入 Standby 前没有清除,导致一醒来又触发闹钟,又进 Standby。死循环了。所以记住:进 Standby 前,一定要清除所有唤醒标志。
// 进入 Standby 模式
HAL_PWR_EnterSTANDBYMode();
// 进入 Shutdown 模式
HAL_PWREx_EnterSHUTDOWNMode();
// 检查复位原因(判断是否从 Standby 醒来)
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) {
// 从 Standby 醒来
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
}
4.6 模式切换的避坑指南
说了这么多,最后总结几条实战经验。这些都是我拿真金白银换来的教训。
- 时钟源要提前切好。 进 Low-power Run 前切到 MSI,进 Stop 前确保没有外设在用 HSE。否则切换会失败,或者功耗下不去。
- 外设要提前关掉。 进低功耗模式前,把不需要的外设时钟关了。尤其是 ADC、DAC、USB 这些耗电大户。我见过有人进 Stop 2 还有 10μA,查了半天发现是 ADC 没关。
- GPIO 要处理好。 浮空的 GPIO 会漏电。进低功耗前,把所有不用的引脚设成模拟模式,或者拉高/拉低。这个细节能省下 1-2μA。
- 唤醒源要配置正确。 不是所有中断都能在 Stop 模式下唤醒芯片。只有那些标记为「可唤醒」的中断才行。具体看参考手册的「Wakeup from Stop mode」章节。
- 测量功耗要用实际电路。 开发板上的电流测量跳线往往不准。我习惯自己焊一个 10Ω 采样电阻,用示波器看电压降,这样能精确看到每个模式下的电流波形。
一个小技巧: 调试低功耗时,别一上来就追求最低功耗。先让设备在 Stop 1 模式下跑起来,确认能正常唤醒。然后再一步步优化到 Stop 2、Standby。这样出问题了容易定位。
好了,电源管理模式就讲到这里。这章内容比较多,但都是后面实战的基础。你把这些模式的特性和切换条件记熟,后面做低功耗优化就会顺手很多。