2、硬件基础:MCU低功耗模式详解(Sleep、Stop、Standby)

做嵌入式开发这么多年,我见过太多工程师一上来就怼代码,结果功耗死活降不下去。其实说白了,你得先摸清楚MCU这颗芯片的「脾气」——它到底能睡多沉?

今天咱们就聊聊STM32(以及同类Cortex-M内核MCU)的三种低功耗模式:Sleep、Stop、Standby。这三种模式,就像人的三种休息状态:打盹、浅睡、深度昏迷。嗯,这个比喻可能不太恰当,但意思到了。

2.1 Sleep模式:打个盹儿

Sleep模式是最轻量级的低功耗模式。内核时钟停了,但外设还在跑。你想想看,CPU不干活了,但串口、定时器、DMA这些家伙还在那儿蹦跶。

怎么进入? 执行一条WFI(Wait For Interrupt)或WFE(Wait For Event)指令就行。我个人习惯用WFI,因为更可控。

// 进入Sleep模式
__WFI();  // 等待中断唤醒

怎么唤醒? 任何中断都能把它叫醒。比如你开了个定时器中断,每1ms触发一次,那MCU就每1ms醒一次,处理完继续睡。

典型功耗: 几十μA到几mA不等,取决于你开了多少外设。

我在项目中遇到过一个问题:有个同事把Sleep模式当成了万能药,结果电池还是撑不过三天。后来一查,他开了三个串口、两个SPI、一个I2C,全都挂着时钟——这哪是睡觉?分明是闭着眼睛在蹦迪。

我的建议: 进Sleep前,先把不用的外设时钟关了。用RCC寄存器逐个关,别偷懒。

2.2 Stop模式:浅睡但关机

Stop模式就狠多了。内核停了,所有外设时钟也停了。只有少数几个东西还在工作:RTC、IWDG(独立看门狗)、以及一些唤醒引脚。

说白了,这时候MCU的大部分电路都断电了,只留了一盏「夜灯」。

怎么进入? 需要配置一下寄存器,告诉MCU「我要进Stop了」。

// 进入Stop模式(以STM32为例)
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

怎么唤醒? 外部中断(比如按键)、RTC闹钟、或者某些特定的唤醒引脚。注意,不是所有中断都能唤醒Stop模式——只有那些配置成「唤醒源」的才行。

我曾经踩过的坑: 有一次我用了Stop模式,结果发现唤醒后串口数据全乱了。查了半天,原来是Stop模式下SRAM内容虽然保留,但某些外设寄存器被复位了。唤醒后必须重新初始化外设!

典型功耗: 几μA到几十μA。比Sleep低了一个数量级。

特性 Sleep模式 Stop模式
内核时钟 停止 停止
外设时钟 运行(可配置) 停止
SRAM/寄存器 全部保留 全部保留
唤醒源 任何中断 特定唤醒源
唤醒时间 几μs 几十μs

2.3 Standby模式:深度昏迷

Standby模式,这才是真正的「关机」。除了RTC和备份域(Backup Domain)的电路,其他全部断电。SRAM内容丢失,寄存器复位,程序从头开始跑。

你想想看,这就像电脑拔了电源线,再开机就是冷启动。

怎么进入? 设置一个特殊的寄存器位,然后执行WFI。

// 进入Standby模式
HAL_PWR_EnterSTANDBYMode();

怎么唤醒? 只有几个选择:WKUP引脚上升沿、RTC闹钟、IWDG复位、或者NRST引脚复位。唤醒后,MCU会像上电一样从头执行代码。

典型功耗: 几十nA到几μA。这才是真正的「超低功耗」。

我记得有个项目是做智能门锁,要求电池用一年。我们最后就是靠Standby模式实现的——平时深度休眠,只有按键按下或者RTC定时唤醒时才工作。功耗从几十mA降到了不到1μA。

注意: 进Standby前,一定要把重要数据存到备份寄存器或者RTC的备份SRAM里。否则一觉醒来,数据全没了,程序都不知道自己是谁。

2.4 三种模式怎么选?

这个问题没有标准答案,得看你的应用场景。我一般这么选:

  • 需要频繁响应(比如按键扫描、通信轮询): 用Sleep模式。唤醒快,功耗也能接受。
  • 大部分时间空闲,偶尔需要干活(比如传感器采集): 用Stop模式。功耗低,唤醒后还能接着干。
  • 长期待机,几乎不干活(比如电池供电的遥控器): 用Standby模式。功耗最低,但代价是「失忆」。

另外,很多MCU还支持「Stop模式下的部分外设保持运行」,比如LPUART(低功耗串口)。这玩意儿可以在Stop模式下监听串口数据,有数据来了再唤醒。嗯,这个后面咱们会细讲。

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 唤醒后时钟配置: Stop模式唤醒后,系统时钟可能恢复成默认的HSI(内部高速振荡器)。如果你之前用的是HSE(外部晶振),记得重新配置PLL。
  • GPIO状态: 进低功耗前,把不用的GPIO设成模拟输入或上拉/下拉输出。悬空的GPIO会漏电,这个坑我栽过两次。
  • 调试器干扰: 如果你用J-Link或ST-Link调试,进低功耗模式时调试器可能会把MCU「拽」住,导致功耗降不下去。断开调试器再测。

好了,这一章就聊到这儿。下一章咱们会讲如何用RTOS的任务管理来配合这些低功耗模式——说白了,就是让系统该睡的时候睡,该醒的时候醒,别瞎折腾。