第1章:MCU低功耗模式详解:Sleep、Deep Sleep、Standby模式切换,以及唤醒源配置(RTC、GPIO中断)

各位同学,咱们今天聊聊MCU的低功耗模式。说实话,做便携式美容仪,电池就那么一小块,续航要是拉胯,用户用两次就吃灰了。我最早做第一款美容仪时,就吃过这个亏——产品功能都挺好,就是用户反馈「充一次电用不了三天」。后来一查,MCU一直在全速跑,根本没睡过觉。

所以这一章,咱们把MCU的三种低功耗模式掰开揉碎讲清楚。你想想看,MCU就像一个人,有清醒、打盹、熟睡、关机几种状态。选对了模式,续航翻倍不是梦。

1.1 三种低功耗模式,到底差在哪?

先看一张表,一目了然:

模式 CPU状态 外设状态 RAM保持 典型电流 唤醒时间
Sleep(睡眠) 停止 全部运行 全部保持 ~1mA 几微秒
Deep Sleep(深度睡眠) 停止 部分运行 部分保持 ~10μA 几十微秒
Standby(待机) 停止 几乎全关 丢失 ~1μA 毫秒级

嗯,这里要注意——电流每差一个数量级,续航就差一个档次。但代价是唤醒时间和功能保留程度也不同。

1.2 Sleep模式:最轻量的睡眠

说白了,Sleep模式就是让CPU歇着,但所有外设还在跑。比如你的美容仪正在做射频输出,但CPU暂时不需要算数据,就可以进Sleep。

我个人习惯在以下场景用Sleep:

  • 等待ADC采样完成时
  • 等待SPI/I2C传输结束的空档
  • 按键消抖的短暂延时

代码示例(以STM32为例):

// 进入Sleep模式
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);

// 任意中断即可唤醒
// 比如定时器中断、GPIO中断

我在项目中遇到过一个问题:进Sleep前忘了关串口打印,结果串口还在发数据,电流根本降不下来。所以进低功耗前,先关掉调试接口,这是血的教训。

1.3 Deep Sleep模式:续航的主力军

Deep Sleep才是美容仪续航优化的主战场。CPU停了,大部分外设也关了,只保留你指定的那几个——比如RTC、几个GPIO唤醒引脚。

我建议这样配置:

  • 保留RTC(实时时钟),用于定时唤醒做周期性检测
  • 保留1-2个GPIO中断引脚,用于按键唤醒
  • 其他外设全部关闭

代码示例:

// 配置RTC唤醒(每5秒唤醒一次)
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5000, RTC_WAKEUPCLOCK_CK_SPRE_16);

// 配置GPIO中断唤醒(PA0引脚)
HAL_GPIO_EXTI_IRQHandler(PA0_PIN);

// 进入Deep Sleep
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
我的小技巧: 进Deep Sleep前,把不用的GPIO全部设为模拟输入模式。为什么?因为数字输入会漏电!我曾经测过,一个浮空的GPIO能多耗2-3μA。别小看这几微安,积少成多。

1.4 Standby模式:终极省电,但有代价

Standby模式是最狠的——几乎把整个芯片都关了,RAM里的数据全丢。唤醒后等于重新启动。电流能压到1μA以下,但代价是唤醒后要重新初始化所有东西。

什么时候用Standby?

  • 美容仪长时间不用,进入深度待机
  • 电池电量极低时,强制进入保护模式
  • 用户长按关机键后
警告: 进Standby前,一定要把关键数据存到备份寄存器或Flash里。我曾经有一次忘了存,唤醒后设备参数全丢了,用户以为机器坏了。从那以后,我每次进Standby前都会写一句:HAL_RTCEx_BKUPWrite(...)

代码示例:

// 保存关键数据到备份寄存器
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0xA5A5);  // 标记位
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, current_mode);

// 进入Standby模式
HAL_PWR_EnterSTANDBYMode();

// 唤醒后检查备份寄存器
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == 0xA5A5) {
    // 恢复之前的工作模式
}

1.5 唤醒源配置:谁叫醒MCU?

三种模式对应不同的唤醒源,我整理了一下:

唤醒源 Sleep Deep Sleep Standby
GPIO中断 ✓(特定引脚) ✓(特定引脚)
RTC闹钟/唤醒
定时器中断
串口接收中断
复位引脚

你看,Deep Sleep和Standby能用的唤醒源很有限。所以设计时要想清楚:你到底需要什么来叫醒MCU?

我一般这样设计美容仪的唤醒策略:

  1. 按键唤醒: 用GPIO中断,配置成上升沿或下降沿触发。注意要加硬件消抖,不然一次按键可能唤醒好几次。
  2. 定时检测: 用RTC每1秒或5秒唤醒一次,检测温度、电池电压等。检测完没事就继续睡。
  3. 充电唤醒: 插入充电器时,通过充电检测引脚唤醒MCU,进入充电管理流程。

核心要点: 唤醒源配置的关键在于——唤醒后第一件事做什么? 我习惯在唤醒中断服务函数里只设一个标志位,然后立即返回。主循环里再根据标志位做具体处理。这样中断服务函数执行时间短,不会影响后续的唤醒响应。

1.6 实战中的模式切换策略

说了这么多,到底怎么用?我分享一个实际案例。

某款美容仪的工作流程:

  • 工作时: 全速运行,输出射频/脉冲
  • 空闲等待: 用户按了开始键但还没贴到皮肤,进Sleep模式,等触摸传感器中断唤醒
  • 短时待机: 用户停止使用但没关机,进Deep Sleep,RTC每10秒唤醒一次检测是否重新使用
  • 长时待机: 超过5分钟无操作,进Standby,只有按键能唤醒

你看,一个产品里三种模式都用上了。关键是根据使用场景动态切换,而不是一棍子打死只用一种。

我曾经犯过一个错:为了省电,一空闲就进Standby。结果用户每次用都要等好几秒重新初始化,体验极差。后来改成先进Deep Sleep,只有长时间不用才进Standby,用户反馈好多了。

1.7 本章小结

嗯,这一章内容不少,我帮你捋一下:

  • Sleep: 轻量睡眠,适合短时空闲,唤醒快
  • Deep Sleep: 主力省电模式,保留RTC和关键GPIO,适合大多数待机场景
  • Standby: 终极省电,但会丢数据,适合长时间不用的场景
  • 唤醒源: RTC做定时唤醒,GPIO做事件唤醒,两者结合最灵活

下一章,咱们会深入讲如何用RTC做精准的定时唤醒,以及怎么避免RTC晶振带来的额外功耗。到时候我会分享一个我调了三天才搞定的RTC校准案例,保证让你少走弯路。

今天就到这儿。记住一句话:低功耗不是一味地睡,而是该睡的时候睡得深,该醒的时候醒得快。