先说结论
蓝牙BLE连接参数调不对,功耗和体验至少废一个。三个核心参数:连接间隔决定多久通信一次,从机延迟决定从机可以睡多少轮,超时时间决定多久没响应就算断开。记住一个核心逻辑:越短越快越费电,越长越慢越省电。 传感器上报类用大间隔+高延迟省电,键鼠控制类用小间隔+零延迟保响应。这篇把三个参数的含义、配置公式、坑点全讲透,参数选错了你自己能排查出来。
三个参数到底是什么?
连接间隔(Connection Interval)
设备连上之后,数据不是一直传的,而是按固定时间窗口定期交换。每个窗口叫一个连接事件(Connection Event),两个连接事件之间的时间就是连接间隔。
BLE协议规定范围:7.5ms ~ 4s
| 连接间隔 | 适用场景 | 响应延迟 | 功耗等级 |
|---|---|---|---|
| 7.5-11.25ms | 键鼠/游戏手柄 | <10ms | 最高 |
| 20-50ms | 音频/心率带 | 20-50ms | 高 |
| 100-200ms | 智能手表/数据采集 | 100-200ms | 中 |
| 500ms-2s | 温湿度/门锁/传感器 | 秒级 | 低 |
| 2s-4s | 超低功耗传感器 | 秒~十秒级 | 极低 |
从机延迟(Slave Latency)
这个参数是说从机可以"跳过"多少个连接事件不响应,直接睡觉。比如设slave_latency=9,意思是手机发过来的连接事件,从机可以选择性忽略,最多跳过9轮不醒。
范围:0 ~ 499(BLE协议上限)
这个设计的精妙之处:BLE连接建立后手机会定期发空包试探从机在不在。如果每次都要从机醒来收包回复,功耗会非常高。从机延迟让从机在没数据要传的时候"装死",多睡几觉省电。
超时时间(Supervision Timeout)
从机多久没响应就算"死了",主机主动断开连接。
范围:100ms ~ 32s
三个经典场景的参数配置
场景一:低功耗传感器(最常见)
温湿度计、烟雾报警器、智能门锁这类设备,数据量小、频率低、续航要求高。
典型配置:
- 连接间隔:1-2s(Nordic SDK里写成800-1600)
- 从机延迟:9(最多跳过9个连接事件,相当于从机9-18秒才醒一次)
- 超时时间:6-8s(留够余量)
场景二:实时控制(鼠标/键盘/手柄)
用户按下去必须马上有反应,延迟容忍度极低。
典型配置:
- 连接间隔:7.5-11.25ms(Nordic SDK里写成6-9)
- 从机延迟:0(每次连接事件都要响应,不跳过)
- 超时时间:200-400ms(断连检测要快)
场景三:中等速率数据流(心率/血氧/计步)
每秒1-2个数据包,持续有数据但频率不高。
典型配置:
- 连接间隔:50-100ms
- 从机延迟:0-4
- 超时时间:500ms-1s
关键公式:超时时间必须大于这个值
这是最容易出错的地方。BLE协议要求:
超时时间 > (1 + 从机延迟) × 连接间隔 × 2
这个不等式必须成立,否则手机会误判连接断了。
举例:
- 连接间隔 = 1s = 1000ms
- 从机延迟 = 9
- 最低超时 = (1+9) × 1000ms × 2 = 20000ms = 20s
- 建议设 = 24s(留20%余量)
常见错误场景:
设了连接间隔1s,从机延迟99,超时设了4s。
- 最低要求 = (1+99) × 1000ms × 2 = 200s
- 你设了4s → 不到4秒手机就认为设备死了,强制断连
- 这就是为什么很多设备"用着用着就自己断开了"
代码配置示例
Nordic nRF52832 SDK
#include "ble_conn_params.h"
// 推荐连接参数(低功耗传感器场景)
static ble_gap_conn_params_t low_power_conn_params = {
.min_conn_interval = MSEC_TO_UNITS(1000, UNIT_1_25_MS), // 最小间隔 1000ms
.max_conn_interval = MSEC_TO_UNITS(1200, UNIT_1_25_MS), // 最大间隔 1200ms
.slave_latency = 9, // 从机延迟:跳过9个连接事件
.conn_sup_timeout = MSEC_TO_UNITS(6000, UNIT_10_MS), // 超时 6000ms = 6s
};
// 连接参数更新模块初始化
void conn_params_init(void) {
ret_code_t err_code;
ble_conn_params_init_t cp_init = {0};
cp_init.p_conn_params = &low_power_conn_params;
// 连接建立后5秒再请求参数更新(避免一连接就要求换参数)
cp_init.first_conn_params_update_delay = APP_TIMER_TICKS(5000);
// 后续每30秒检查一次是否需要更新
cp_init.next_conn_params_update_delay = APP_TIMER_TICKS(30000);
// 最多重试3次
cp_init.max_conn_params_update_count = 3;
err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);
}
实战中最容易踩的三个坑
坑1:iOS不接受你请求的参数
iOS对连接间隔有硬性范围限制:20ms ~ 2s。超出这个范围iOS会强制压缩到你设的最大值附近,或者直接拒绝请求。
建议:连接建立后主动发起参数更新请求,给iOS一个它能接受的参数范围。
坑2:从机延迟太大导致数据积压
从机延迟=99时,如果手机在99个连接事件里持续发数据,从机醒来后要一口气接收所有数据,接收缓冲区很容易溢出丢包。
建议:从机延迟不要超过10,且固件里加流控。
坑3:参数更新请求发太早被手机拒绝
连接刚建立就发参数更新请求,iOS可能会认为是攻击行为直接拒绝。
正确时机:
- 首次参数更新:连接建立后5-8秒
- 后续检查周期:每30-60秒检查一次
参数速查表
| 应用场景 | 连接间隔 | 从机延迟 | 超时时间 | 平均电流 | 响应延迟 |
|---|---|---|---|---|---|
| 温湿度/门磁 | 1-2s | 9-19 | 6-8s | 1-5μA | 秒级 |
| 心率/血氧 | 50-100ms | 0-4 | 500ms-1s | 10-30μA | 50-100ms |
| 蓝牙鼠标/键盘 | 7.5-11.25ms | 0 | 200-400ms | 30-80μA | <10ms |
| OTA固件升级 | 7.5ms | 0 | 200ms | 100mA+ | <10ms |
| 语音数据流 | 7.5-20ms | 0 | 200ms | 100-500μA | <20ms |
常见问题Q&A
Q1:设备老是莫名其妙断开连接,怎么排查?
按这个顺序排查:①打印连接事件日志,看是哪种断开原因;②检查超时时间公式有没有算对;③用Nordic的Power Profiler Kit实测电流波形;④检查是否是距离问题;⑤换手机测试,排除手机蓝牙兼容性问题。
Q2:iOS和Android连接参数表现不一样,是谁的问题?
iOS对参数要求更严格:间隔范围20ms-2s,超出会被压缩。Android五花八门,有的接受大间隔有的不接受。建议:连接后主动发起参数更新请求,给一个双方都能接受的中间值。
Q3:连接建立后多久发参数更新请求最合适?
用Nordic SDK的话,ble_conn_params模块会自动处理。手动发的话建议:首次连接建立后5-8秒发一次,后续每30秒检查一次。iOS对频繁的参数更新请求会直接拒绝。
Q4:用什么仪器测连接功耗?
Nordic官方的Power Profiler Kit II(PPK2)是标配,USB直连电脑,能测μA级别电流波形,价格约1000元。如果预算有限,万用表+串联电阻也能估算。