3. 硬件基础:MCU的几种典型低功耗模式
做无线设备,说白了就是在跟电池较劲。你想想看,一个传感器节点可能要在野外跑一年,电池就那么点容量,MCU 要是不会「偷懒」,根本撑不住。
我个人习惯把 MCU 的低功耗模式比作人的睡眠状态——有浅睡、深睡、还有完全昏迷。不同场景选不同模式,选错了要么功耗下不来,要么醒不过来。这章我们就把这几种模式掰开揉碎讲清楚。
3.1 四种核心模式概览
大部分现代 MCU(比如 STM32、EFM32、MSP430)都提供 4 种基本运行状态。我整理了一张表,方便你对照着看:
| 模式 | CPU 状态 | 外设状态 | 唤醒源 | 典型电流 |
|---|---|---|---|---|
| Run | 全速运行 | 全部可用 | — | mA 级 |
| Sleep | 暂停 | 全部保持 | 任意中断 | 几百 µA |
| Deep Sleep | 暂停 | 部分保留 | 特定外设/RTC | 几 µA |
| Shutdown | 掉电 | 全部关闭 | 复位/唤醒引脚 | nA 级 |
嗯,这里要注意:不同厂商的叫法可能不一样。比如 ST 把 Deep Sleep 叫 Stop 模式,Shutdown 叫 Standby。但底层逻辑是一样的——用关闭功能换省电。
3.2 Run 模式——该干活时就干活
Run 模式没什么好说的,CPU 全速跑,所有外设都开着。这时候功耗最高,但也是唯一能真正「干活」的状态。
我在项目中遇到过不少新手,上来就想让 MCU 一直跑在低功耗模式。这其实是个误区。你想想,无线设备要发数据包,发一个包可能只要 10ms,但电流是 10mA。如果这 10ms 你让它跑在 Sleep 模式,数据根本发不出去。
关键原则:Run 模式不是敌人,低效的 Run 模式才是。把工作时间压缩到最短,然后尽快进入低功耗状态,这才是正道。
3.3 Sleep 模式——浅睡,随叫随到
Sleep 模式是最温和的低功耗模式。CPU 的时钟停了,但 SRAM 和寄存器内容全部保留,所有外设照常工作。任何一个中断都能把它唤醒。
说白了,这就是「假寐」。CPU 虽然不执行代码了,但整个系统还处于待命状态。
什么时候用?比如你在等一个 SPI 传输完成,或者等一个 GPIO 电平变化。这种场景下,Sleep 模式最合适——唤醒快(几个时钟周期),而且不用操心保存现场。
// 伪代码示例:进入 Sleep 模式
void enter_sleep(void) {
// 设置 SLEEPDEEP 位为 0
SCB->SCR &= ~(1 << 2);
// 执行 WFI 指令
__WFI();
// 醒来后从这里继续执行
}
我的经验:Sleep 模式虽然省电有限,但非常适合做「轮询等待」的替代方案。我曾经把一个用 delay 等待传感器就绪的程序改成 Sleep + 中断唤醒,功耗直接降了 60%。
3.4 Deep Sleep 模式——深度休息,只留关键设备
Deep Sleep 模式就狠多了。CPU 停掉,大部分外设的时钟也切掉,只保留少数几个关键模块——比如 RTC、低功耗定时器、以及你指定的唤醒引脚。
为什么会这样?因为很多外设在 Deep Sleep 下根本用不上。比如你不需要在睡觉的时候还开着 USART 等数据,那纯粹是浪费电。
我建议你在设计时先列一个清单:Deep Sleep 期间,哪些外设必须活着?
- 必须保留:RTC(维持时间)、唤醒定时器、唤醒 GPIO
- 可以关闭:ADC、DAC、SPI、I2C、USART、DMA
- 视情况保留:看门狗(如果要求高可靠性)
唤醒时间比 Sleep 模式长一些,大概几十微秒到几百微秒。因为系统需要重新锁相环、恢复时钟树。
避坑指南:我曾经在 Deep Sleep 模式下忘记关闭 ADC 的参考电压源,结果功耗比预期高了 3 倍。后来用电流表一量才发现——那个参考源在 Deep Sleep 下居然还耗着 10µA。所以,进入 Deep Sleep 前,一定要逐个确认每个外设的电源域是否真的切断了。
3.5 Shutdown 模式——彻底关机,几乎零功耗
Shutdown 模式是终极省电手段。CPU 掉电,SRAM 内容丢失,所有外设全部关闭。整个芯片只剩下几个唤醒引脚还活着。
这时候的电流能低到什么程度?几十纳安。对,你没看错,是 nA 级。一节 CR2032 电池在这种模式下能撑好几年。
但代价也很大:
- 唤醒相当于一次复位,程序从头开始跑
- RAM 里的数据全没了,必须提前保存到备份寄存器或 Flash
- 唤醒时间最长,通常需要几毫秒
所以 Shutdown 模式只适合那些「大部分时间完全不需要干活」的场景。比如一个温湿度传感器,每小时醒来一次,采集 10ms 数据,发完就继续睡。
// 伪代码示例:进入 Shutdown 模式(以 STM32 为例)
void enter_shutdown(void) {
// 设置 SLEEPDEEP 位为 1
SCB->SCR |= (1 << 2);
// 选择 Standby 模式
PWR->CR |= PWR_CR_PDDS;
// 清除唤醒标志
PWR->CR |= PWR_CR_CWUF;
// 执行 WFI
__WFI();
// 醒来后从 Reset Handler 开始执行
}
3.6 四种模式的切换逻辑
光知道每种模式是什么还不够,你得知道什么时候切、怎么切。下面这张 SVG 图展示了我常用的状态机设计:
3.7 如何选择合适模式
选模式其实就三个问题:
- 你多久醒一次?——唤醒间隔越短,越不适合用 Shutdown,因为唤醒开销占比太大
- 醒来要干什么?——如果只是检查一个标志位,Sleep 就够了;如果要发无线数据包,必须 Run
- 数据能不能丢?——Shutdown 会清空 RAM,关键数据必须提前存到非易失区
我个人的经验是:能用 Deep Sleep 就别用 Sleep,能用 Shutdown 就别用 Deep Sleep。但前提是——你得把唤醒逻辑和现场恢复都测试透了。否则省下来的电,全花在调试上了。
总结一句话:低功耗设计的本质不是让 MCU 跑得更慢,而是让它「该睡就睡,该醒就醒,醒的时候麻利干完活继续睡」。