第四章:协议栈功耗分析

好,咱们今天聊聊协议栈的功耗。说实话,很多工程师把精力都放在硬件上,觉得选个低功耗芯片就万事大吉了。但我在项目中踩过最大的坑,反而是协议栈配置不当导致的功耗飙升。你想想看,芯片再省电,如果协议栈一直在瞎忙活,那也白搭。

4.1 链路层状态机功耗

BLE的链路层有五种状态:待机、广播、扫描、发起、连接。每个状态的功耗天差地别。我习惯把状态机想象成一个人的日常——待机就是睡觉,广播是站在路口举牌子,扫描是东张西望找人,连接就是跟人聊天。

状态 典型电流 占比时间 说明
待机 1-3 µA 90%+ 几乎不耗电,但射频关闭
广播 5-15 mA 0.1%-1% 发射功率决定,距离越远越费电
扫描 5-10 mA 0.1%-1% 接收窗口大小影响功耗
连接 3-8 mA 1%-10% 连接间隔决定,越频繁越耗电

这里有个关键点:状态切换本身也耗电。我记得有一次调试,发现设备每隔100ms就切换一次状态,结果平均电流比预期高了3倍。后来一查,是状态机设计得太激进,频繁进出广播和扫描模式。

核心原则:尽量让设备待在待机状态。每次状态切换都有代价,就像你从床上爬起来再躺回去,折腾几次就累了。

4.2 连接事件功耗

连接事件是BLE功耗的大头。说白了,就是主设备和从设备约定好时间,定期交换数据。这个「定期」就是连接间隔。

我见过最典型的错误:把连接间隔设成7.5ms(最小值),结果设备一天就没电了。你想想看,每秒要醒来133次,每次都要收发数据,能不费电吗?

我的经验:对于温度传感器这类低频数据上报,连接间隔设到100ms-500ms完全够用。只有音频、OTA这类实时性要求高的场景,才需要短间隔。

连接事件功耗可以这样估算:

平均电流 = (事件电流 × 事件时长) / 连接间隔

举例:
事件电流 = 6 mA
事件时长 = 2 ms
连接间隔 = 100 ms
平均电流 = (6 × 2) / 100 = 0.12 mA = 120 µA

嗯,这里要注意:事件时长不是固定的。它取决于你要传多少数据。数据包越长,射频打开的时间就越久。我曾经优化过一个项目,把数据包从20字节压缩到8字节,事件时长缩短了40%,功耗直接降了三分之一。

避坑指南:连接事件里有个「空包」的概念。即使没有数据要传,主从设备也要交换空包来维持连接。我曾经遇到一个案例,设备明明没数据要发,但连接间隔设得太短,结果空包占了90%的功耗。解决方案很简单——拉长连接间隔,或者用「从设备延迟」功能减少空包次数。

4.3 广播事件功耗

广播事件是BLE设备「刷存在感」的方式。设备定期发送广播包,告诉周围「我在这儿」。广播间隔决定了刷存在的频率。

广播功耗的公式很简单:

平均电流 = (广播电流 × 广播时长) / 广播间隔

举例:
广播电流 = 8 mA
广播时长 = 1 ms
广播间隔 = 1000 ms
平均电流 = (8 × 1) / 1000 = 0.008 mA = 8 µA

你看,广播间隔拉到1秒,平均电流才8µA,几乎可以忽略。但很多产品为了「快速被发现」,把广播间隔设成20ms,结果平均电流飙到400µA。说白了,这就是典型的「过度设计」。

我的建议:广播间隔不要低于100ms。除非你的产品需要秒级发现,否则100ms-500ms完全够用。我在做智能门锁项目时,广播间隔设成200ms,用户按门铃后1秒内就能发现设备,体验完全没问题。

另外,广播数据长度也影响功耗。每个广播包最多31字节,但你不一定非要塞满。我习惯只放必要的数据——比如设备名称、服务UUID,其他信息放到扫描响应里。这样广播包更短,射频打开时间更少。

4.4 扫描事件功耗

扫描事件是接收端的行为。设备打开接收窗口,监听周围的广播包。扫描功耗取决于两个参数:扫描窗口和扫描间隔。

举个例子:

扫描窗口 = 30 ms(每次监听时长)
扫描间隔 = 100 ms(每100ms监听一次)
占空比 = 30 / 100 = 30%
平均电流 = 接收电流 × 占空比 = 8 mA × 30% = 2.4 mA

2.4mA!这可不是小数目。如果你让设备一直扫描,电池撑不了多久。我见过一些产品,扫描占空比设到100%(连续扫描),结果功耗比连接状态还高。

优化技巧:扫描占空比控制在10%以内比较合理。比如扫描窗口30ms,扫描间隔300ms,占空比10%,平均电流只有0.8mA。对于大多数应用场景,这个配置足够发现附近的设备了。

还有一个容易被忽略的点:扫描过滤。如果你只关心特定类型的设备,可以在扫描时设置过滤条件。比如只扫描带有特定服务UUID的设备,这样芯片可以忽略无关的广播包,减少处理功耗。我在做Beacon项目时就用过这招,扫描功耗直接降了一半。

我曾经踩过的坑:有一次做多设备组网,所有设备都在疯狂扫描,结果互相干扰,扫描成功率反而下降了。后来我加了随机退避——每个设备的扫描起始时间随机偏移,避免同时扫描造成冲突。这个改动不仅提高了扫描成功率,还意外降低了整体功耗。

小结

协议栈功耗说白了就是「时间×电流」的游戏。射频打开的时间越短、频率越低,功耗就越小。但你不能一味追求低功耗而牺牲功能——比如广播间隔设成10秒,设备半天发现不了,那产品就没法用了。

我的经验是:先满足功能需求,再优化功耗。把连接间隔、广播间隔、扫描占空比这些参数调到一个「够用就好」的范围,往往能省下50%以上的功耗。记住,BLE协议栈给了你很大的灵活性,但灵活性也意味着责任——配置不当,功耗翻倍;配置得当,续航翻倍。

下一章咱们聊聊射频前端的功耗优化,那又是另一个有意思的话题了。