BlueNRG-LP/LPS低功耗模式详解:SMPS配置与实测电流排障指南 做 BLE 产品的朋友应该都有这种经历方案选型的时候看数据手册睡眠电流几百纳安、微安级别续航算下来漂亮得很。结果板子一打样实测平均电流直接翻了几倍找半天不知道电耗在哪了。BlueNRG-LP、BlueNRG-LPS 这两颗芯片ST 官方给的功耗数据确实很能打但“能打”的前提是模式选对、配置到位、外围不拖后腿。这篇应用笔记我就把这两颗芯片的省电模式从原理到代码到实测排障完整捋一遍重点讲清楚省电模式之间的区别、SMPS 和 LDO 怎么选、SDK 里哪些配置真正影响功耗以及为什么你的板子总是多耗几百微安。在进入正题之前先想清楚一个问题BLE 设备的平均功耗不是由“某一个模式”决定的而是由整个事件驱动模型决定的。设备大部分时间在睡觉但每一次醒来、做一次射频收发、再睡回去这个过程里每一毫秒的电流和每一微安的睡眠电流最后都会被平均到整个运行周期里。所以省电模式的理解不能停留在“能睡多深”而是要看整套机制怎么配合。1. BLE 设备平均电流的“大头”与省电的核心逻辑1.1 事件驱动模型的功耗预算拆法BLE 协议是典型的事件驱动型协议。无论是广播Advertising还是连接Connection芯片并不是一直在收发数据而是在固定的时间点醒来完成几个毫秒的射频操作后立刻回到睡眠状态。以一次广播事件为例设备在广播信道 37、38、39 三个信道上依次发送广播包整个过程持续约 1 到 3 毫秒期间电流在毫安级别。但如果广播间隔是 1 秒那么这 1 毫秒左右的毫安级电流会被分摊到整整 1 秒的周期里。平均电流的计算逻辑并不复杂[ I_{avg} \frac{I_{event} \times T_{event} I_{sleep} \times T_{sleep}}{T_{event} T_{sleep}} ]举个例子一次广播事件按 3 个信道算假设发射电流 4.3mA持续时间 1.2ms广播间隔 1s睡眠电流 1µA。那么[ I_{avg} \frac{4.3 \times 1.2 0.001 \times 998.8}{1000} \approx 6.2µA ]算下来并不吓人。但问题在于如果芯片没有真正进入睡眠或者每秒钟被一个周期中断唤醒一次干点别的事哪怕只是醒着跑几百微秒平均电流都会显著上升。1.2 三个指标决定电池寿命吃透省电模式之前要先盯住三个指标第一个是射频事件电流也就是收发一个包时芯片的实际电流。这个值一般在数据手册里能看到典型值BlueNRG-LP 在输出功率 0dBm 时发射电流约为 4.3mA接收电流约为 3.4mA。这个数值在不同供电配置下会有差异后面讲 SMPS 和 LDO 时会详细说。第二个是睡眠电流也就是事件之间芯片睡着的电流。这个值直接决定了设备在不干活的绝大多数时间里消耗多少电。对于低频次上报的传感器、电子价签、资产标签这类产品设备 99% 以上的时间都在睡觉睡眠电流的每 0.1µA 差异都可能在电池寿命上放大成几周甚至几个月的变化。第三个是唤醒和进入睡眠的开销。芯片进入睡眠需要时间醒来也需要时间期间要恢复时钟、等待稳压器稳定、重新加载上下文。如果每次事件前后都花几十微秒在状态切换上而单次射频事件本身也就一毫秒多这个开销就非常可观了。1.3 BlueNRG-LP/LPS 的省电设计思路BlueNRG-LP 和 BlueNRG-LPS 的底层是一颗 ARM Cortex-M0 内核跑的是 ST 的 BLE 协议栈。省电设计的核心思路是让协议栈自动管理 CPU 的睡眠和唤醒应用代码不需要每次手动执行 WFI 指令。协议栈在完成当前所有待处理的 BLE 事件后会计算出下一个需要醒来的绝对时间点然后自动配置一个低功耗定时器LPTIM 或者 RTC接着进入睡眠。这个过程对一个 BLE 应用来说几乎是透明的。但之所以很多工程师用这颗芯片还是做不出低功耗产品问题往往出在应用代码本身把协议栈“叫醒”了比如主循环里跑了一个阻塞延时、周期性的 SysTick 中断不断触发、或者某个外设没有正确关闭。后面我会专门讲这些坑。2. BlueNRG-LP / LPS 功耗模式全景从 Run 到 Shutdown芯片的省电模式不是一个开关而是一组从浅到深的睡眠等级。不同模式下CPU、时钟、内存、外设和唤醒源各有不同的保留状态。理解这组模式是配置省电逻辑的第一步。模式CPU 状态时钟状态RAM 保留典型电流量级唤醒方式Run运行全部高频时钟全部由负载决定mA 级别-Low Power Run运行低频模式只剩低频时钟全部数百 µA 以下-Sleep停止可保留 LPTIM/RTC 等低功耗时钟全部或大部分1µA 左右或以下低功耗定时器、GPIO、BLE 事件Low Power Sleep停止内部稳压器进入更低功耗状态低频时钟可选可按需保留通常比 Sleep 更低低功耗定时器、GPIO、BLE 事件Standby停止基本全部关闭不保留或仅部分备份寄存器数百 nA 级别特定唤醒引脚、复位Shutdown停止大部分电源域断开全部关闭不保留最低几十到几百 nA上电复位、特定唤醒引脚2.1 Sleep 模式绝大多数 BLE 应用的主战场先说 Sleep 模式。这是 BLE 设备用得最多的一种模式也是协议栈默认进入的模式。在 Sleep 模式下CPU 停止取指执行但 SRAM 保持供电低功耗定时器和部分外设时钟可以继续运行。这样做的最大好处是芯片从 Sleep 模式唤醒后可以立即从原上下文继续执行不需要重新初始化系统和协议栈。对 BlueNRG-LP 来说Sleep 模式下的电流可以做到 1µA 上下具体数值取决于保留的 SRAM 大小、供电方式SMPS 还是 LDO、内核电压档位以及 LPTIM、RTC 等模块是否开启。如果你的产品在两次 BLE 事件之间不需要做额外的传感采集Sleep 模式就足够用了。2.2 Low Power Sleep省到极致时的取舍Low Power Sleep 是比 Sleep 更深一级的模式。它会把内部高速稳压器切换到更低功耗的配置进一步压低静态电流。代价是唤醒时间变长因为恢复高速时钟和稳压器输出需要额外的时间。如果你的产品两次事件之间的间隔比较长比如广播周期到了秒级以上或者连接但启用了较大的从机延迟那么多花几个微秒唤醒完全不影响整体功耗反而能省下零点几微安的睡眠电流。从工程角度Sleep 和 Low Power Sleep 的选择并不是非黑即白。我的建议是先用功耗分析仪测整机在 Sleep 模式下的实际电流如果和芯片手册里的典型值还有差距再考虑切到 Low Power Sleep 继续压。切换之前要确认唤醒时间增加后BLE 协议栈是否还能在事件到达前恢复完成。ST 的协议栈在初始化蓝牙时会对事件时间进行计算一般不会出问题但应用自定义的 GPIO 中断唤醒如果对响应时间敏感就需要留意。2.3 Standby / Shutdown只能用于特殊场景的极端选项Standby 和 Shutdown 模式属于“深睡”选项。这两个模式会关闭绝大部分电源域RAM 数据不再保留唤醒后更像一次冷启动。之所以 BlueNRG-LP/LPS 还提供这两个模式是为了配合外部低功耗管理逻辑。例如设备靠一个物理开关按键唤醒或者外部传感器在检测到特定事件后才需要唤醒主控那么用 Standby/Shutdown 模式可以把睡眠电流压到纳安级。但使用这两个模式的代价很大BLE 协议栈状态会丢失再次唤醒后要重新初始化协议栈、重新广播或重新发起连接。整个过程可能会耗费几毫秒甚至几十毫秒瞬时电流也比较高。所以一般只有两类产品会用到一类是按键触发的电子锁、遥控器另一类是带外部独立 RTC 定时唤醒的超低功耗采集终端。如果是普通的 BLE 周期上报产品老老实实用 Sleep 或 Low Power Sleep 就行。3. SMPS 还是 LDO供电路径选不对模式白配3.1 两种供电路径的电流差异BlueNRG-LP 芯片内部集成了 SMPS开关电源和 LDO 两条供电路径用于给数字核心逻辑供电。选择不同路径直接影响芯片在射频事件和运行状态下的电流大小。简单对比一下LDO 方案结构简单外围只需要极少电容成本低但 LDO 的转换效率是线性的供电电压越低、压差越大浪费在热量上的能量就越多。而 SMPS 方案需要用外部电感和电容能实现更高的转换效率特别是射频发射这种瞬时大电流场景下SMPS 的节电优势非常明显。ST 给的数据里SMPS 使能时射频收发电流可以比 LDO 路径低 10% 到 20% 左右这个数字在电池供电产品里相当可观。如果你的产品使用纽扣电池并且每天都要进行 BLE 广播或连接通信我建议优先使用 SMPS。虽然电路上多了两个元件但对整机续航的提升是立竿见影的。3.2 SMPS 外围选型与布局注意SMPS 外围选型是很多人忽略的细节。电感选型不当不仅效率上不去甚至可能造成射频杂散发射变差。以下是几个实际项目里验证过的要点电感量BlueNRG-LP 在 SMPS 模式下典型应用电路里用的是 10µH 的电感。一定要用手册参考设计里的推荐值不要随意加大或减小。电感量偏差过大可能导致 SMPS 环路不稳定影响射频性能。电感 DCRDCR 越小电感的效率越高。但 DCR 小的电感往往体积更大、价格更高。对纽扣电池应用建议选择 DCR 在几百毫欧以下的贴片电感不要用小体积高 DCR 的功率电感。输出电容参考设计里的电容值也不要随意改动。SMPS 的补偿网络对输出电容的 ESR 有一定要求乱换电容可能出现啸叫或者动态响应问题。PCB 布局SMPS 的开关节点要短粗电感靠近芯片的 SW 引脚反馈走线远离开关节点。这部分如果布局不好轻载时的损耗会明显偏大睡醒后恢复时间也可能变长。3.3 切换 SMPS/LDO 的软件点在 ST 的 SDK 中供电模式通常在系统初始化时通过电源管理接口配置。以 BlueNRG-LP 的 LL 驱动为例一般会有一个设置电源模式的枚举比如SMPS和LDO两种选项。配置位置在 Platform 初始化代码里和时钟配置放在一起。伪代码大致是这样的/* 选择电源模式为 SMPS */ PWR_SetRegulatorMode(PWR_REGULATOR_MODE_SMPS); /* 选择内核电压档位 */ PWR_SetCoreVoltage(PWR_CORE_VOLTAGE_1V1);内核电压档位也需要关注。数字核心电压越低运行功耗和睡眠功耗越低但最高运行频率可能会受限。如果你的应用不需要 CPU 跑满主频可以选低一档的内核电压来换取功耗优势。具体档位和频率的对应关系以数据手册为准。4. SDK 工程里真正“启用”省电模式的几个关键开关拿到一个 BlueNRG-LP 的示例工程后默认跑起来可能是可以正常通信的但功耗未必是最优的。要把省电模式真正“打开”需要逐个确认下面几个关键开关。4.1 Tickless 机制BLE 协议栈需要知道下一个广播或连接事件的时间传统做法是用一个周期性的系统节拍tick来计时。但每 1ms 一次的中断会周期性地唤醒 CPU这个开销在低功耗应用里不可接受。BlueNRG-LP 的协议栈支持 Tickless 模式也就是不依赖固定周期中断而是在进入睡眠前计算好下一个应唤醒的绝对时间并配置到低功耗定时器上。SDK 里通常在协议栈初始化参数中或预编译宏里选择是否使能 Tickless。如果工程里默认没有开启而你的应用又对功耗敏感需要修改配置。开启后SysTick 不再作为协议栈的时间基准应用自身的延时函数最好也改为基于 LPTIM 或系统毫秒计数器的非阻塞方式。4.2 主循环中 power manager 的结构很多人的初始化代码写得很好协议栈也正常跑但主循环里每个循环都会执行一次延时等待导致 CPU 根本无法进入睡眠。正确的结构应该是主循环里尽量不做阻塞操作应用有事件时处理没事件时直接进入低功耗模式。while (1) { /* 处理协议栈事件 */ Ble_Hci_Process(); /* 处理应用事件 */ App_Process(); /* 没有待处理任务进入低功耗 */ PWR_EnterSleepMode(PWR_SLEEPMODE_SLEEP, NULL); }注意PWR_EnterSleepMode这行代码的位置。如果把它放在一个条件分支后面而条件绝大多数时候为假CPU 就会一直空转电流直接停留在正常运行的毫安级别。协议栈自身在睡眠前会停掉部分时钟但应用主循环如果不配合效果会大打折扣。4.3 时钟、SysTick 和唤醒源的配合进入低功耗模式后高频晶振和 PLL 可以关闭但协议栈在睡眠前会确保 LPTIM 或 RTC 处于运行状态以提供事件唤醒功能。这里容易出问题的是 SysTick 和 HAL 库的HAL_Delay函数。如果 SDK 的延时驱动没有感知低功耗状态一个基于 SysTick 的HAL_Delay(1)就会让系统定时器周期性地唤醒 CPU即使睡眠模式生效平均电流也会被拉高几十微安。建议在低功耗工程中所有应用层的延时都改成基于 tickless 唤醒机制或者在进入睡眠前显式关闭 SysTick唤醒后再恢复。4.4 保留 RAM 大小的配置Sleep 和 Low Power Sleep 模式下SRAM 可以全部保留也可以只保留部分。保留的 RAM 越多睡眠电流越高。SDK 里通常有配置宏可以指定保留区域。对于绝大多数 BLE 应用协议栈和应用程序用到的 RAM 必须保留否则唤醒后数据就丢了。但如果某些大数组只在运行阶段使用且不需要跨睡眠保存可以把它分配到可关闭的 RAM 区域。实际操作中可以通过查看编译器的 map 文件和 SDK 的 RAM 分区配置来调整。5. 用广播与连接参数把平均电流压到微安级芯片的功耗模式配置好之后决定平均电流的就是协议参数了。广播间隔、连接间隔、从机延迟、监管超时这些参数每一个都直接影响事件频率和射频收发次数。5.1 平均电流估算公式在连接状态下一个连接事件通常只在一个射频信道上完成一次 TX 和一次 RX。把收发电流近似为 5mA、事件占用约 2ms连接间隔 30ms睡眠电流 1µA那么平均电流大约是[ I_{avg} \frac{5 \times 2 0.001 \times 28}{30} \approx 334µA ]这个数字对纽扣电池应用来说太高了。如果不想改硬件唯一能压的就是参数。把连接间隔从 30ms 放宽到 100ms并且用从机延迟Slave Latency让设备每 4 个连接事件只监听 1 次那么有效监听间隔变成 400ms。此时平均电流变为[ I_{avg} \frac{5 \times 2 0.001 \times 398}{400} \approx 26µA ]功耗直接下降一个数量级。这就是 BLE 功耗调优的核心手段在不影响业务实时性的前提下尽可能拉长监听间隔。5.2 广播间隔和连接参数广播场景的参数同样重要。广播间隔越长平均电流越低但设备被发现的速度越慢。如果产品是绑定模式下才广播建议把广播间隔设成 50ms 到 100ms 的短间隔让主机快速扫描到完成配对后再进入连接状态依靠连接参数来控制功耗。连接参数包括 Connection Interval、Slave Latency 和 Supervision Timeout。需要特别注意的是这组参数不是从机单方面说了算主机也可能发起参数更新请求。作为从机可以在GAP_UpdateConnectionParameters()时提交期望的参数组合并配置参数更新权限。实际很多手机主机会强行采用自己的参数所以产品设计时要做好两个方向的准备主机参数激进时如何保证实时性主机参数宽松时如何节能。5.3 典型场景参数表场景推荐广播间隔连接间隔从机延迟说明电子价签广播仅配对阶段配对后连接100ms3-7低频更新显示内容事件间隔可拉长资产标签广播间隔 1s-10s不常连接无广播为主连接仅维护时使用可穿戴通知广播间隔 30ms-100ms30ms-50ms0-1需要较快的通知延迟功耗较高低功耗传感器广播间隔 1s-10s无无数据通过广播承载最快方式上报5.4 官方功耗计算工具与实测验证ST 官方有基于 Excel 的功耗估算工具输入工作电压、广播参数、连接参数、GPIO 负载等可以估算平均电流和电池寿命。这个工具在方案初期的选型阶段非常实用能快速判断当前参数方案是否满足续航目标。但工具算出来的数字始终是理论值。板子到手后我建议用功耗分析仪抓整机的电流曲线把事件电流、事件持续时间、睡眠电流分别读出来然后反推实际平均电流。如果实测值和工具估算值差距超过 20%先检查有没有外设漏电再看睡眠前是不是有 GPIO 没有处理到位。6. 实测排障板子莫名其妙多耗几百微安的常见原因最后说几个我在实际项目里遇到最多的“伪低功耗”问题。这四个问题几乎覆盖了 80% 的功耗异常场景。6.1 GPIO 配置和外部器件漏电最常见的坑是 GPIO 浮空输入。芯片进入睡眠后如果某个 GPIO 被配置为浮空输入引脚电位不稳定内部输入缓冲会不断产生翻转电流。这个问题在有些 MCU 上不明显但在 BlueNRG-LP 这种微安级睡眠电流的设计里一个浮空引脚就可能吃掉零点几微安甚至几微安。处理方法是逐个检查未使用引脚把它们配置为模拟模式、或者配置为输出低电平避免悬空。连接外部传感器或上拉电阻的引脚要确认外部器件在其电源关闭时是否会通过 GPIO 反灌电流。如果传感器供电由 GPIO 控制先断供再进睡眠顺序不能反。6.2 调试器和复位电路的影响开发阶段接调试器时功耗测量几乎不能作为参考。调试器的供电、SWD 引脚的上下拉都会给目标芯片额外供电或产生漏电路径。测量低功耗电流时一定要断开调试器用电池或用稳压电源给板子供电并禁止调试接口。复位电路也有讲究。外部复位引脚不能悬空通常要接一个合适的上拉电阻。如果复位电容太大上电复位时间变长也会影响低功耗状态下的可靠性。6.3 测量方法示波器 vs 万用表测量平均电流时用万用表直接串联在电源线上只能看到平均值无法看到事件电流和睡眠电流的分布一旦事件电流持续时间很短平均值可能看起来还行但实际电池容量消耗却很高。测量瞬时电流波形建议用低噪声示波器配合电流探头或者在电源轨上串联一个 1Ω 精密采样电阻用差分探头测量电阻两端压降。睡眠电流的测量要特别注意量程切换。万用表在毫安档时内阻较小但测微安级电流时分辨率不够在微安档时表笔内阻又可能影响芯片的供电。最稳妥的方案是使用支持自动量程的精密功耗分析仪或者用并联在供电端的示波器电流探头。6.4 校准与闪存访问BlueNRG-LP 的射频前端在唤醒后会执行校准流程以保证射频指标。如果配置成每次醒来都执行完整校准那么每次事件的时间会长不少平均电流随之增加。SDK 里通常有校准配置可以根据晶振稳定性和温度变化速度选择合适的校准策略比如降低校准频率或延后校准。闪存访问本身也会产生额外电流。如果在协议栈处理事件期间应用代码频繁读写 Flash会拉高事件期间的峰值电流。建议把需要掉电保存的数据集中在一个时间段写入避免在射频收发的前后窗口里做 Flash 操作。根据我自己的排查经验如果你发现实测电流比估算值高很多不要先怀疑芯片按照“睡眠前 GPIO 状态 → 外部器件漏电 → 调试连接 → 测量方法 → 协议参数”这个顺序查成功率最高。最后再分享一个小经验每次进入睡眠前把主循环里所有 HAL 的锁存中断标志和 GPIO 状态打一次日志出问题的时候翻日志定位比埋头改代码快得多。