3. 连接建立流程:连接参数、连接过程与状态机
这一章我们聊聊 BLE 连接是怎么建立起来的。说白了,就是两个设备从「互相看见」到「正式握手」再到「稳定通信」的全过程。很多初学者觉得连接就是一发一收的事,其实里面藏着不少坑。我当年第一次调多设备连接时,就被连接间隔和超时参数坑过——设备连上了,但数据就是收不全。
好,我们一步步拆开看。
3.1 连接参数:间隔、延迟与超时
连接参数是主从设备之间协商好的通信节奏。三个核心参数:连接间隔、从机延迟、监督超时。它们共同决定了连接的功耗、实时性和稳定性。
| 参数 | 范围 | 单位 | 作用 |
|---|---|---|---|
| 连接间隔 | 7.5 ms ~ 4 s | 1.25 ms 步进 | 主设备两次发送数据包的时间间隔 |
| 从机延迟 | 0 ~ 499 | 连接间隔倍数 | 从设备可跳过的最大连接事件数 |
| 监督超时 | 100 ms ~ 32 s | 10 ms 步进 | 无数据交换时,连接保持的最大时间 |
关键公式:监督超时 > (1 + 从机延迟) × 连接间隔 × 2
这个公式必须满足,否则连接会不稳定。我见过有人把从机延迟设成 400,连接间隔 50 ms,监督超时只设了 1 秒——结果设备频繁断连。
连接间隔决定了带宽和功耗。间隔越小,数据吞吐越高,但功耗也大。我个人习惯:对实时性要求高的场景(比如音频),用 7.5 ms ~ 30 ms;对低功耗传感器,用 100 ms 以上。
从机延迟是从设备的「偷懒权」。它可以在连续 N 个连接事件里不回复主机,省电。但注意:延迟越大,数据延迟也越大。我曾经在一个数据采集项目里把从机延迟设成 10,结果主机发出去的指令,从机要等 1 秒才响应——调试时差点以为是硬件坏了。
监督超时是连接的「保命底线」。如果在这个时间内主从双方没有任何数据交换,连接就会自动断开。嗯,这里要注意:超时值不能设得太短,否则信号稍微波动就断连;也不能设得太长,否则设备「假连」了你都不知道。
我的经验:做多设备连接时,建议把监督超时设为连接间隔的 10~20 倍。比如连接间隔 30 ms,超时设 300~600 ms。这样既能容忍短暂丢包,又能在设备真正离线时快速释放资源。
3.2 连接建立过程:三步握手
BLE 连接建立不是瞬间完成的。它分三步:发起连接 → 连接请求 → 连接完成。每一步都有明确的协议行为。
3.2.1 发起连接(Initiating)
主机(Central)在扫描到从机(Peripheral)的广播包后,如果满足连接条件,就会进入发起状态。主机发送一个 CONNECT_IND 包,里面包含了连接参数。
这个包的结构长这样:
CONNECT_IND PDU:
- InitA: 主机设备地址
- AdvA: 从机设备地址
- LLData:
- Access Address: 32 位连接唯一标识
- CRCInit: CRC 初始值
- WinSize: 传输窗口大小
- WinOffset: 传输窗口偏移
- Interval: 连接间隔
- Latency: 从机延迟
- Timeout: 监督超时
- ChM: 信道映射
- Hop: 跳频增量
- SCA: 睡眠时钟精度
这里有个细节:Access Address 是连接的「身份证」。每个连接都有唯一的 Access Address,主设备用它来区分不同从设备的数据包。我做多设备连接时,就靠这个字段来路由数据。
3.2.2 连接请求(Connection Request)
从机收到 CONNECT_IND 后,会解析里面的参数。如果参数合法,从机就在指定的传输窗口内回复一个空包,表示「我收到了,准备就绪」。
这一步很容易出问题。我记得有一次调试,从机一直不回复,抓包一看——连接间隔设成了 6 ms,但从机芯片不支持这么快的间隔。所以,连接参数必须在主从双方的能力范围内。
避坑指南:我曾经遇到一个 case——主机发了 CONNECT_IND,从机也回复了,但连接就是建立不起来。最后发现是信道映射(ChM)里包含了从机不支持的信道。所以,连接前最好先交换双方的能力信息。
3.2.3 连接完成(Connection Established)
主从双方成功交换第一个数据包后,连接正式建立。此时,主机和从机都进入 Connected 状态,开始按照协商好的连接间隔进行周期性通信。
从协议栈角度看,连接完成后会触发一个 Connection Complete Event。这个事件里包含了连接句柄、连接参数、角色等信息。应用层拿到这个事件,就可以开始收发数据了。
3.3 连接状态机:从广播到连接的完整流转
BLE 设备在连接建立过程中,会经历多个状态。理解状态机,是调试连接问题的基本功。
状态流转其实不复杂。主机从待机进入扫描,发现目标后进入发起连接,最后到已连接。从机从待机进入广播,收到连接请求后直接到已连接。
但这里有个容易忽略的点:从机在广播状态下,可以同时被多个主机连接吗?答案是不行。一个从机一次只能建立一个连接。如果你想实现一从多主,需要特殊的拓扑设计,比如用多个广播集。
调试技巧:当连接建立失败时,先看状态机卡在哪一步。如果从机一直停留在广播状态,说明它没收到 CONNECT_IND,或者收到了但参数不合法。抓包工具(比如 Ellisys 或 Nordic nRF Sniffer)能帮你快速定位。
3.4 多设备连接的连接参数管理
做多设备连接时,连接参数的管理是个大课题。每个从机都有自己的连接间隔、延迟和超时。主机需要维护一张参数表。
我一般这样设计:
- 低功耗传感器:连接间隔 200 ms,从机延迟 10,监督超时 4 s
- 实时控制设备:连接间隔 15 ms,从机延迟 0,监督超时 300 ms
- 数据批量传输:连接间隔 30 ms,从机延迟 5,监督超时 1 s
主机在发起连接时,需要根据从机类型选择合适的参数。如果所有从机都用同一套参数,要么浪费功耗,要么实时性不够。
注意:连接参数不是一成不变的。连接建立后,双方可以通过 Connection Parameter Update Request 来动态调整参数。但要注意,参数更新需要从机同意,而且不能频繁触发——我曾经在一个项目里每秒更新一次参数,结果把从机协议栈搞崩了。
3.5 实战中的常见问题
最后,分享几个我在多设备连接实战中踩过的坑:
- 连接间隔冲突:多个从机的连接间隔如果都是 7.5 ms,主机的调度压力会很大。建议错开间隔,或者用更大的间隔。
- 监督超时误判:如果从机延迟很大,主机可能误以为从机离线了。记得把监督超时设得足够大。
- 连接建立超时:从机收到 CONNECT_IND 后,必须在 6 个连接事件内回复。如果从机忙不过来,连接就会失败。
- 参数协商失败:有些从机不支持主机下发的参数,会拒绝连接。建议在连接前先读取从机的能力信息。
嗯,连接建立这块内容就这些。参数、流程、状态机,三者缺一不可。你只要把这三个东西理清楚,多设备连接的基本功就算打牢了。