第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);
1.4 Standby模式:终极省电,但有代价
Standby模式是最狠的——几乎把整个芯片都关了,RAM里的数据全丢。唤醒后等于重新启动。电流能压到1μA以下,但代价是唤醒后要重新初始化所有东西。
什么时候用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?
我一般这样设计美容仪的唤醒策略:
- 按键唤醒: 用GPIO中断,配置成上升沿或下降沿触发。注意要加硬件消抖,不然一次按键可能唤醒好几次。
- 定时检测: 用RTC每1秒或5秒唤醒一次,检测温度、电池电压等。检测完没事就继续睡。
- 充电唤醒: 插入充电器时,通过充电检测引脚唤醒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校准案例,保证让你少走弯路。
今天就到这儿。记住一句话:低功耗不是一味地睡,而是该睡的时候睡得深,该醒的时候醒得快。