拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

BLE 广播包结构详解

BLE 广播包结构详解

BLE 广播包结构详解:从一个真实抓包说起

  • 一、先建立整体图景
    • 1.1 一个广播包的完整封装
    • 1.2 Preamble 长度随 PHY 变
  • 二、PDU Header:16 个 bit 决定一切
  • 三、Payload 里装什么:AD Structure
    • 3.1 一次完整的"扫码-应答"
    • 3.2 实例 ① :Flags
    • 3.3 实例 ② :16-bit 服务 UUID 列表
    • 3.4 实例 ③ :完整设备名
    • 3.5 为什么设备名必须放到 SCAN_RSP?
  • 四、从广播到连接:跳频与 Channel Selection
    • 4.1 主从怎么同步跳?
    • 4.2 Channel Map 由谁维护?
  • 五、速查手册
    • 5.1 PDU Type 全表
    • 5.2 常用 AD Type
    • 5.3 三种 PHY

本文以 Zephyr 的peripheral_hr为例,把「源码里写的ad[]」和「Wireshark 里抓到的字节」逐层对应起来。
读完之后,拿到任意一段 BLE 广播包的十六进制,都能自己拆开看。

一、先建立整体图景

BLE 广播涉及三个层次:

层次负责什么
Link Layer(链路层)包的物理外壳:怎么在 2.4 GHz 上传一帧
GAPPayload 里「广播数据」的格式约定,即 AD Structure
应用层广播什么内容

1.1 一个广播包的完整封装

+-----------+------------------+--------------+-----------+ | Preamble | Access Address | PDU | CRC | | 1 byte | 4 bytes | 2~39 bytes | 3 bytes | +-----------+------------------+--------------+-----------+ │ ▼ +------------------+-----------------------+ | Header | Payload | | 2 bytes | 0~37 bytes | +------------------+-----------------------+

Access Address 在广播信道上固定为0x8E89BED6(低字节先发,所以空口上是D6 BE 89 8E)。它有两个作用:

  1. 帧同步—— 接收机在噪声中滑动匹配这个 32-bit 序列,一旦匹配上就知道「后面跟着一个有效包」。
  2. 区分包类型—— 广播信道(37/38/39)上的包固定用它;数据信道(0~36)上的连接包用随机32-bit 值,每次连接都不同。

1.2 Preamble 长度随 PHY 变

PHYPreamble内容
LE 1M8 bits(1 字节)如01010101
LE 2M16 bits(2 字节)如0101010101010101
LE Coded80 个符号10 组00111100,时长 80 µs

以上尺寸是传统广播(Legacy Advertising,LE 1M)的情况。扩展广播的 PDU 尺寸不同:Length 字段扩到 8 bits,单包 Payload 最多 255 字节,靠 chaining 可拼到 1650 字节。

二、PDU Header:16 个 bit 决定一切

PDU Header 是 16 bits。BLE 4.x 和 BLE 5.x 看它的角度略有不同 —— 差别只在 bit 5。

BLE 4.x bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ├─ RFU ─├────── Length ──────┤ RxAdd │ TxAdd │ RFU │ PDU Type │ BLE 5.x(bit 5 从 RFU 变成 ChSel) bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ├─ RFU ─├────── Length ──────┤ RxAdd │ TxAdd │ ChSel │ RFU │ PDU Type │
字段bit 位置长度含义
PDU Type0~34 bits包类型(ADV_IND / SCAN_RSP / CONNECT_IND …)
RFU41 bit保留未用
ChSel51 bitBLE 5.0 起:连接后使用 CSA #1(=0)还是 CSA #2(=1)
TxAdd61 bit发送方地址类型:0 = Public,1 = Random
RxAdd71 bit接收方地址类型:0 = Public,1 = Random
Length8~136 bitsPayload 长度。字段本身可表示 0~63,传统广播实际最大 37
RFU14~152 bits保留未用

关于 ChSel:只有双方都支持CSA #2 时才会用 #2,否则降级到 #1。这是规范保证的兼容性 —— 广播者在ADV_IND里宣告自己是否支持,发起者在CONNECT_IND里宣告,两边都置 1 才启用。

三、Payload 里装什么:AD Structure

peripheral_hr广播时一共发了两个包,Payload 里装了三个 AD 结构:

包源码数组装了什么字节数
ADV_INDad[]Flags + 3 个 16-bit UUID11
SCAN_RSPsd[]完整设备名25

每个 AD 结构的通用格式是:

┌──────────┬───────────┬──────────────────────┐ │ Length │ AD Type │ AD Data │ │ 1 byte │ 1 byte │ (Length - 1) bytes │ └──────────┴───────────┴──────────────────────┘

Length只统计它后面的字节数(即 Type + Data),不含 Length 字段自己。一个AdvData里可以串联多个 AD Structure。

3.1 一次完整的"扫码-应答"

三个 AD 结构分别装在两个包里。它们是这样被手机拿到的:

手机 板子 │ │ │ ◄──────── ADV_IND ───────────────────────┤ 广播包:Flags + UUID 列表 │ │ ├───────── SCAN_REQ ──────────────────────►│ 手机:"我想知道你是谁" │ │ │ ◄──────── SCAN_RSP ──────────────────────┤ 扫描响应:完整设备名 │ │



下面把这三个 AD 结构逐个拆开——每个都从源码一路看到空口字节。

3.2 实例 ① :Flags

源码:

BT_DATA_BYTES(BT_DATA_FLAGS,(BT_LE_AD_GENERAL|BT_LE_AD_NO_BREDR))

空口字节:

02 01 06 │ └┬┘ │ └─── AD Type = 0x01(Flags),AD Data = 0x06 └─────── Length = 0x02

解码:BT_LE_AD_GENERAL = 0x02(bit 1)、BT_LE_AD_NO_BREDR = 0x04(bit 2),两者相或得0x06

Bit含义值
0LE Limited Discoverable Mode0
1LE General Discoverable Mode1✅
2BR/EDR Not Supported1✅
3~4Simultaneous LE + BR/EDR0
5~7Reserved0

3.3 实例 ② :16-bit 服务 UUID 列表

源码:

BT_DATA_BYTES(BT_DATA_UUID16_ALL,BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),// 0x180DBT_UUID_16_ENCODE(BT_UUID_BAS_VAL),// 0x180FBT_UUID_16_ENCODE(BT_UUID_DIS_VAL))// 0x180A

空口字节:

07 03 0d 18 0f 18 0a 18 │ │ └───────┬───────┘ │ │ └─── AD Data(6 字节 = 3 个 UUID) │ └───────────── AD Type = 0x03(Complete List of 16-bit Service Class UUIDs) └──────────────── Length = 0x07
空口字节UUID服务
0d 180x180DHeart Rate Service(HRS)
0f 180x180FBattery Service(BAS)
0a 180x180ADevice Information Service(DIS)

UUID 在空口上是小端的,所以0d 18还原成0x180D。

3.4 实例 ③ :完整设备名

源码:

BT_DATA(BT_DATA_NAME_COMPLETE,CONFIG_BT_DEVICE_NAME,sizeof(CONFIG_BT_DEVICE_NAME)-1)

空口字节:

18 09 5a 65 70 68 79 72 20 48 65 61 72 74 72 61 74 65 20 53 65 6e 73 6f 72 │ │ └────────────────────────────────────────────────────────────────────┘ │ │ AD Data(23 字节,ASCII) │ └───── AD Type = 0x09(Complete Local Name) └──────── Length = 0x18 = 24(Type + Data 共 24 字节)

解码:AD Data 是 23 字节 ASCII,即Zephyr Heartrate Sensor。
源码里的sizeof(CONFIG_BT_DEVICE_NAME) - 1正是去掉字符串末尾的\0,得到 23 字节。

3.5 为什么设备名必须放到 SCAN_RSP?

Legacy 广播的AdvData/ScanRspData上限都只有31 字节。本例中:

Flags 的 AD 结构 = 1(Length) + 1(Type) + 1(Data) = 3 字节 UUID 列表 AD 结构 = 1(Length) + 1(Type) + 6(3 个 UUID) = 8 字节 设备名 AD 结构 = 1(Length) + 1(Type) + 23(名字) = 25 字节 ────────────────────────────────────────────────────────────────── 全部塞进 AdvData 36 字节 > 31 ✗

超了, 所以源码把设备名挪到SCAN_RSP,广播包只留 Flags + UUID(11 字节)。

这是规范约束,不是「习惯」。

四、从广播到连接:跳频与 Channel Selection

为什么要跳频?因为 2.4 GHz 是公共频段,WiFi、蓝牙、Zigbee、微波炉都挤在一起。如果 BLE 一直用某个信道而它正好被 WiFi 占着,就会持续丢包。跳频把丢包风险分摊到 37 个信道上—— 某些信道差,其他信道还能用。

阶段信道数量特点
广播阶段37、38、393 个固定,所有人都知道
连接阶段0~3637 个跳频

4.1 主从怎么同步跳?

不能靠 “再发个包商量”,必须用双方都知道的确定性算法:

项目CSA #1CSA #2
引入版本BLE 4.0BLE 5.0
空口 ChSel 值01
算法本质简单递增取模伪随机 + 位运算
核心公式(简化)next = (last + hop) mod 37基于channelIdentifier + counter的伪随机映射
信道图受限时的表现⚠️ 分布不均,部分信道被过度使用✅ 保持均匀
抗干扰能力一般显著更强
最少可用信道要求≥ 2≥ 2

CSA #2 是可选特性:如果一方不支持,连接时自动降级到 CSA #1,不会出现「连不上」,只是性能差异。
谁决定?:广播者在ADV_IND的 ChSel 位宣告,发起者在CONNECT_IND里也带 ChSel,双方都支持才用 #2。

4.2 Channel Map 由谁维护?

主设备(通常是手机)。它在CONNECT_IND里把信道图交给从机,之后要改就通过LL_CHANNEL_MAP_IND下发。手机做 WiFi 共存时,会把被 WiFi 占用的信道标记为「不可用」,BLE 就只在剩下的信道里跳。

从机只能被动接受,没有拒绝的权利。规范要求信道图里至少要有 2 个可用信道 —— 即使干扰极严重,也要保留最少 2 个才能维持跳频。

五、速查手册

5.1 PDU Type 全表

二进制十六进制PDU Type说明
00000x0ADV_IND可连接 + 可扫描 + 非定向广播
00010x1ADV_DIRECT_IND可连接定向广播(高速重连)
00100x2ADV_NONCONN_IND不可连接、不可扫描(Beacon 常用)
00110x3SCAN_REQ扫描请求(由中心设备发出)
01000x4SCAN_RSP扫描响应
01010x5CONNECT_IND连接请求
01100x6ADV_SCAN_IND可扫描但不可连接
01110x7ADV_EXT_IND扩展广播指示(BLE 5.0)
10000x8AUX_ADV_IND 等辅助广播信道包(BLE 5.0)
1001~11110x9~0xFReserved保留

5.2 常用 AD Type

AD Type名称说明
0x01Flags发现模式 / BR/EDR 支持
0x02 / 0x0316-bit UUID 列表不完整 / 完整
0x04 / 0x0532-bit UUID 列表不完整 / 完整
0x06 / 0x07128-bit UUID 列表不完整 / 完整
0x08 / 0x09设备名截断版 / 完整版
0x0ATx Power Level发射功率
0x12Peripheral Connection Interval Range从机期望的连接间隔范围
0x16Service Data (16-bit UUID)服务数据
0x19Appearance外观(决定手机显示什么图标)
0x1AAdvertising Interval广播间隔
0x24URI网址
0xFFManufacturer Specific Data厂商自定义数据(iBeacon 核心)

5.3 三种 PHY

PHY调制速率编码数据速率特点
LE 1M1 Msym/s无1 Mb/sBLE 4.0 原始 PHY,兼容性最好
LE 2M2 Msym/s无2 Mb/sBLE 5.0 新增,快一倍,距离更近
LE Coded1 Msym/sS=8125 kb/sBLE 5.0 新增,距离最远
LE Coded1 Msym/sS=2500 kb/s速率与距离的折中

S= 每个 bit 用几个符号。S 越大,纠错越强、传得越远,但速率越低。

主广播信道(37/38/39)不能用 LE 2M,这是为了向后兼容老设备。
传统广播(ADV_IND / SCAN_RSP / CONNECT_IND)固定用 LE 1M;
扩展广播(ADV_EXT_IND)则可以在主信道上使用 LE Coded PHY。

返回列表