BLE 连接建立与连接参数详解

发布时间:2026/9/30 9:38:35
BLE 连接建立与连接参数详解 BLE 连接建立与连接参数详解从 CONNECT_IND 到断开一、连接建立CONNECT_IND 与第一次握手窗口1.1 CONNECT_IND 逐字段解析1.2 Access Address 与 CRC Init连接前后的分界线1.3 时间单位1.25 ms 与 10 ms1.4 第一次握手窗口Window Size / Offset二、连接事件循环2.1 一问一答T_IFS 150 μs2.2 Empty PDU给从机说话的机会2.3 MD 位连接事件可以提前结束2.4 Slave Latency从机可以睡过几个事件三、连接后的六次协商3.1 Feature Exchange互相通报能力3.2 Version Exchange实际版本取双方较小值3.3 DLE 协商一个数据包能装多少字节3.4 连接参数更新30 ms → 7.5 ms3.4.1 为什么切换需要 Window Size/Offset Instant3.4.2 为什么手机要加快3.4.3 Offset 和 Preferred Periodicity 是干嘛的3.5 PHY 更新切到 2M 或 Coded3.6 Channel Map 更新自适应跳频AFH四、断开连接LL_TERMINATE_IND全文脉络广播阶段 连接建立 连接后的协商LL 控制过程 ────────── ───────── ───────────────────────── ADV_IND ──► CONNECT_IND ──► ① Feature Exchange特性交换 广播者 发起者/手机 ② Version Exchange版本交换 ③ DLE 协商数据长度扩展 SCAN_RSP ◄── ④ Connection Parameter Update 可选 ▼ ⑤ PHY Update切 2M / Coded 连接事件循环 ⑥ Channel Map UpdateAFH 自适应跳频 每 connInterval 一次 ⑦ Terminate断开连接 │ ▼ GATT 层服务发现 / 订阅 / 通知一句话概括CONNECT_IND把连接参数一次性定下来之后双方按connInterval周期碰头碰头过程中再通过 LL 控制包不断谈判优化参数。一、连接建立CONNECT_IND 与第一次握手窗口CONNECT_IND是手机Initiator / Central向板子Advertiser / Peripheral发出的连接请求。它的 Payload 由三段组成InitA(6) AdvA(6) LLData(22)——参数全在那 22 字节的 LLData 里。1.1 CONNECT_IND 逐字段解析字段抓到的值含义Initiator Address4e:b2:86:dd:a2:3d手机的 MAC随机地址Advertising Address7c:e8:b1:aa:da:36板子 的 MACAccess Address0x742e6ed6★ 连接后的新同步字后续数据包全用它CRC Init0xb248a4连接后 CRC 的初始值Window Size22.5 ms第一个传输窗口的大小Window Offset1620 ms从 CONNECT_IND 结束到第一个窗口的偏移Interval2430 ms连接间隔双方每 30 ms 通信一次Latency0从机可以跳过的连接事件数Timeout5005000 ms连接超时5 秒没收到就断开Channel Map1fff000000★ 可用数据信道图Hop5跳频步长规范要求是5~16的随机值SCA31~50 ppm中央设备手机的睡眠时钟精度LLData 的完整字段布局AA CRCInit WinSize WinOffset Interval Latency Timeout ChM Hop SCA (4 octets) (3 octets) (1 oct) (2 oct) (2 oct) (2 oct) (2 oct) (5 oct) (5 bits) (3 bits)1.2 Access Address 与 CRC Init连接前后的分界线广播阶段信道 37/38/39连接阶段信道 0~36Access Address固定0x8E89BED6随机 32-bit由 CONNECT_IND 指定CRC 初值固定0x555555随机值由 CONNECT_IND 的 CRCInit 指定两者每次连接都不同—— 所以它们天然可以当作 “这是哪一次连接” 的指纹。1.3 时间单位1.25 ms 与 10 msBLE 物理层时隙是625 μs连接参数以两个时隙为基本单位1.25 ms 2 × 625 μs参数单位抓到的原始值实际时间transmitWindowSize1.25 ms22 × 1.25 2.5 ms✅transmitWindowOffset1.25 ms1616 × 1.25 20 ms✅connInterval1.25 ms2424 × 1.25 30 ms✅connSupervisionTimeout10 ms500500 × 10 5000 ms 5 s✅connSlaveLatency无单位次数00 次⚠️唯一例外Timeout 的步长是10 ms不是 1.25 ms。这是最容易记混的一个。1.4 第一次握手窗口Window Size / Offset连接建立的瞬间有个根本问题广播者和发起者的时钟不同步。手机发完 CONNECT_IND 后从机并不知道手机会在精确的哪一刻发来第一个数据包。所以 BLE 设计了一个容差窗口手机说“我会在 CONNECT_IND 结束后约20 ms开始在接下来的2.5 ms窗口内找个时间发第一个包。你从机在那 2.5 ms 里把接收机打开等着。”要点说明只用一次Window Size/Offset只用于第一个连接事件。之后双方已同步按精确 Interval 走从机怎么做收到 CONNECT_IND → 等约 20 ms → 开接收机持续 2.5 ms → 收到就同步成功窗口内没收到从机在下一个 Interval30 ms 后再开一次窗口继续等二、连接事件循环连接建立后主从周期性碰头。每一次碰头的机会就叫一个Connection Event|-- connInterval 30ms --|-- connInterval 30ms --| ▲ ▲ 连接事件 #1 连接事件 #2在每个事件里主机先发一个包 → 从机回一个包 → 如果还有数据就继续收发 → 双方都没数据了就关闭射频睡觉等下一个 Interval。2.1 一问一答T_IFS 150 μs|──────── 一个 Connection Event ────────| 主机 ────[包]────► 从机 ← 主机发起必须有 T_IFS150μs 主机 ◄───[包]───── 从机 ← 从机回应必须有规范原文“The Inter Frame Space is designatedT_IFSand shall be150 µs.”从机收到后必须在 150 μs 内回应否则超时重传。2.2 Empty PDU给从机说话的机会核心规则BLE 连接建立后从机永远不能主动发起通信必须等主机先发包然后在 150 μs 内回应。所以就有了 Empty PDU主机 ────[Empty PDU]────► 从机 ← 主机我没啥要发的你呢 主机 ◄───[心率 Notification]── 从机 ← 从机正好我有数据没有这个机制从机有数据也只能干等着BLE 不允许从机主动打断主机。 这也解释了为什么connInterval 直接决定了数据上报延迟。2.3 MD 位连接事件可以提前结束数据信道 PDU 的 Header 里有个MDMore Data位MD 1表示 “我还有数据继续传”MD 0表示 “我没数据了”。主机 ──[数据包 MD1]──► 从机 主机 ◄─[数据包 MD1]─── 从机 ← 还有数据继续 主机 ──[数据包 MD0]──► 从机 主机 ◄─[数据包 MD0]─── 从机 ← 都没数据了 → 事件关闭 ┌──────────────────┐ │ 射频关闭睡觉 │ │ 等下一个 30ms │ └──────────────────┘所以连接事件不一定占满整个 Interval—— 传完就睡这是 BLE 省电的关键之一。2.4 Slave Latency从机可以睡过几个事件问题如果每 30 ms 都要唤醒射频收发一次哪怕只是空包功耗很可观。解决允许从机跳过一些连接事件。Latency 0每次都醒主机: ● ● ● ● ● ● ● ● 从机: ● ● ● ● ● ● ● ● ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 每次都醒每次都收发哪怕只是空包 有效通信周期 30 ms 功耗最高 延迟最低Latency 4可跳 4 次每 5 个事件响应 1 次主机: ● ● ● ● ● ● ● ● ● ● ● ← 主机每个事件都发 从机: ● ● ● ← 从机只醒第 1、6、11... |----- 150 ms -----| (5 × 30 ms 从机实际醒来的间隔) 从机少醒了 4/5 80% 功耗大幅降低 延迟最高 150 ms关键理解Slave Latency 不是主机不发而是从机可以不听。主机每个连接事件照常发否则连接就断了从机可以睡过 N 个事件只在第 N1 个醒来收。约束公式connSupervisionTimeout (1 connSlaveLatency) × connInterval × 2Latency 设得太大导致左边接近甚至超过 Timeout连接就会被误判为超时断开。从机什么时候不能睡有数据要上报时比如心率有新值必须立刻醒来发主机发了需要响应的包也必须回。所以Latency 是没事的时候可以睡不是强制睡。工程上怎么选核心权衡永远是「延迟 ↔ 功耗」场景推荐参数心率手环省电优先延迟不敏感Interval 大100 ms ~ 1 s Latency 高4~20游戏手柄 / 遥控器低延迟Interval 小7.5~15 ms Latency 0固件升级 OTA要吞吐Interval 小7.5 ms Latency 0 开 DLE传感器定时上报Interval 中等 Latency 适中三、连接后的六次协商连接建立后双方会按需进行一系列 LL 控制过程。它们有一个共同的套路① REQ ── 发起方探测/提议 ② RSP ── 回应方答复 ③ IND ── 中央设备拍板并指定 Instant从第几个连接事件起生效只有必须双方同时切换的过程才需要第 ③ 步比如 PHY 和连接参数。3.1 Feature Exchange互相通报能力连接建立后第一个协商过程FeatureSet 0xf9ff逐位解读Bit特性值说明0LE Encryption✅支持加密配对 / bonding 的基础1Connection Parameters Request✅支持连接参数更新流程2Extended Reject Indication✅拒绝时能带原因码3Peripheral Initiated Features Exchange✅从机可以主动发起特性交换4LE Ping✅链路层保活探测5LE Data Packet Length Extension (DLE)✅数据长度扩展6LL Privacy✅链路层隐私随机地址7Extended Scanner Filter Policies✅扩展扫描过滤策略8LE 2M PHY✅2M 速率需切换才生效9Stable Modulation Index - Tx❌发射机稳定调制指数10Stable Modulation Index - Rx❌接收机稳定调制指数11LE Coded PHY✅长距离模式BLE 5.012LE Extended Advertising✅扩展广播13LE Periodic Advertising✅周期性广播14Channel Selection Algorithm #2✅CSA #215LE Power Class 1✅支持 Class 1 发射功率注意 bit 3 1所以从机才会主动回一个LL_PERIPHERAL_FEATURE_REQ。另外LL_FEATURE_RSP的 FeatureSet 字段 发送这个 RSP 的那一方自己支持的特性。3.2 Version Exchange实际版本取双方较小值手机: BLE 6.0 板子: BLE 5.0 ──────────────── 有效版本: BLE 5.03.3 DLE 协商一个数据包能装多少字节DLE Data Length Extension数据长度扩展。无 DLEBLE 4.0/4.1有 DLEBLE 4.2数据信道 PDU 最大 Payload27 字节251 字节单包有效数据ATT 层20 字节244 字节传 1 KB 数据需要~51 个包~5 个包协商用的四个字段字段含义Max RX octets我作为接收方最多能收的 payload 字节数Max RX time我作为接收方最多能收的射频时长Max TX octets我作为发送方最多能发的 payload 字节数Max TX time我作为发送方最多能发的射频时长① 手机 → 板子② 板子 → 手机③ 手机 → 板子④ 板子 → 手机★ 关键公式每个方向的有效长度某方向的有效长度 min( 对端的 MaxRX , 本端的 MaxTX )套用到本次抓包手机 → 板子 min(板子 MaxRX251, 手机 MaxTX27) 27 字节 板子 → 手机 min(手机 MaxRX251, 板子 MaxTX251) 251 字节结论这次连接是「非对称」的—— 板子给手机发心率通知可以一次发 251 字节手机给板子发写特征值一次只能 27 字节。3.4 连接参数更新30 ms → 7.5 ms这是抓包里连接参数更新的完整流程手机主动要求把连接加快手机 ── LL_CONNECTION_PARAM_REQ ──► 板子 我想把连接间隔改成 7.5ms 手机 ◄── LL_CONNECTION_PARAM_RSP ── 板子 同意 手机 ── LL_CONNECTION_UPDATE_IND ──► 板子 从现在起第 17 个连接事件开始生效① LL_CONNECTION_PARAM_REQ手机发起字段值含义Interval Min / Max6 / 66 × 1.25 ms 7.5 msLatency0不跳过任何连接事件Timeout500500 × 10 ms 5000 msPreferred Periodicity0手机对事件偏移无偏好Reference Connection Event Count6计算偏移的参考锚点Offset 0~55, 0, 1, 3, 4, 65535建议的连接事件偏移65535 无效② LL_CONNECTION_PARAM_RSP板子回应大部分和 REQ 相同只有Preferred Periodicity变成1板子表示我接受你的参数并且偏好周期性为 1。板子接受了手机提议的 7.5 ms 间隔所以 RSP 几乎照抄 REQ。如果板子不接受RSP 里会填不同的 Interval Min/Max—— 这时手机可以选择接受板子的提议或者发起断开。③ LL_CONNECTION_UPDATE_IND手机下发更新指令字段值含义Window Size1更新后的第一个事件窗口 1.25 msWindow Offset5更新后的第一个事件偏移 6.25 msInterval6新连接间隔 7.5 msLatency0不变Timeout5005000 ms不变Instant17第 17 个连接事件时切换新参数3.4.1 为什么切换需要 Window Size/Offset Instant参数从 30 ms 切到 7.5 ms时序会发生跳变。切换的那一瞬间双方需要一个 “重新对齐的窗口”Instant 17双方都从 CONNECT_IND 之后开始数连接事件数到第 17 个时同时切换。这样不需要额外通信就能保证同步。Window Size 11.25 ms板子在这个窗口内打开接收机等待新参数的第一个包。3.4.2 为什么手机要加快最可能的原因是nRF Connect App 进入了活跃状态。阶段典型 Interval场景刚连接30~50 ms低功耗后台维持用户打开 App 交互7.5~15 ms低延迟服务发现、读写稳定传输数据7.5~30 ms根据应用调整长时间空闲100~1000 ms超低功耗反过来很多产品连接成功后从机会主动发起参数更新把 Interval 拉大100 ms ~ 1 s、Latency 设成 4~10进入省电模式。3.4.3 Offset 和 Preferred Periodicity 是干嘛的这是给手机同时连接多个 BLE 设备时用的 —— 它希望这些设备的连接事件错开不要撞在一起设备 A 的连接事件t0, 7.5ms, 15ms, ... 设备 B 的连接事件t2.5ms, 10ms, 17.5ms, ... ← 错开Preferred Periodicity 0发起方手机没偏好Preferred Periodicity 1从机希望按某个周期错开Offset 0 ~ 5具体偏置值列表65535 表示 “这个选项无效”本例的 Offset 列表是[5, 0, 1, 3, 4, 65535]说明有5 个有效偏置建议单位 1.25 ms。从LL_CONNECTION_UPDATE_IND的 Window Offset 5 可以看出主机最终接受了 Offset0 56.25 ms。3.5 PHY 更新切到 2M 或 Coded连接建立后想把 1M 换成 2M或 Coded① LL_PHY_REQ手机 → 板子字段值含义TX PHYs0x07手机发送时支持 1M / 2M / CodedRX PHYs0x02手机希望接收时只用 2M② LL_PHY_RSP板子 → 手机字段值含义TX PHYs0x07板子发送时支持 1M / 2M / CodedRX PHYs0x07板子接收时支持 1M / 2M / Coded③ LL_PHY_UPDATE_IND手机 → 板子最终决定字段值含义Central → Peripheral PHY0x02手机发给板子用2MPeripheral → Central PHY0x02板子发给手机用2MInstant60在第 60 个连接事件时切换 PHY3.6 Channel Map 更新自适应跳频AFH手机Central告诉板子Peripheral“新的可用数据信道图是0xffcff1f从第 125 个连接事件开始生效。”字段值含义Control Opcode0x01LL_CHANNEL_MAP_INDChannel Map0xffcff1f数据信道 0~36 的可用性位图Instant125新信道图在第 125 个连接事件生效Channel Map 的正确解码方法① bit N ←→ 数据信道 N N 0 ~ 36 ② 1 可用Used0 不可用Unused ③ 字节按【小端】拼成一个整数octet0 对应信道 0~7以0x0ffcffff1f即0x0FFCFFFF1F10 位十六进制 5 字节为例逐字节拆开字节小端序值二进制对应信道状态octet0最右字节0x1F0001 11110~70~4 ✅ 可用5~7 ❌octet10xFF1111 11118~15全部 ✅octet20xFF1111 111116~23全部 ✅octet30xFC1111 110024~3126~31 ✅ 可用24~25 ❌octet4最左字节0x0F0000 111132~3632~35 ✅ 可用36 ❌四、断开连接LL_TERMINATE_IND字段值含义LLID0x3Control PDU链路层控制报文Control Opcode0x02LL_TERMINATE_INDError Code0x13Remote User Terminated ConnectionLength2只有 Opcode Error Code 两个字节Error Code 0x13Remote User Terminated Connection—— 有一方手机或板子的用户/应用层主动点了断开然后通过这个链路层 PDU 通知对方。注意这里的 “Error” 不是故障BLE 里断开原因统一用这个字段表示。