3. BLE连接建立与参数协商

BLE连接建立是主机(Central)与从机(Peripheral)之间建立双向数据通道的过程。连接建立后,双方通过连接事件(Connection Events)进行周期性通信,通信的节奏由连接间隔、连接延迟和监控超时三个参数共同决定。此外,MTU交换用于提升单次数据传输的有效载荷,而连接回调则是应用层感知连接状态变化的入口。

BLE连接建立与参数协商流程 1. 主机发起连接请求 (CONNECT_REQ) 2. 从机接受连接,进入连接状态 3. 连接参数协商 连接间隔 (Connection Interval) | 连接延迟 (Slave Latency) 监控超时 (Supervision Timeout) 4. MTU交换 (MTU Exchange) 默认 23 字节 → 协商至最大 512 字节 (BLE 4.2+) 5. 连接建立成功 6. 连接回调触发 (on_connected) 参数范围 连接间隔: 7.5 ms ~ 4 s 步长: 1.25 ms 连接延迟: 0 ~ 499 监控超时: 100 ms ~ 32 s MTU: 23 ~ 512 字节

3.1 连接参数详解

连接参数在BLE链路层(Link Layer)建立连接时确定,直接影响通信的实时性、功耗和稳定性。应用层可以在连接建立后发起参数更新请求,但最终由链路层根据双方能力协商决定。

参数含义范围步长典型值
连接间隔 (Connection Interval)两个相邻连接事件之间的时间间隔7.5 ms ~ 4 s1.25 ms30~50 ms (低延迟) / 100~400 ms (低功耗)
连接延迟 (Slave Latency)从机可以跳过而不丢失连接的最大连接事件数0 ~ 49910~9 (低延迟) / 10~100 (低功耗)
监控超时 (Supervision Timeout)从机未收到任何数据包后判定连接丢失的超时时间100 ms ~ 32 s10 ms2~6 s (通常取 4 s)
MTU (Maximum Transmission Unit)单个ATT数据包的最大有效载荷23 ~ 512 字节1 字节247 (BLE 4.0/4.1) / 512 (BLE 4.2+)
设计建议: 连接间隔越小,数据实时性越高,但双方功耗也越高;连接延迟越大,从机在空闲时休眠的时间越长,越省电,但会牺牲响应速度。监控超时建议设置为连接间隔的 3~5 倍以上,避免因短暂干扰导致误断开。

3.1.1 连接间隔

连接间隔以 1.25 ms 为单位递增。主机在 CONNECT_REQ 中发送初始间隔,从机可以在连接建立后通过 LL_CONNECTION_PARAM_REQ 发起参数更新。BLE 协议规定连接间隔的最小值为 6(对应 7.5 ms),最大值为 3200(对应 4 s)。实际产品中,交互式应用(如遥控器、游戏手柄)常用 30~50 ms,数据采集类(如传感器)常用 100~400 ms。

3.1.2 连接延迟

连接延迟允许从机在指定数量的连接事件中不发送数据包,以节省功耗。延迟值 N 表示从机最多可以连续跳过 N 个连接事件。但协议规定:从机不得连续跳过超过 supervision_timeout / (interval * 2) 个事件,以确保链路不被判定超时。连接延迟为 0 表示每个连接事件从机都必须响应。

3.1.3 监控超时

监控超时是链路层判断连接丢失的最长时间。如果从机在该时间内未收到任何有效数据包(包括空包),链路层将强制断开连接,并通过回调通知应用层。超时值必须大于 connection_interval * (1 + slave_latency) * 2,否则参数更新将被拒绝。

3.2 MTU 交换

MTU(最大传输单元)决定了单个 ATT 数据包可以携带的用户数据大小。默认 MTU 为 23 字节(其中 3 字节为 ATT 头,实际有效载荷仅 20 字节)。通过 MTU 交换,双方可以协商一个更大的值,减少大数据传输时的分片开销。

  • MTU 交换流程: 客户端发送 MTU Exchange Request 携带本端最大接收 MTU,服务端回复 MTU Exchange Response 携带本端最大接收 MTU,最终取两者中的较小值作为连接 MTU。
  • BLE 版本差异: BLE 4.0/4.1 最大支持 247 字节,BLE 4.2+ 最大支持 512 字节(基于 LE Data Length Extension)。
  • 影响: MTU 从 23 提升到 247 时,单次传输效率提升约 10 倍,适合固件升级、批量数据同步等场景。
注意: MTU 交换必须在连接建立后、GATT 通信开始前完成。部分 BLE 协议栈(如 BlueZ、Zephyr)会自动发起 MTU 交换,而部分平台(如某些低功耗 SoC)需要应用层显式调用 API 触发。如果未做 MTU 交换,实际 MTU 将保持在 23 字节,导致大包传输时性能下降。

3.3 连接回调代码实现

连接回调是应用层监听连接状态、获取连接参数、处理 MTU 更新的核心接口。下面展示一个典型的连接回调实现,包括连接建立、参数获取、MTU 更新和断开通知。

/* ble_conn_cb.h - 连接回调接口定义 */

typedef struct {
    void (*on_connected)(void *conn_handle, uint8_t role,
                         uint16_t interval, uint16_t latency,
                         uint16_t timeout);
    void (*on_disconnected)(void *conn_handle, uint8_t reason);
    void (*on_mtu_updated)(void *conn_handle, uint16_t mtu);
    void (*on_param_updated)(void *conn_handle,
                             uint16_t interval, uint16_t latency,
                             uint16_t timeout);
} ble_conn_cb_t;

/* 注册回调 */
void ble_conn_cb_register(ble_conn_cb_t *cb);
/* ble_conn_cb_example.c - 连接回调实现示例 */

#include "ble_conn_cb.h"

/* 连接建立回调 */
static void on_connected(void *conn_handle, uint8_t role,
                         uint16_t interval, uint16_t latency,
                         uint16_t timeout) {
    printf("[BLE] 连接建立, 角色: %s\n",
           role == 0 ? "主机" : "从机");
    printf("      连接间隔: %.2f ms\n", interval * 1.25);
    printf("      连接延迟: %u 个事件\n", latency);
    printf("      监控超时: %.2f s\n", timeout * 0.01);

    /* 发起 MTU 交换 (通常在连接后立即发起) */
    ble_mtu_exchange(conn_handle, 512);
}

/* 断开连接回调 */
static void on_disconnected(void *conn_handle, uint8_t reason) {
    printf("[BLE] 连接断开, 原因: 0x%02X\n", reason);
    /* 此处可添加重连逻辑 */
}

/* MTU 更新回调 */
static void on_mtu_updated(void *conn_handle, uint16_t mtu) {
    printf("[BLE] MTU 已更新: %u 字节\n", mtu);
    /* MTU 更新后可以安全地发送小于等于 mtu-3 字节的数据包 */
}

/* 连接参数更新回调 (从机成功更新参数后触发) */
static void on_param_updated(void *conn_handle,
                             uint16_t interval, uint16_t latency,
                             uint16_t timeout) {
    printf("[BLE] 连接参数已更新\n");
    printf("      新连接间隔: %.2f ms\n", interval * 1.25);
    printf("      新连接延迟: %u\n", latency);
    printf("      新监控超时: %.2f s\n", timeout * 0.01);
}

/* 注册回调结构体 */
static ble_conn_cb_t g_conn_cb = {
    .on_connected    = on_connected,
    .on_disconnected = on_disconnected,
    .on_mtu_updated  = on_mtu_updated,
    .on_param_updated = on_param_updated,
};

/* 应用初始化时调用 */
void app_ble_init(void) {
    ble_conn_cb_register(&g_conn_cb);
    printf("BLE 连接回调已注册\n");
}
关键点解析:
  • on_connected 中立即获取连接参数并打印,方便调试时确认实际协商结果。
  • MTU 交换应在连接后尽快发起,通常在 on_connected 回调中调用 ble_mtu_exchange。
  • on_param_updated 仅在从机侧参数更新成功时触发,主机侧一般不会收到该回调(主机是参数更新的发起方)。
  • 断开回调的 reason 参数可以区分“正常断开”、“超时断开”、“对方主动断开”等场景,用于日志记录和重连策略。

3.4 参数更新请求与协商

从机可以在连接建立后通过 ble_conn_param_update_req 发起参数更新。主机收到请求后,根据自身能力决定接受或拒绝。参数更新请求需要满足协议约束:

  • 间隔约束: min_interval ≤ max_interval,且两者均必须落在 7.5 ms ~ 4 s 范围内。
  • 延迟约束: latency ≤ (supervision_timeout / (max_interval × 2)) - 1。
  • 超时约束: supervision_timeout > max_interval × (1 + latency) × 2。
/* 从机发起连接参数更新请求示例 */

ble_conn_param_t new_params = {
    .min_interval = 40,   /* 40 × 1.25 ms = 50 ms */
    .max_interval = 48,   /* 48 × 1.25 ms = 60 ms */
    .latency      = 4,    /* 最多跳过 4 个连接事件 */
    .timeout      = 400,  /* 400 × 10 ms = 4 s */
};

int err = ble_conn_param_update_req(conn_handle, &new_params);
if (err == 0) {
    printf("参数更新请求已发送\n");
} else {
    printf("参数更新请求失败, err: %d\n", err);
}

3.5 常见错误与调试

错误场景典型原因排查方向
连接建立失败设备不在广播状态、MAC 地址错误、蓝牙未初始化检查广播日志;确认扫描过滤条件;确认协议栈状态
参数更新被拒绝间隔/延迟/超时不满足协议约束、主机不支持该参数打印主机返回的错误码;检查参数范围是否越界;降低延迟值重试
MTU 交换超时或失败对方不支持 MTU 交换、链路质量差导致丢包确认对端 BLE 版本;重试交换;增大监控超时
连接频繁断开监控超时过短、信号干扰、连接间隔过大导致从机饥饿增大监控超时;减小连接间隔;增加射频重传次数
数据传输速率低于预期MTU 未协商、连接间隔过大、未启用 LE Data Length Extension确认 MTU 交换成功;调小连接间隔;检查是否支持 2-Mbit PHY
调试技巧:
  • 使用 BLE 嗅探器(如 nRF Sniffer、Ellisys)捕获空中包,直接查看 CONNECT_REQ 中的连接参数和 MTU 交换过程。
  • 在 on_connected 和 on_param_updated 回调中打印完整参数,与预期值对比。
  • 如果参数更新被拒绝,可以先尝试用更保守的参数(如更大间隔、更小延迟)发起更新,确认链路正常后再逐步收紧。

3.6 性能与稳定性优化

连接参数的选择本质是实时性、功耗和链路稳定性的三方权衡。以下优化策略可供参考:

  • 低延迟场景(遥控器、游戏手柄): 连接间隔 30~50 ms,延迟 0,超时 2~4 s。确保每 30~50 ms 有一次双向通信,触控响应在 100 ms 以内。
  • 低功耗场景(传感器、信标): 连接间隔 200~400 ms,延迟 10~50,超时 4~6 s。从机在大部分连接事件中休眠,大幅降低平均电流。
  • 大数据传输场景(OTA 升级、日志导出): 先发起 MTU 交换到 512 字节,再尝试缩小连接间隔至 15~30 ms,同时启用 2-Mbit PHY 和 LE Data Length Extension 以提升吞吐量。
  • 链路稳定性: 监控超时建议设置为连接间隔 × (1 + 延迟) × 4 以上,为射频重传保留足够余量。若部署在强干扰环境(如 Wi-Fi 密集区),可适当增大连接间隔以避免碰撞。
注意: 在参数更新协商过程中,如果主机和从机的参数偏好冲突,最终结果由主机链路层决定。从机应做好参数更新失败的容错处理,维持使用初始参数继续通信,而非强制断开连接。