BLE 蓝牙空中报文格式与解析(广播包) BLE 广播包数据格式解析说明 ...... 矜辰所致
报文格式 是 蓝牙学习必备理论基础,本文来讲一讲蓝牙广播报文格式 以及 在 沁恒微蓝牙芯片代码中如何设置广播报文 。
我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!
BLE 广播报文(Advertising Packet)在空中的完整格式分 4 段,总共 47 字节(BLE 4.x/5.x 都一样),用户能改的只有中间 31 字节 Payload(下图浅绿色部分),其余由链路层自动拼好。
我们先上一张整体的广播包示意图(后面会详细分析):

我们再给加上解释说明:

看完整体的格式包,我们再重点关注一下我们应用时候可以修改的 Payload 部分, 这部分由若干「AD Structure」拼接而成,「AD Structure」是有一定格式的,我们在代码中定义广播包的时候就是要按照这种格式填写我们想要的广播数据。
「AD Structure」 格式如下:
Len(1 B) + Type(1 B) + Data(n B)
整包总长度 ≤ 31 B,不足补 0 ,如下图:

对于每个 「AD Structure」,我们重点要知道的是类型,AD Type(包括 0x01 ~ 0xFF 的全部定义)由 Bluetooth SIG(蓝牙技术联盟)统一分配和维护,大家需要用什么可以网上查询,这里放出部分常用 AD Type(保持更新):
| AD Type | Value (Hex) | 描述 |
|---|---|---|
| Flags | 0x01 | 广播出自己蓝牙某些特性 |
| Incomplete List of 16-bit Service UUIDs | 0x02 | 只放部分 16-bit UUID,不完全 |
| Complete List of 16-bit Service UUIDs | 0x03 | 完全的16-bit UUID |
| Incomplete List of 32-bit Service UUIDs | 0x04 | 部分 32-bit UUID |
| Complete List of 32-bit Service UUIDs | 0x05 | 完全的32-bit UUID |
| Incomplete List of 128-bit Service UUIDs | 0x06 | 部分 128-bit |
| Complete List of 128-bit Service UUIDs | 0x07 | 完全 128-bit |
| Shortened Local Name | 0x08 | 设备简称 |
| Complete Local Name | 0x09 | 设备全名 |
| TX Power Level | 0x0A | 广播出自己的射频发射功率 |
| Simple Pairing Option OOB Tags | 0x0D ~ 0x0F | 广播出安全管理带外标签(本文忽略) |
| Security Manager TK Value | 0x10 | 广播出带外方式配对绑定时的 TK(本文忽略) |
| Security Manager OOB Flags | 0x11 | 广播出带外特性标志(本文忽略) |
| Slave Connection Interval Range | 0x12 | 广播出自己已希望的连接参数范围 |
| ServiceData | 0x16 | 服务数据 |
| Appearance | 0x19 | 外观类型(鼠标/键盘/游戏柄等 HID 设备必放) |
| Advertising Interval | 0x1A | 广播出当前广播间隔(单位 0.625 ms) |
| PB-ADV | 0x22 | Mesh 配网阶段专用广播承载 |
| Manufacturer Specific Data | 0xFF | 广播出厂商信息(用户可以放自定义数据) |
根据上面表格,我们如果想设置短的 16bit UUID:
0x03 0x02 (UUID低8位) (UUID高8位)
0x03 0x02 0xE1 0xFF
如果想设置完整的名字:
(名字长度加+1) 0x09 (名字,自己取,自己算长度)
0x07 0x09 'S' 'i' 'm' 'p' 'l' 'e'
至此,广播包格式详细大家已经完全清楚了。
为什么讲蓝牙广播要提到扫描响应?
扫描响应的报文格式和蓝牙广播一摸一样。
我们先来说一下什么是扫描响应,广播是我们从机主动发出的报文,扫描响应是从机在收到主机扫描请求后 回复的响应报文(前提是它支持回复扫描响应),如下图:

扫描响应有什么作用?
我们知道蓝牙广播包只有 31 个字节可以用户自定义,如果我们广播数据放不下,想放更多的数据,我们可以写在 扫描响应里面,在手机扫描过程中,会一并作为广播包加入解析(下面会有示例说明)。
我们完成了理论说明,我们来看看在实际工程中广播包的体现,本次测试说明使用的是沁恒微蓝牙芯片 CH585 ,示例为官方的从机示例 Peripheral 。
我们只要关注的点就是在工程中peripheral.c 文件里面,有两个数组就是广播包的定义其中 scanRspData[] 对应扫描响应,advertData[] 对应广播包,我们烧录好程序观察一下现象:

通过图片大家应该可以很直观的理解,然后配合上文说明的 「AD Structure」 格式解析,应该都能明白怎么回事。
大家完全可以根据我们上文的说明,设置成自己想要的广播数据。
这里需要额外说明的是,上面说到过不是所有的广播包都支持扫描响应,在 CH58x 的 EVT 是使用:
GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, 1, &advEventType);
来设置广播类型的,但是示例中的从机初始化环节并没有设置GAPROLE_ADV_EVENT_TYPE 这个类型的操作,那是因为默认就是GAP_ADTYPE_ADV_IND类型:

我们可以继续查看一下,官方有哪些类型的定义:

上个表格就一目了然了:
| 宏定义(CH585 SDK) | 实际值 | 广播类型 | 支持连接? | 支持扫描响应? | 典型用途 |
|---|---|---|---|---|---|
GAP_ADTYPE_ADV_IND | 0x00 | 通用广播(可连接 / 非定向) | ✅ | ✅ | 最常见,外设等人来连 |
GAP_ADTYPE_ADV_HDC_DIRECT_IND | 0x01 | 高占空比定向广播(可连接 / 定向) | ✅ | ❌ | 快速重连,不响应扫描 |
GAP_ADTYPE_ADV_SCAN_IND | 0x02 | 可扫描广播(不可连接 / 非定向) | ❌ | ✅ | 只广播数据,允许扫描但不连 |
GAP_ADTYPE_ADV_NONCONN_IND | 0x03 | 不可连接广播(不可连接 / 非定向) | ❌ | ❌ | 纯 beacon,不连也不扫 |
GAP_ADTYPE_ADV_LDC_DIRECT_IND | 0x04 | 低占空比定向广播(可连接 / 定向) | ✅ | ❌ | 功耗更低定向包,同样不响应扫描 |
说明:沁恒微代码把「高占空比」和「低占空比」拆成两条宏,其实都属于同一个 PDU 类型 ADV_DIRECT_IND 。
所以我们想设置广播类型,只要在初始化的时候,加上这两句代码:
uint8_t advEventType = GAP_ADTYPE_ADV_IND;
GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, 1, &advEventType);
设置中文广播包,首先要知道中文的编码,蓝牙名称采用的编码格式位 UTF-8 格式的,一个汉字 UTF-8 编码格式占用 3 个字节。 我们实际生产编码的时候一般都需要使用工具。
我们测试的时候可以通过这个在线工具生成,网址如下:
https://www.jyshare.com/front-end/695/

然后我们把这个编码按照格式写入广播包定义数组里面,效果如下:

广播报文不复杂,我们这里也是简单上一下蓝牙分析仪抓包的效果:


通过 Adv PDU Type 我们就可以看出空中包的类型,简单解释一下:
SCAN_REQ
SCAN_RSP
ADV_NONCONN_IND
ADC_IND
AD_EXT_IND
上面既然说到了 Adv PDU Type ,那就补充说明一下,这部分的表示是在协议种的这个部分:

上个表格:
| PDU Type | 名称 | 简述 |
|---|---|---|
| 0b0000 (0) | ADV_IND | 可连接、可扫描、非定向 |
| 0b0001 (1) | ADV_DIRECT_IND | 可连接、定向、不扫描 |
| 0b0010 (2) | ADV_NONCONN_IND | 不可连接、不扫描 |
| 0b0011 (3) | SCAN_REQ | 扫描请求 |
| 0b0100 (4) | SCAN_RSP | 扫描响应 |
| 0b0101 (5) | CONNECT_IND | 连接请求 |
| 0b0110 (6) | ADV_SCAN_IND | 可扫描、不可连接 |
| 0b0111 (7) | ADV_EXT_IND | 扩展广播头包(指向 AUX 包 |
| 0b1000 (8) | AUX_ADV_IND | 扩展广播真正负载 |
抓包工具怎么看:

本文我们说明了一下蓝牙广播包的报文格式,以及使用沁恒微蓝牙芯片如何设置广播包,通过本文学习,相信大家能够应对所有广播数据修改的问题 。
在蓝牙设备连接上以后,连接过程数据交互也会有自己的协议包,这个在后期有机会也会写一篇文中给大家分析。
好了,本文就到这里。谢谢大家!
全部0条评论
快来发表一下你的评论吧 !