2、MCU的睡眠模式详解:待机模式、停止模式、休眠模式的区别与选择策略

做低功耗设计,说白了就是跟MCU的“睡法”打交道。

很多工程师一上来就翻数据手册,看到Sleep、Stop、Standby三个词就头大。我刚开始做项目时也踩过这个坑——选错了模式,要么功耗下不去,要么唤醒后系统直接“失忆”。

这一节,咱们就把这三种模式彻底讲透。

2.1 三种模式的本质差异

先看一张总览表,心里有个底。

特性 休眠模式 (Sleep) 停止模式 (Stop) 待机模式 (Standby)
CPU时钟 关闭 关闭 关闭
SRAM/寄存器 保持 保持 丢失
主要时钟源 运行 可关闭 全部关闭
唤醒源 任意中断 有限中断/事件 特定唤醒引脚/RTC
唤醒时间 ~1 µs ~10 µs ~100 µs ~ ms
典型电流 mA级 µA级 nA级
代码执行连续性 完全连续 连续 重新启动

你想想看,这三种模式其实是在“功耗”和“唤醒代价”之间做权衡。没有绝对的好坏,只有合不合适的场景。

2.2 休眠模式(Sleep Mode)—— 打个盹

休眠模式是MCU最浅的睡眠。CPU停了,但外设和时钟还在跑。

我记得有一次调试一个传感器采集项目,采样间隔只有1ms。用Stop模式根本来不及唤醒,最后选了Sleep模式,配合DMA传输,完美搞定。

适用场景:

  • 需要频繁、快速响应的任务(如按键扫描、通信轮询)
  • 外设仍在工作(如定时器、ADC连续采样)
  • 唤醒延迟必须控制在微秒级

代码示例也很简单:

// 进入休眠模式(以STM32为例)
HAL_SuspendTick();          // 暂停系统滴答,避免频繁唤醒
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
// 醒来后继续执行下一行
HAL_ResumeTick();

这里有个坑:WFI(Wait For Interrupt)和WFE(Wait For Event)的区别。WFI需要中断发生才能唤醒,WFE只要有事件就能唤醒。我个人习惯用WFI,因为更可控。

2.3 停止模式(Stop Mode)—— 睡个整觉

停止模式就狠多了。CPU停了,大部分时钟也停了,但SRAM和寄存器内容还在。

为什么说“大部分”?因为你可以选择保留低速时钟(如LSI、LSE)给RTC或独立看门狗用。

我的经验:

在物联网终端设备中,Stop模式是最常用的。比如LoRa节点,每几秒醒来发一次数据,平时就待在Stop模式。电流能压到几个µA,唤醒时间几十微秒,完全够用。

进入Stop模式的代码:

// 进入停止模式,保留RTC
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 系统时钟需要重新配置!
SystemClock_Config();

注意:从Stop模式唤醒后,HSE/PLL等高速时钟默认是关闭的。你必须手动重新配置系统时钟,否则MCU会以低速时钟运行,性能大打折扣。我曾经因为这个原因,导致一个显示刷新任务卡了整整半天。

2.4 待机模式(Standby Mode)—— 深度冬眠

待机模式是功耗最低的模式,没有之一。SRAM没了,寄存器没了,除了备份域(Backup Domain)里的RTC和几个唤醒引脚,其他全部断电。

唤醒后,MCU的行为跟复位几乎一样——从main函数重新开始执行。

代码示例:

// 进入待机模式
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
HAL_PWR_EnterSTANDBYMode();
// 唤醒后从这里重新开始

关键点:

  • 唤醒后系统复位,所有变量需要重新初始化
  • 备份域(Backup SRAM)可以保存少量关键数据
  • 唤醒源只有:WKUP引脚上升沿、RTC闹钟、入侵检测等

我曾经在一个电池供电的温湿度记录仪上用过Standby模式。设备每10分钟醒来一次,采集数据存到Flash,然后继续睡。一节CR2032电池撑了两年多。

2.5 选择策略:到底该用哪个?

这个问题没有标准答案,但我给你一个决策流程,照着走基本不会错。

睡眠模式选择决策流程 开始选择 需要保留SRAM/寄存器? 是 否 唤醒时间 < 5µs? 需要nA级功耗? 休眠模式 (Sleep) 待机模式 (Standby) 外设/时钟需要继续工作? 是 否 休眠模式 (Sleep) 停止模式 (Stop) 提示:实际项目中,建议先按此流程初选,再根据实测功耗微调

总结一下我的个人经验:

  • 需要频繁响应(ms级间隔) → 休眠模式
  • 需要低功耗且保留上下文 → 停止模式
  • 需要极低功耗且可以接受复位式唤醒 → 待机模式

避坑指南:

我曾经在一个项目中,为了追求极致功耗,直接用了Standby模式。结果发现每次唤醒后,外设初始化时间太长,导致数据采集出现了时间戳错位。后来改成了Stop模式,虽然功耗多了2µA,但系统稳定多了。

记住:低功耗设计不是一味追求最低功耗,而是在满足功能的前提下,选择最合适的模式。