4. 低功耗模式详解:Sleep、Stop0/1/2、Standby、Shutdown

低功耗设计,说白了就是让芯片在没事干的时候尽量「睡过去」。但怎么睡、睡多深、醒来要多快,这里面门道不少。STM32L4 给了我们好几种睡眠模式,从打个盹到彻底关机,各有各的用场。

我刚开始做低功耗项目时,总觉得选个最省电的模式就对了。结果呢?要么唤醒太慢,要么该干活的时候起不来。后来踩过几次坑,才真正搞明白这些模式该怎么用。

核心原则:功耗越低,唤醒越慢,保留的功能越少。没有万能模式,只有最适合你场景的模式。
STM32L4 低功耗模式层级图 Run 模式(正常运行) Sleep 模式(CPU 停止) Stop 模式(内核掉电,SRAM 保持) Stop 0 Stop 1 Stop 2 Standby 模式(SRAM 掉电) Shutdown 模式(最省电) 功耗 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 最低

4.1 Sleep 模式——打个盹

Sleep 模式是最浅的睡眠。CPU 停了,但外设还在跑。你想想看,就像你躺在床上闭着眼,但耳朵还能听见周围的声音。

进入 Sleep 很简单,执行一条 WFI 或 WFE 指令就行。唤醒也快,任何中断都能把它叫醒。我有个项目是做无线传感器,数据采集间隔 100ms,中间就用 Sleep 模式。每次采集完睡过去,定时器一到就醒,功耗从 10mA 降到了 3mA 左右。

我的习惯:如果唤醒后不需要重新配置外设,用 Sleep 模式最省事。但要注意,DMA 在 Sleep 模式下还能继续工作,这个特性有时候很好用。

4.2 Stop 模式——深度睡眠

Stop 模式就厉害了。内核掉电,但 SRAM 和寄存器内容都保留。说白了就是「脑子关机了,但记忆还在」。STM32L4 给了我们三个 Stop 子模式:Stop 0、Stop 1、Stop 2。

特性 Stop 0 Stop 1 Stop 2
典型功耗 ~100 μA ~30 μA ~3 μA
唤醒时间 ~5 μs ~10 μs ~15 μs
SRAM 保持 全部 全部 全部
RTC 可用 是 是 是
LPUART 可用 是 是 是
LPTIM 可用 是 是 是
ADC 可用 是 否 否

看到这个表,你应该明白了。Stop 0 功耗最高但唤醒最快,Stop 2 最省电但唤醒最慢。怎么选?看你的应用场景。

我曾经做过一个便携式医疗设备,要求电池用一年。大部分时间设备在待机,但需要 RTC 定时唤醒做测量。我选了 Stop 2 模式,配合 RTC 唤醒,待机功耗做到了 3.5 μA。客户测试下来,两节 CR2032 电池确实撑了 14 个月。

注意:进入 Stop 模式前,记得把不用的外设时钟关掉。我见过有人进了 Stop 2 模式,功耗还有 50 μA,查了半天发现是某个 GPIO 没配置好,漏电了。

4.3 Standby 模式——彻底关机

Standby 模式就更狠了。SRAM 掉电,寄存器全丢,除了备份域(Backup Domain)里的东西,啥都不剩。唤醒后相当于复位重跑。

功耗能降到 0.3 μA 左右。但代价是什么?唤醒后代码从头执行,变量全没了。你得把关键数据存到备份寄存器或者 RTC 的备份 SRAM 里。

我记得有个项目是做户外环境监测,设备装在野外,半年换一次电池。平时就 Standby 模式,每天定时唤醒一次,采集数据、通过 LoRa 发出去,然后继续睡。功耗算下来,两节 AA 电池能撑 8 个月。

关键点:Standby 模式下,只有 RTC、IWDG(独立看门狗)和部分 GPIO(WKUP 引脚)能唤醒。别指望 UART 或者定时器能叫醒它。

4.4 Shutdown 模式——终极省电

Shutdown 模式是 STM32L4 的终极武器。功耗低到 0.1 μA 以下,比 Standby 还省。但代价也更大——连备份域的部分功能都关了。

Shutdown 模式下,只有 RTC 的特定唤醒事件和 WKUP 引脚能唤醒。而且唤醒后,系统从复位开始跑,连 RTC 的配置都可能需要重新初始化。

说实话,Shutdown 模式我用得不多。只有在那些对功耗要求极其苛刻的场景才会用。比如纽扣电池供电、一年只工作几次的设备。

我的建议:除非你的设备真的需要 0.1 μA 级别的待机功耗,否则优先考虑 Stop 2 或 Standby。Shutdown 模式唤醒太麻烦,调试起来也费劲。

4.5 模式选择决策流程

这么多模式,到底怎么选?我一般按这个思路来:

  1. 先看唤醒频率——如果每秒唤醒多次,用 Sleep 或 Stop 0
  2. 再看唤醒源——如果需要 UART 唤醒,只能用 Stop 模式
  3. 然后看数据保持需求——如果变量不能丢,别用 Standby 或 Shutdown
  4. 最后算功耗预算——根据电池容量和目标续航,反推允许的待机功耗

你想想看,如果设备每 10 秒醒一次,每次工作 50ms,那大部分时间在待机。这时候待机功耗就决定了整机续航。选对模式,电池寿命能差好几倍。

我曾经踩过的坑:有个项目用了 Stop 2 模式,功耗测出来 5 μA,觉得挺好。结果量产 1000 台后,有 3% 的设备电池提前耗尽了。查了两个月,发现是某些芯片在 Stop 2 模式下,内部 LDO 的配置有差异,导致漏电流偏大。后来加了出厂校准,问题才解决。所以,低功耗设计一定要留余量,别卡着极限值算。

4.6 代码示例:进入 Stop 2 模式

说了这么多,来点实际的。下面这段代码演示如何进入 Stop 2 模式,并用 RTC 唤醒:

// 进入 Stop 2 模式示例
void Enter_Stop2_Mode(void)
{
    // 1. 关闭不用的外设时钟
    __HAL_RCC_GPIOA_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    // ... 其他外设
    
    // 2. 配置 RTC 唤醒(假设已初始化)
    HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 4000, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
    // 每 4000 个时钟周期唤醒一次,约 1 秒(假设 LSE 32.768kHz)
    
    // 3. 进入 Stop 2 模式
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
    
    // 4. 唤醒后从这里继续执行
    // 重新配置系统时钟
    SystemClock_Config();
    
    // 重新使能外设时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    // ...
}

这段代码看起来简单,但有几个细节要注意。RTC 唤醒的时钟源、分频系数、重装值,都要算清楚。我见过有人把分频设错了,本来想 1 秒唤醒一次,结果 10 秒才醒一次,数据采集全乱了。

经验之谈:调试低功耗模式时,别一上来就测功耗。先用一个 LED 指示进入和退出的状态,确认唤醒逻辑没问题了,再关掉 LED 去测电流。否则你都不知道是没进去还是没出来。

好了,这几种模式的区别和用法,你应该心里有数了。记住,没有最好的模式,只有最适合你项目的模式。选对了,电池能多用好几个月;选错了,调试能让你怀疑人生。