3. 链路层广播机制与抓包分析
链路层,简称 LL,是 BLE 协议栈里最核心的一层。说白了,它负责两件事:什么时候发数据,以及数据长什么样。我刚开始接触 BLE 时,总觉得 LL 就是个调度器,后来踩了几个坑才明白——不理解 LL,你连连接都建不起来。
3.1 链路层状态机——设备在干什么?
BLE 设备在任何时刻都处于五种状态之一。这五种状态构成了链路层的状态机,也是整个 BLE 通信的基础。
五种状态:待机(Standby)、广播(Advertising)、扫描(Scanning)、发起连接(Initiating)、连接(Connection)。
状态之间的跳转有严格规则。你不能从广播直接跳到扫描,也不能从连接直接跳到发起。我画了一张图,帮你理清这个关系。
嗯,这里要注意:待机状态是唯一一个可以从任何状态进入的状态。你想想看,设备上电后默认就在待机,然后根据应用需求决定下一步做什么。
3.2 设备角色——谁在说话,谁在听?
状态机定义了设备在干什么,但设备在通信中扮演什么角色,是由设备角色决定的。BLE 4.0/4.1 定义了四种角色,我习惯把它们分成两组:
| 角色 | 对应状态 | 典型设备 | 一句话描述 |
|---|---|---|---|
| 广播者 (Advertiser) | 广播 | 传感器、信标 | 我在这,快来连我 |
| 扫描者 (Scanner) | 扫描 | 手机、网关 | 谁在广播?我看看 |
| 主机 (Master) | 连接(发起方) | 手机、中心设备 | 我来控制连接节奏 |
| 从机 (Slave) | 连接(被发起方) | 手环、耳机 | 听主机安排 |
我的经验:一个设备可以同时是广播者和扫描者吗?可以。比如手机在扫描周围设备的同时,也可以广播自己的信息。但注意,同一时刻只能处于一个状态,角色是时分复用的。
我记得有一次做项目,客户要求一个设备既能被手机连接,又能扫描其他传感器。我一开始想当然地让设备同时做两件事,结果发现广播间隔和扫描窗口冲突了。后来我用了交替调度——广播 30ms,扫描 30ms,再广播 30ms……虽然吞吐量降了,但功能都跑通了。
3.3 链路层数据包结构——数据长什么样?
链路层的数据包,官方叫 PDU(Protocol Data Unit)。不管你是广播包还是数据包,底层都遵循同一套结构。我把它拆成三部分:
- 前导码 (Preamble):1 字节,用于接收端同步时钟。固定为 0xAA 或 0x55。
- 访问地址 (Access Address):4 字节。广播包固定为 0x8E89BED6,数据包是随机生成的。
- PDU:2~257 字节,包含实际数据。
- CRC:3 字节,校验数据完整性。
你想想看,为什么广播包的访问地址是固定的?因为扫描者不知道谁会广播,必须用一个大家都认识的地址来监听。而连接后的数据包,地址是随机生成的,这样别的设备就不会误收你的数据。
3.3.1 广播信道 PDU
广播包有两种类型:
| 类型 | PDU 长度 | 用途 |
|---|---|---|
| 广播指示 (ADV_IND) | 6~37 字节 | 可连接的非定向广播 |
| 扫描请求 (SCAN_REQ) | 12 字节 | 扫描者请求更多信息 |
| 扫描响应 (SCAN_RSP) | 6~37 字节 | 广播者回复扫描请求 |
| 连接请求 (CONNECT_REQ) | 34 字节 | 发起连接,包含连接参数 |
避坑指南:我曾经在广播包里塞了太多厂商自定义数据,结果超过 31 字节的载荷上限。扫描者收到后直接丢弃了整个包。后来我才知道,广播包 PDU 的载荷最大 31 字节,超过就得用扫描响应来补充。
3.3.2 数据信道 PDU
连接建立后,数据在数据信道上传送。数据 PDU 分为两种:
- LL 数据 PDU:承载上层(L2CAP)数据,最大 251 字节。
- LL 控制 PDU:用于链路层管理,比如更新连接参数、加密等。
数据 PDU 的头部只有 2 字节,但包含了很多信息:
LL 数据 PDU 头部(2 字节):
- LLID (2 bits):标识是数据还是控制包
- NESN (1 bit):下一个期望的序列号
- SN (1 bit):当前包的序列号
- MD (1 bit):是否还有更多数据要发
- RFU (3 bits):保留
- Length (8 bits):载荷长度
嗯,这里 SN 和 NESN 是 BLE 可靠传输的关键。每次发送一个包,SN 翻转一次;接收端用 NESN 告诉对方“我收到了,请发下一个”。如果丢包了,NESN 不变,发送端就会重传。
3.4 链路层的关键机制
除了状态机和数据包,链路层还有几个机制,我挑两个最重要的说说。
3.4.1 白名单 (White List)
白名单是一组设备地址。只有在白名单里的设备,才能收到你的广播,或者才能连接你。我习惯用白名单来做设备过滤,避免无关设备干扰。
我的习惯:在量产项目中,我会把白名单放在 OTP(一次性可编程)区域。这样设备出厂后,白名单就不能改了,安全性高很多。
3.4.2 连接参数更新
连接建立后,主机和从机可以协商更新连接参数,包括:
- 连接间隔 (Connection Interval):7.5ms ~ 4s
- 从机延迟 (Slave Latency):0~499 个事件
- 监督超时 (Supervision Timeout):100ms ~ 32s
我记得有一次做低功耗项目,把连接间隔设成了 400ms,从机延迟设成了 9。结果设备在大部分时间都在睡觉,功耗降到了 10μA 以下。但代价是响应延迟变大了——按个按钮,要等 4 秒才有反应。所以低功耗和低延迟是矛盾的,你得根据应用场景做取舍。
3.5 本章小结
链路层是 BLE 的基石。你理解了状态机,就知道设备在干什么;理解了角色,就知道谁控制谁;理解了数据包结构,就能读懂空中飞过的每一帧数据。我个人觉得,LL 是 BLE 协议栈里最值得花时间啃的部分——啃透了,后面的 L2CAP、ATT、GATT 都会轻松很多。