单片机低功耗模式概述:睡眠、停止与待机

做嵌入式开发这些年,我越来越觉得低功耗设计不是选修课,而是必修课。你想想看,一个产品如果电池撑不过三天,功能再强用户也不会买账。而低功耗模式,说白了就是让单片机在“没事干”的时候尽量少耗电。

今天咱们先聊清楚三种最基本的低功耗模式:睡眠模式、停止模式和待机模式。这三兄弟的区别,我当年可是花了不少功夫才真正搞明白。

一、为什么需要低功耗模式?

先问个问题:单片机跑在72MHz全速工作时,电流可能到几十毫安甚至上百毫安。但大部分时间,它只是在等一个按键、等一个定时器溢出、或者等传感器数据准备好。这段时间的电流,说白了就是浪费。

低功耗模式的核心思路就一句话:关掉不需要的模块,降低时钟频率,甚至完全停止时钟。不同的关法,就对应不同的模式。

关键指标对比:

  • 睡眠模式:电流约 1-10 mA(视外设而定)
  • 停止模式:电流约 10-100 µA
  • 待机模式:电流约 1-5 µA(甚至更低)

从毫安级到微安级,差了三个数量级。这就是你产品续航从3天变成3个月的关键。

二、三种模式的核心区别

我习惯用一个比喻来理解这三种模式:

  • 睡眠模式:就像你坐在工位上打盹,有人叫你马上能醒。CPU停了,但外设还在跑。
  • 停止模式:就像你回家睡觉了,闹钟响了才能醒。CPU和外设都停了,但寄存器和RAM里的数据还在。
  • 待机模式:就像你出差去了另一个城市,只有紧急电话才能找到你。几乎整个芯片都断电了,醒来一切从头开始。

嗯,这个比喻虽然不精确,但能帮你快速建立直觉。下面咱们看技术细节。

特性 睡眠模式 停止模式 待机模式
CPU时钟 停止 停止 停止
外设时钟 运行(可配置) 停止 停止
SRAM/寄存器内容 保持 保持 丢失
唤醒源 任意中断 特定外设中断(如EXTI、RTC) 特定唤醒引脚、RTC、复位
唤醒后执行 从中断处继续 从中断处继续 从头执行(类似复位)
典型电流 ~5 mA ~50 µA ~2 µA

我曾经踩过的坑:有一次做手持设备,我用了停止模式,以为所有外设都停了。结果发现一个GPIO没配置好,漏电导致整机电流多了200µA。后来养成习惯:进低功耗前,把所有不用的GPIO都设成模拟输入模式,或者拉高/拉低到固定电平。

三、三种模式的唤醒机制

唤醒方式决定了你该选哪种模式。我个人习惯这样选:

  • 需要频繁响应外部事件(比如按键扫描、通信接收)→ 用睡眠模式。唤醒快,功耗适中。
  • 需要定时唤醒做数据采集(比如每10秒读一次传感器)→ 用停止模式+RTC定时器。功耗低,还能保持数据。
  • 设备大部分时间在休眠,偶尔被唤醒(比如遥控器、门磁)→ 用待机模式。功耗最低,但醒来要重新初始化。

你想想看,如果遥控器用睡眠模式,电池可能半年就没了。但用待机模式,两三年都没问题。

四、知识结构总览

下面这张图是我自己整理的,把三种模式的关系和选择逻辑画清楚了。建议你保存下来,做项目时对照着看。

单片机低功耗模式知识结构图 低功耗模式 睡眠模式 停止模式 待机模式 特性 • CPU停,外设可运行 • 任意中断可唤醒 • 唤醒后继续执行 • 电流 ~5 mA 特性 • CPU停,外设停 • 特定中断唤醒 • SRAM/寄存器保持 • 电流 ~50 µA 特性 • 几乎全芯片断电 • 特定引脚/RTC唤醒 • 数据丢失,重新初始化 • 电流 ~2 µA 适用场景 频繁响应外部事件 适用场景 定时唤醒数据采集 适用场景 长期休眠,偶尔唤醒 选择原则:唤醒频率越高 → 选功耗越高的模式(唤醒快)

五、寄存器配置初探

虽然这一章只是概述,但我还是想让你先看一眼寄存器长什么样。以STM32F1为例,进入睡眠模式只需要一条指令:

// 进入睡眠模式(WFI指令)
__WFI();

进入停止模式需要配置电源控制寄存器:

// 进入停止模式
PWR->CR |= PWR_CR_LPDS;   // 低功耗深度睡眠
PWR->CR |= PWR_CR_CWUF;   // 清除唤醒标志
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;  // 深度睡眠
__WFI();

进入待机模式就更彻底了:

// 进入待机模式
PWR->CR |= PWR_CR_PDDS;   // 电源深度掉电
PWR->CR |= PWR_CR_CWUF;   // 清除唤醒标志
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__WFI();

我的小技巧:调试低功耗代码时,别一上来就进待机模式。先试睡眠模式,确认唤醒逻辑没问题了,再逐步切换到停止模式、待机模式。否则一旦进待机醒不来,调试器都连不上,只能重新上电——我吃过这个亏。

六、避坑指南

最后总结几个我实际项目中遇到的坑,你提前知道能省不少时间:

  1. GPIO浮空漏电:进低功耗前,把所有不用的GPIO设成模拟输入或固定电平。浮空引脚会通过IO保护二极管漏电。
  2. 唤醒源没配置好:停止模式下,不是所有中断都能唤醒。必须用EXTI、RTC等特定外设。我见过有人用UART中断唤醒停止模式,结果死活醒不来。
  3. 待机模式的数据保存:待机模式下SRAM内容会丢失。如果你需要保存数据,要么用RTC备份寄存器,要么在进待机前把数据写到Flash里。
  4. 调试器连接问题:进待机模式后,调试接口也会断电。所以调试时建议先用睡眠模式验证逻辑,最后再切到待机模式。