2、外设功耗模型:外设的几种工作状态(运行、空闲、睡眠、关闭)

做低功耗设计这么多年,我见过太多工程师一上来就盯着MCU内核的睡眠模式使劲优化。其实啊,真正吃电的大头,往往是那些不起眼的外设。你想想看,一个传感器在后台默默采数据,功耗可能比CPU本身还高。

今天我们就来聊聊外设的功耗模型。说白了,就是搞清楚外设到底有几种活法,每种活法吃多少电。

2.1 外设的四种基本工作状态

我个人习惯把外设的工作状态分成四档:运行、空闲、睡眠、关闭。这四档基本覆盖了所有常见外设的行为模式。

状态 典型功耗比例 功能描述 恢复时间
运行 100% 全速工作,时钟开启,数据正常处理 立即
空闲 30%~60% 时钟还在,但无数据传输,等待触发 几微秒
睡眠 1%~10% 主时钟关闭,保留寄存器状态,可被唤醒 几十微秒到几毫秒
关闭 0%(漏电除外) 完全断电,寄存器丢失,需重新初始化 几毫秒到几十毫秒

嗯,这里要注意:不同厂商对「睡眠」的定义差别很大。我在项目中遇到过某款蓝牙SoC,它的UART睡眠模式居然还保留着波特率发生器——这其实已经算「空闲」了。

2.2 运行状态:该干活时就干活

运行状态没什么好说的,外设全速运转。时钟、电源、数据通路全部打开。这时候功耗最高,但也是唯一能完成实际工作的状态。

我建议你养成一个习惯:只在真正需要的时候才让外设进入运行态。比如SPI传输,数据发完就立刻切走,别让它闲着耗电。

关键指标:运行状态下的功耗 = 动态功耗 + 静态功耗。动态功耗跟时钟频率成正比,频率越高越费电。

2.3 空闲状态:看似没事,其实在偷电

空闲状态是个陷阱。很多工程师觉得「没干活就不费电」,其实大错特错。

空闲状态下,外设的时钟还在跑,只是没有数据传输。比如一个I2C总线,主设备不发数据了,但SCL和SDA线上的上拉电阻还在耗电。你想想看,一个4.7kΩ的上拉电阻在3.3V下,光漏电流就吃掉0.7mA。十个外设就是7mA,这可不是小数目。

我曾经在一个穿戴项目里排查功耗,发现蓝牙模块在空闲模式下吃了2.3mA。查了半天,原来是它的内部时钟分频器没关。关掉之后直接降到0.4mA。

我的经验:空闲状态最适合做「快速响应」的场景。比如按键扫描,平时空闲,按下时立刻唤醒。但如果你不需要那么快的响应,不如直接进睡眠。

2.4 睡眠状态:低功耗的主力军

睡眠状态才是低功耗设计的重头戏。外设的主时钟被关掉,但寄存器内容保留,唤醒后能快速恢复。

不同外设的睡眠模式差别很大。以UART为例:

  • 浅睡眠:只关发送/接收逻辑,但保留波特率发生器。唤醒后1~2个时钟周期就能恢复。
  • 深睡眠:连波特率发生器也关了,只保留唤醒检测电路。恢复需要重新锁定波特率,大概要几百微秒。

我建议你在选型时仔细看数据手册的「Sleep Mode」章节。有些厂商会把「空闲」包装成「睡眠」来宣传,实际功耗根本没降下来。

避坑指南:我曾经踩过一个坑——某款ADC在睡眠模式下,内部参考电压居然还开着。数据手册上写的是「Sleep Mode Current: 1μA」,实际上参考电压那部分额外吃了8μA。所以一定要看「Total Current」那一行。

2.5 关闭状态:最省电,但代价也最大

关闭状态就是彻底断电。外设的寄存器全部丢失,唤醒后需要重新初始化。这个代价可不小。

举个例子,一个LCD驱动芯片,从关闭到正常显示,可能需要几十毫秒的初始化时间。如果你的系统每秒钟唤醒一次,那关闭状态反而不划算——初始化那段时间的功耗可能比一直空闲还高。

我个人习惯:只在长时间不用的场景下才用关闭状态。比如传感器采集完数据后,如果下一次采集在10秒以后,那就果断关掉。

2.6 状态切换的代价分析

状态切换不是免费的。每次切换都有时间和功耗的代价。我整理了一个表格,方便你评估:

切换路径 时间代价 功耗代价 适用场景
运行 → 空闲 ~1μs 几乎无 短时间等待
运行 → 睡眠 ~10μs 中等时间等待
运行 → 关闭 ~100μs 中等 长时间休眠
睡眠 → 运行 ~50μs 中等 快速响应需求
关闭 → 运行 ~10ms 非频繁唤醒

你想想看,如果你的系统每100ms唤醒一次,每次从关闭到运行要10ms,那光初始化就占了10%的时间。这10%的时间里功耗可能是正常运行的好几倍。算下来,还不如一直待在空闲状态。

2.7 实战建议:如何选择合适的状态

说了这么多,到底怎么选?我总结了几条原则:

  1. 看唤醒频率:唤醒间隔 < 1ms,用空闲;1ms~100ms,用睡眠;> 100ms,考虑关闭。
  2. 看恢复时间要求:如果系统要求从唤醒到正常工作 < 10μs,那只能用空闲或浅睡眠。
  3. 看外设类型:通信类外设(UART、SPI)适合空闲/睡眠;传感器类外设适合关闭。
  4. 看漏电水平:如果外设的漏电流本身就很小(比如nA级),那关闭和睡眠的区别不大。

核心思想:没有最好的状态,只有最合适的。低功耗设计的本质,就是在「功耗」和「响应时间」之间找平衡。

好了,这一章的内容就到这里。下一章我们会聊聊如何用代码来控制这些状态切换,到时候我会分享一些我在实际项目中用过的技巧和坑。


公众号:蓝海资料掘金营,微信deep3321