简介:这份PDF资料聚焦杰理BLE芯片的功耗数据与降功耗方法,面向正在开发蓝牙低功耗产品、遇到功耗降不下来或无法满足客户续航要求的嵌入式工程师。内容以AC6321为例,系统梳理powerdown、poweroff、sniff三种功耗模式的特点与唤醒机制,并给出环境准备、软件配置、各阶段功耗分析及进出低功耗流程的完整思路。资源包内含1个PDF文件,大小约2.18MB,便于随时查阅与对照调试。目前已有2056人学习下载,说明其在杰理平台开发者中具有较高参考价值。读者可从中获得低功耗模式的具体电流数据、广播与连接状态的功耗波形解读、连接参数对功耗的影响,以及排查芯片不进低功耗、功耗偏高等问题的实用方向,适合需要优化BLE设备电池寿命的开发者参考。
1. 杰理 BLE 功耗从 185uA 压到 18uA:一份能照着复现的降功耗笔记
做杰理 BLE 案子的人,十个里有八个被功耗卡过脖子。客户要求整机待机 50uA 以内,你测出来 200uA 下不去;公版程序跑出来正常,自己写的代码一烧进去功耗直接翻倍。这类问题不是玄学,是有一整套可复现的排查路径的。这份笔记以 AC6321 为例,把杰理 BLE 芯片的功耗模式、测量方法、软件配置、进出低功耗机制和常见翻车点拆开讲一遍。适合正在用杰理 SDK 做透传、防丢器、Beacon 类产品的嵌入式工程师,也适合刚接手 BLE 项目、对 powerdown 和 sniff 还没建立直觉的新手。读完你至少能做到:知道正常功耗长什么样、知道自己的代码为什么不进低功耗、知道连接参数怎么影响平均电流。
2. 先把三个功耗名词和测量环境立住:powerdown、poweroff、sniff 到底差在哪
2.1 powerdown 与 poweroff:一个保连接,一个只留按键
杰理芯片的低功耗名词如果不先理清,后面看波形就是黑匣子。最核心的两个状态是 powerdown 和 poweroff。
poweroff 也叫 shutdown,软关机模式,功耗大约 2uA。这个模式下 RAM 掉电,芯片基本处于“只留一口气”的状态,唤醒方式只有按键和 RTC 闹钟。几乎所有芯片的 shutdown 功耗都在这个量级,不是杰理独有的优势,所以别拿这个数字去宣传续航。
powerdown 才是 BLE 产品真正要盯的状态。AC632 在 powerdown 下功耗约 18uA,RAM 不掉电,蓝牙连接可以保持。唤醒源比 poweroff 多一个:系统定时器中断也能把芯片拉出来。这意味着你的 BLE 从机可以在保持连接的同时,大部分时间躺在 18uA 里,每隔一段时间被定时器叫醒处理一下协议栈的事情,然后继续睡。
我一般会跟新人这么解释:poweroff 是“关机”,powerdown 是“打盹”。BLE 产品要的是打盹,不是关机。因为关机之后连接就断了,手机再连你得重新广播、重新配对,用户体验直接崩。
这里有个容易混淆的点:sniff 不是硬件状态,是蓝牙协议层的一种策略。它通过减少主设备发送数据的时隙数、相应减少从设备监听的时隙数来省电。但 sniff 省的是“射频监听”那部分的电,如果芯片本身没有进 powerdown,该跑的系统定时器还在跑,该唤醒的模块还在唤醒,实际功耗不一定降得下来。所以判断 sniff 有没有用,最终还是要看电流波形上芯片有没有频繁进入那个 18uA 的平台区。
2.2 测量环境:为什么电流表不如功耗盒子
测 BLE 功耗,普通万用表基本没法用。BLE 的电流是脉冲式的:广播时瞬间冲到几 mA,然后掉到 uA 级,再冲上去。万用表采样率不够,你看到的是一个被平均过的数字,根本不知道芯片在干什么。
常见做法是用功耗盒子,它能以波形方式显示电流随时间的变化。接线方式不同盒子可能有差异,但核心就两点:盒子输出给板子供电,盒子串在供电回路里采电流。第一次用之前先做“空载归零”,不然零点漂移会让你的 uA 级读数完全不可信。
注意:接板子之前,先用万用表量一下功耗盒子的输出电压。有些盒子输出会偏高,直接烧芯片。烧了芯片再测功耗,数据就没有意义了。
板子本身也要处理。如果你手上是样机,不是 demo 板,那就拆。把跟杰理芯片不相关的硬件全去掉,只留晶振、VBAT、VDDIO 脚的电容。支持 DCDC 的芯片可以保留 DCDC 部分电路。为什么要拆?因为一个 LDO、一颗 LED、一个上拉电阻,都可能在你测 18uA 的时候贡献出几十 uA 的偏差。你以为是芯片没进低功耗,其实是外围电路在漏电。
2.3 软件配置:测功耗前必须关掉的东西
软件层面,测功耗的工程建议用最简单的 BLE 透传单从机工程。功能越少,变量越少,功耗基线越干净。
板级配置里要动几个地方。串口在测功耗时可以开,但测数据的时候串口线不要接,接了以后功耗会偏低——因为串口线的电平会通过 IO 口倒灌电流,让你的读数比真实值小。AD 按键要关掉,软件开了 AD 按键但硬件没接,会导致芯片无法进入低功耗。低功耗模式要使能,DCDC 和 LDO 根据实际硬件选,DCDC 比 LDO 功耗低。电量检测和经典蓝牙也关掉,这两个模块在纯 BLE 透传场景下没有用,开着只会增加唤醒次数。
这些配置改完之后,把代码下载到 demo 板,接上功耗盒子,你才有资格开始谈“功耗高不高”。
3. 四个阶段的功耗波形怎么读:从广播 185uA 到连接 377ms 周期
3.1 低功耗平台:18-20uA 是及格线
下载程序后,串口如果有<>和[]打印,说明芯片有正常进出低功耗。<>是应用层的打印,[]是库里面的打印。用功耗盒子的游标去量波形最低点的功耗,应该在 18-20uA 之间。
如果这个值偏高,先排查芯片外围电路。把不相关的硬件断开,只留最小系统再测。如果还是高,换一块板子试试。我遇到过一块板子因为 VBAT 脚的一个电容漏电,低功耗平台一直在 35uA 下不去,换电容之后立刻回到 18uA。这种问题用万用表是看不出来的,只有波形能暴露。
3.2 广播状态:185uA 和 500ms 间隔
广播状态下,功耗波形是一串脉冲。两个波峰之间的间隔是广播间隔,常见配置是 500ms。近期的平均功耗大约 185uA。
这个 185uA 是怎么来的?芯片大部分时间在 powerdown 里,每隔 500ms 被广播定时器叫醒,启动射频发一包广播数据,然后继续睡。平均电流就是“睡眠电流 × 睡眠时间占比 + 广播瞬间电流 × 广播时间占比”的加权结果。想降广播功耗,要么拉长广播间隔,要么缩短每次广播的射频开启时间。但广播间隔改到 2s 以上,手机搜索到设备的速度会明显变慢,甚至有些手机直接搜不到。这是一个需要跟产品经理拉扯的取舍点。
3.3 上电状态:全擦 Flash 第一次上电为什么偏高
正常上电开机的波形,全擦 Flash 上电功耗会高一点。原因是芯片第一次上电会多一个校准流程,这个流程会消耗额外的电流。如果你测的是刚擦完 Flash 的板子,看到上电瞬间电流比平时高,不用慌,等校准完成之后会回落到正常水平。
这个阶段基本没有降功耗的空间,因为校准是芯片启动的必经流程。你要关注的是校准完成后的稳态功耗,而不是上电瞬间的峰值。
3.4 连接状态:interval、latency、timeout 怎么决定平均电流
连接状态是 BLE 产品待机功耗的大头。用 iPhone 测试,连接参数 interval=28、latency=10、timeout=600 时,两个波峰之间的时间大约是 377ms。
这个时间可以算出来。低功耗周期 = interval × 1.25 × latency,单位 ms。代入数值:28 × 1.25 × 10 = 350ms。实测 377ms 跟理论值相差不大,多出来的部分是协议栈处理和射频启动的固定开销。
有时候你会看到连续两个波峰,原因是杰理看门狗周期的一半也会触发低功耗退出。看门狗是硬件模块,它的唤醒不受连接参数控制,所以会在连接周期的中间插进来一次。如果你在波形上看到这种“双峰”,不用怀疑芯片坏了,这是正常现象。
连接参数怎么改?interval 决定从机多久起来跟主机通信一次,latency 决定从机可以跳过多少次连接事件,timeout 是连接超时时间。latency 设得越大,从机睡的时间越长,平均功耗越低。但 latency 太大会导致主机发数据时从机响应变慢,影响吞吐量。timeout 要大于 interval × (latency + 1) × 1.25 × 2,否则会误触发连接超时断开。
提示:公版流程是主机打开监听通道时,从机才会向主机请求自己的连接参数。所以你在代码里设了参数,不代表立刻生效,要等主机发起参数更新请求。
4. 进出低功耗的底层逻辑:REGISTER_LP_TARGET 和定时器怎么配合
4.1 芯片不能主动进低功耗,但可以阻止它进
杰理芯片的低功耗机制跟很多 MCU 不一样。你没法在代码里写一句“现在进入 powerdown”,芯片是在空闲的时候自动进低功耗的。当系统定时器产生中断时,芯片会主动退出低功耗。
程序不能控制芯片主动进低功耗,但可以控制芯片不要进低功耗。这个“阻止”机制就是REGISTER_LP_TARGET注册的回调函数。底层在准备进低功耗之前,会遍历所有注册的 LP target,调用它们的is_idle函数。如果任何一个返回 0,芯片就不进低功耗。
// 代码任意地方添加此段代码,全局修改此变量,底层会自动获取判断 u8 can_enter_lp = 0; // 置 1 可进睡眠,置 0 不可进睡眠 static u8 custom_idle_query(void) { if (can_enter_lp) { return 1; // 允许进低功耗 } else { return 0; // 阻止进低功耗 } } REGISTER_LP_TARGET(custom_lp_target) = { .name = "custom_lp", .is_idle = custom_idle_query, };这段代码的逻辑是:定义一个全局变量can_enter_lp,在任意地方修改它。custom_idle_query是底层会调用的查询函数,返回 1 表示当前允许进低功耗,返回 0 表示不允许。REGISTER_LP_TARGET宏把这个 target 注册到低功耗管理模块里。
参数说明:.name是 target 的名字,调试用;.is_idle是查询函数指针,底层在进低功耗前会调用它。如果你有多个模块需要控制低功耗,可以注册多个 target,任何一个返回 0 都会阻止芯片进低功耗。
4.2 系统定时器:功耗和实时性的拉扯
sys_timer_add和sys_timeout_add是杰理 SDK 里常用的两个定时器接口。它们底层用的是系统定时器,会产生中断,把芯片从 powerdown 里拉出来。
u16 sys_timer_add(void *priv, void (*func)(void *priv), u32 msec); u16 sys_timeout_add(void *priv, void (*func)(void *priv), u32 msec);sys_timer_add是周期性定时器,每隔msec毫秒调用一次func。sys_timeout_add是一次性定时器,msec毫秒后调用一次func,然后自动释放。priv是传给回调函数的私有参数,func是回调函数指针。
这两个接口用起来方便,但对功耗不友好。每调用一次,芯片就要退出低功耗一次。如果你在代码里开了很多系统定时器,芯片进出低功耗的频率会非常快,平均功耗自然就上去了。
如果在意功耗,我一般会建议用硬件定时器替代系统定时器。硬件定时器可以在低功耗模式下继续计数,不需要 CPU 频繁唤醒。但硬件定时器的接口比系统定时器复杂,需要配置寄存器,而且数量有限。这是一个典型的“功耗换开发效率”的取舍。
4.3 usr_timer 的 priority 参数:0 和 1 的区别
SDK 里还有一个usr_timer_add接口,它的priority参数直接决定了对低功耗的影响。
/** * @brief usr_timer 定时扫描增加接口 * @param [in] priv 私有参数 * @param [in] func 定时扫描回调函数 * @param [in] msec 定时时间,单位:毫秒 * @param [in] priority 优先级,范围:0/1 * @return 定时器分配的 id 号 * @note * 1、usr_timer 的参数 priority 为 1,使用该类定时器,系统无法进入低功耗; * 2、usr_timer 的参数 priority 为 0,使用该类定时器,系统低功耗会忽略该节拍, * 节拍不会丢失,但是定时周期会变; * 3、usr_timer 属于异步接口,add 的时候注册的扫描函数将在硬件定时器中时基到时被调用; * 4、对应释放接口 usr_timer_del。 */ u16 usr_timer_add(void *priv, void (*func)(void *priv), u32 msec, u8 priority);priority=1时,系统无法进入低功耗。这个模式适合对定时精度要求极高的场景,比如某些传感器采样。priority=0时,系统低功耗会忽略这个节拍,节拍不会丢失,但定时周期会变。什么意思?就是芯片该睡还是睡,定时器到点了会记录一个标志,等芯片醒来之后再处理。这样功耗保住了,但定时精度下降了。
选哪个取决于你的产品需求。如果只是 LED 闪烁、状态轮询,priority=0完全够用。如果是射频时序控制、精确采样,那就得用priority=1,接受功耗上升的代价。
5. 避坑排查:公版正常、自己代码功耗高的四类原因
5.1 芯片直接不进低功耗
现象:功耗一直在 mA 级,波形上看不到 18uA 的平台区,串口也没有<>和[]打印。
原因一:REGISTER_LP_TARGET注册的函数有地方没有返回 1。底层遍历所有 target 时,只要有一个返回 0,芯片就不进低功耗。检查你的is_idle函数,确认所有分支都有正确的返回值。
原因二:板级配置里面低功耗没有使能。这个在 SDK 的板级配置文件里,不同版本位置可能不一样,但关键词是LP或low_power。确认对应的宏是打开的。
原因三:自己写的代码耗时太长,导致芯片进不了低功耗。芯片是在空闲时进低功耗的,如果你的主循环里有一个函数执行了几百毫秒,芯片就一直没机会睡。排查方法是用示波器抓函数前后,在函数入口和出口翻转一个 IO 口,看高电平持续时间。如果超过几毫秒,就要考虑把这个函数拆成状态机,分多次执行。
原因四:其他模块阻止了低功耗。比如某些外设驱动在初始化时注册了自己的 LP target,但没有正确释放。这种情况需要逐个排查最近添加的模块。
5.2 芯片有进低功耗但功耗偏高
现象:串口有<>和[]打印,波形上能看到低功耗平台,但平台电流不是 18uA,而是 50uA、100uA 甚至更高。
原因一:DP、DM 脚做输出会高 300uA。USB 的 DP、DM 脚如果配置成输出模式,即使没有 USB 通信,也会产生额外的漏电流。检查你的 IO 配置,把不用的 USB 脚设成高阻或输入。
原因二:IO 口同时开上下拉电阻。一个 IO 口同时开上拉和下拉,相当于在电源和地之间接了一个电阻,电流直接漏掉。检查所有 IO 的上下拉配置,确保没有同时使能。
原因三:外围电路漏电。前面提过的电容漏电、LDO 静态电流、LED 漏电流,都会叠加到芯片的低功耗平台电流上。把外围电路逐个断开,看平台电流有没有变化。
5.3 芯片进出低功耗频率太快
现象:波形上低功耗平台很短,波峰很密,平均功耗比预期高很多。
原因:调用了太多的系统定时器。每个sys_timer_add都会产生周期性中断,把芯片从低功耗里拉出来。如果你开了 5 个 10ms 的定时器,芯片每 10ms 就要醒一次,低功耗平台根本来不及稳定。
解决:如果在意功耗,避免系统定时器的使用,改用硬件定时器。或者把多个定时任务合并到一个定时器里,用计数器分频。比如一个 10ms 的定时器,在里面计数到 100 再执行 1s 的任务,这样芯片只需要每 10ms 醒一次,而不是每个任务都单独唤醒。
5.4 连接状态功耗降不下来
现象:广播状态功耗正常,一连接功耗就上去了。
原因:连接参数没设对,或者主机没有接受从机的参数更新请求。连接状态的低功耗周期由 interval 和 latency 决定,如果 latency 是 0,从机每个连接事件都要起来,功耗自然高。
解决:在代码里请求合适的连接参数,latency 尽量设大,但不要超过主机允许的范围。同时确认主机是否接受了参数更新。有些手机对 latency 有限制,比如 iOS 对某些参数组合会拒绝。如果主机拒绝,从机只能接受主机的参数,这时候功耗就取决于主机的配置了。
6. 把功耗压到极限的几个进阶技巧和验证习惯
6.1 用 IO 翻转做时间测量
当你怀疑某个函数耗时太长导致芯片进不了低功耗时,最直接的方法是在函数入口和出口翻转一个 IO 口,用示波器看高电平持续时间。
// 假设 PA0 是调试 IO gpio_set_output(PA0); gpio_write(PA0, 1); // 函数入口拉高 my_long_function(); gpio_write(PA0, 0); // 函数出口拉低这个方法的精度取决于示波器带宽和 IO 翻转速度,对于毫秒级的函数完全够用。如果高电平持续时间超过你预期的低功耗周期,就要考虑拆分函数。
6.2 分阶段验证功耗
不要一上来就测整机功耗。按阶段来:先测最小系统板在 powerdown 下的平台电流,确认是 18uA;再测广播状态的平均电流,确认是 185uA 左右;再测连接状态,确认低功耗周期符合公式;最后才测整机。
每个阶段都确认正常之后,再往上叠加功能。这样一旦功耗异常,你能快速定位是哪个阶段引入的。
6.3 连接参数的计算和验证
低功耗周期 = interval × 1.25 × latency(单位 ms)。这个公式要记牢。设置参数时先算一遍理论值,再用功耗盒子测实际值,两者对比。
| 参数 | 含义 | 对功耗的影响 | 建议范围 |
|---|---|---|---|
| interval | 连接事件间隔 | 越大功耗越低 | 28-80(35-100ms) |
| latency | 可跳过的连接事件数 | 越大功耗越低 | 4-20 |
| timeout | 连接超时时间 | 需大于周期×2 | 600-2000(6-20s) |
timeout 的计算:timeout > interval × (latency + 1) × 1.25 × 2。比如 interval=28、latency=10,周期是 350ms,timeout 要大于 700ms。实际设置时留足余量,600(6s)是安全的。
6.4 看门狗周期对功耗的隐藏影响
前面提过,杰理看门狗周期的一半也会触发低功耗退出。这意味着即使你的连接参数设得很大,看门狗还是会定期把芯片叫醒。如果你在波形上看到连接周期的中间有一个额外的波峰,那就是看门狗干的。
看门狗周期能不能改?可以,但要看 SDK 是否开放了配置接口。有些版本看门狗周期是固定的,你只能接受这个额外的唤醒。如果看门狗周期是 1s,那芯片最多每 500ms 就会被叫醒一次,连接参数设得再大也突破不了这个下限。
我一般会在项目初期就把看门狗周期确认清楚,把它纳入功耗预算。如果看门狗周期不可改,那连接参数的优化空间就有限,需要跟产品经理同步这个限制。
6.5 一个验证习惯
从那以后我每次改完功耗相关的配置,都会强制走一遍完整验证:擦 Flash、重新烧录、功耗盒子归零、测平台电流、测广播电流、测连接电流、记录波形。不跳步骤,不凭感觉。因为功耗问题最怕的就是“我以为改好了”,结果一测还是老样子。希望帮到你。
本文还有配套的精品资源,点击获取