前言
本文主要讲述BLE链路层交互的空中包相关概念
BLE的协议栈架构层级划分简述如下:
层级 | 功能 | 示例 |
---|---|---|
物理层(PHY) | 负责无线信号的调制/解调,工作在 2.4GHz ISM 频段(40个信道:37 data, 3 advertising) | GFSK 调制,1Mbps(BLE 5.0 支持2Mbps) |
链路层(Link Layer) | 管理广播、扫描、连接建立和数据传输 | 处理 ADV_IND 或 CONNECT_REQ |
主机控制接口层(HCI) | 定义主机(Host)与控制器(Controller)间的通信协议(如指令、事件、数据流) | 通过 UART/USB 传输 HCI 命令包 |
逻辑链路控制与适配协议(L2CAP) | 提供数据分片、重组和多路复用,管理协议通道 | 将 ATT 数据分片为适合链路层的包 |
安全管理层(SM) | 处理配对、加密和密钥分发,保障通信安全 | 使用 AES-CCM 加密链路数据 |
属性协议层(ATT) | 定义设备间数据访问的协议(读/写/通知),基于客户端-服务器模型 | 读取设备的电量值(0x180F 服务) |
通用属性配置文件(GATT) | 在 ATT 基础上组织数据为服务(Service)、特征(Characteristic)等结构 | 心率服务(0x180D)包含测量特征 |
通用访问配置文件(GAP) | 管理设备可见性、连接模式和安全性(角色:广播者、观察者、外围/中心设备) | 设置设备为可连接模式 |
蓝牙设备间的通信,归根到底都是基于空中数据包的交互,本文主要讲述BLE空中包,以及涉及到空中包的相关知识、应用、场景。
BLE空中包基础
BLE链路层(Link Layer)只定义了一种空中包格式:Preamble(前导帧)| Access Address | PDU(protocol data unit,协议数据单元) | CRC(cyclic redundancy check,循环冗余校验)
ATT、GATT、GAP层 都是基于数据信道包的payload的概念
Preamble(前导帧):0x55或者0xAA
Access Address
Access Address用来标示接收者ID或者空中包身份,根据Access Address的不同,区分两种Packet类型:广播包
和数据包
- 广播包Access Address 固定为0x8E89BED6
- 数据包,是数据信道空中包的简称,数据包只在数据信道上传输,即除37/38/39之外的其余37信道(Bluetooth LE总共占用40个信道)。
PDU
PDU(protocol data unit,协议数据单元)前两个字节固定为LL header(1个字节长)和payload length(1个字节长,又称data length)
PDU
进一步为:LL Header | Payload Length | Payload
PDU 是 BLE 协议栈链路层的核心概念,定义了设备间数据交换的基本格式。无论是广播还是连接状态下的通信,都依赖于特定类型的 PDU 来完成任务。
BLE广播包
广播包,全名蓝牙广播通道(channel)空中包,即在蓝牙广播通道上传输的空中包,为两种空中包的一种。
对于广播包,PDU
段的格式为:LL Header(1 Byte) | Payload Length(1 Byte) | Payload(6-37 Bytes)
PDU
段的LL Header
,即Advertising Header,其8个bit定义如下所示:
- Bit0:接收地址类型
- Bit1:发送地址类型
- Bit2-3:保留
- Bit4-7:广播报文类型,具体定义如下:
类型 包 用法 0000 ADV_IND 可连接非定向广播 0001 ADV_DIRECT_IND 可连接定向广播 0010 ADV_NONCONN_IND 不可连接非定向广播 0011 SCAN_REQ 扫描者需要获得更多信息的扫描请求 0100 SCAN_RSP 响应来自扫描者的扫描请求 0101 CONNECT_REQ 发起者的连接请求 0110 ADV_SCAN_IND 可扫描、不可连接的无定向广播 xxxx 保留
Payload Length: 广播报文规范的长度范围是6-37字节
Payload:
- Device Address:蓝牙MAC地址(6 Bytes)是强制的
- 对于ADV_IND、SCAN_RSP两种类型的广播包,Advertising data的最大值为
37 - 6 = 31
字节,这就是广播包数据最长只能为31个字节的由来 - ADV_DIRECT_IND 直连广播包净荷格式由6字节的广播设备地址和6字节的目标设备地址组成
- SCAN_REQ 扫描请求包净荷格式由6字节的扫描设备地址和6字节的广播设备地址组成。远程发起连接的设备,搜索到周围正在广播的设备后,一般会发送扫描请求。
对于一个可连接非定向广播而言,主机设备仅通过广播能够获取到其的数据长度为
被动接收的ADV_IND:31个字节 + 主动扫描的回复包SCAN_RSP:31个字节 = 62个字节
广播包数据(Advertising data)
广播包的数据由多个 AD Structure 组成,每个结构包含3个字段:
- 应用数据的结构格式:
AD Structure 1 | AD Structure 2 | ... | AD Structure N
AD structure
的格式为:Length(1 Byte) | Type(1 Byte) | Data
Length(1字节)
:表示Type
和Data
的长度Type(1字节)
:数据类型标识,表示Data
的用途。0x02
表示不完整的16位服务UUID(示例值:0x180A),0x09
表示设备完整名称,0x0A
表示发射功率等级,0x19
表示设备外观,0xFF
表示自定义数据(可以私有定义)等等,具体定义见如下:- 特别地说明,广播名称属于type:0x09,可以选择放置在ADV_IND(主动广播包),或者ADV_RSP(扫描响应包),由于
Length
和Type
各占用了一个字节,那么BLE广播名称的最大有效长度为31 - 2 = 29
个字节。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46/*eir packet_type*/
typedef enum {
HCI_EIR_DATATYPE_FLAGS = 0x01,
HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS = 0x02,
HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS = 0x03,
HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS = 0x04,
HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS = 0x05,
HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS = 0x06,
HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS = 0x07,
HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME = 0x08,
HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME = 0x09,
HCI_EIR_DATATYPE_TX_POWER_LEVEL = 0x0A,
HCI_EIR_DATATYPE_CLASS_OF_DEVICE = 0x0D,
HCI_EIR_DATATYPE_SIMPLE_PAIRING_HASH_C = 0x0E,
HCI_EIR_DATATYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F,
HCI_EIR_DATATYPE_SECURITY_MANAGER_TK_VALUE = 0x10,
HCI_EIR_DATATYPE_SECURITY_MANAGER_OOB_FLAGS = 0x11,
HCI_EIR_DATATYPE_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12,
HCI_EIR_DATATYPE_16BIT_SERVICE_SOLICITATION_UUIDS = 0x14,
HCI_EIR_DATATYPE_128BIT_SERVICE_SOLICITATION_UUIDS = 0x15,
HCI_EIR_DATATYPE_SERVICE_DATA = 0x16,
HCI_EIR_DATATYPE_APPEARANCE_DATA = 0x19,
HCI_EIR_DATATYPE_ADVERTISING_INTERVAL = 0X1A,
HCI_EIR_DATATYPE_LE_BLUETOOTH_DEVICE_ADDRESS = 0X1B,
HCI_EIR_DATATYPE_LE_ROLE = 0X1C,
HCI_EIR_DATATYPE_SIMPLE_PAIRING_HASH_C256 = 0X1D,
HCI_EIR_DATATYPE_SIMPLE_PAIRING_RANDOMIZER_R256 = 0X1E,
HCI_EIR_DATATYPE_LIST_OF_32BIT_SERVICE_SOLICITATION_UUIDS = 0X1F,
HCI_EIR_DATATYPE_SERVICE_DATA_32BIT_UUID = 0X20,
HCI_EIR_DATATYPE_SERVICE_DATA_128BIT_UUID = 0X21,
HCI_EIR_DATATYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0X22,
HCI_EIR_DATATYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0X23,
HCI_EIR_DATATYPE_URI = 0X24,
HCI_EIR_DATATYPE_INDOOR_POSITIONING = 0X25,
HCI_EIR_DATATYPE_TRANSPORT_DISCOVERY_DATA = 0X26,
HCI_EIR_DATATYPE_LE_SUPPORTED_FEATURES = 0X27,
HCI_EIR_DATATYPE_CHANNEL_MAP_UPDATE_INDICATION = 0X28,
HCI_EIR_DATATYPE_BIGINFO = 0X2C,
HCI_EIR_DATATYPE_BROADCAST_CODE = 0X2D,
HCI_EIR_DATATYPE_RESOLVABLE_SET_IDENTIFIER = 0X2E,
HCI_EIR_DATATYPE_ADVERTISING_INTERVAL_LONG = 0X2F,
HCI_EIR_DATATYPE_BROADCAST_NAME = 0X30,
HCI_EIR_DATATYPE_3D_INFORMATION_DATA = 0X3D,
HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF
} HCI_EIR_datatype_t;
广播信道空中包类型及应用
定向与非定向广播的区别与联系、应用
定向广播 的 Payload 中包含两个地址:
- 广播设备地址(6字节)
- 目标设备地址(6字节)
连接与非连接广播的区别与联系、应用
物理信道
BLE信道:40个,其中3个为广播信道,其余37个为连接信道
信标是什么
实际应用案例设计讲解
定向连接广播应用
一个Server设备如果已经与主机设备配对连接过,那么如果想要实现后续回连,只能这个主机去单独连接。避免其它设备点击误连接。 则可以设置定向广播,首次没有连接过时,设置为非定向广播。有连接记录后,记录目标设备的MAC地址,下次连接时,设置定向广播,指定目标MAC地址。
- 从而限制仅目标设备可以连接此个广播。
比如音箱与手环,如果是非定向广播,那么任何主机设备都能点击连接到广播,就会导致有时候想点击连接时,被其它设备占用了连接。
多个广播、多主机连接应用
ble5.0 扩展广播同时支持多个广播,如何配置呢?
需要注意 多个广播和多主机连接的区别与应用
Server(从机)广播参数设置
主动广播包(Advertising Packet)扫描响应包(Scan Response Packet)
两种广播包,主动广播包和响应包,各31个字节,共62字节
adv packet:放置其它字段
adv resonse:可以只用来放置名称
代码应用示例(以杰理方案为例)
1 | /*! |
思考与拓展
BLE的加密、配对是怎样的?LTK是什么?一般不都是直接点击就连接成功了吗?
BLE 支持配对(Pairing)和绑定(Bonding)。配对、绑定是 BLE 安全机制的一部分,位于 GAP 和 SM 层,不属于 GATT 层。
配对绑定流程简述
连接建立
发起配对请求(Pairing Request)
交换 IO 能力(Display Only / Keyboard Only / No Input No Output 等)
计算 TK、LTK、CSRK
设备确认(MITM Protection)
绑定信息保存到 Flash/NVS
完成:进入 BONDED 状态
密钥类型 描述
LTK(Long Term Key) 加密通信使用的主密钥
IRK(Identity Resolving Key) 解析私有地址(Private Address)
CSRK(Connection Signature Resolving Key) 数据签名验证
EDIV & RAND 用于 LTK 再生
可以通过按键确认绑定配对。
绑定 启用 bond = 1 并保存密钥
用户确认 按钮触发配对响应
下次连接 自动恢复加密状态,无需重新配对
情况一:只连接不配对
可以读写 GATT 特性
但不能访问受保护的特性(如带加密要求的服务)
安全等级较低,适合调试
✅ 情况二:配对但不绑定
当前连接可以加密通信
下次连接仍需重新配对
✅ 情况三:配对并绑定
第一次连接后保存密钥
下次连接可直接恢复加密通道(无需重新配对)
不是说广播一包最大255个字节吗?为什么又说广播包数据最多只能放31个字节?
空中包的数据包类型的有效载荷最大296字节?
BLE名称通常放在哪个广播包?可以分散放在不同包中吗?为什么?
可以放在ADV_IND,也可以放在ADV_RSP,但只能放在一个广播包中
说明名称的长度最大29个字节
广播参数有哪些?连接参数有哪些?有什么区别与联系?
slot是什么
手机扫描周围的广播时,会向所有发现的广播发送扫描请求吗?这个发送过程是怎样的?
是向周围广播 扫描请求 包吗?
BLE 4.x 和 BLE 5.x 有什么区别?在空中包上的体现有哪些?
信道上的区别
4.x 默认信道 37 38 39
从蓝牙5.0开始广播包可以在其它信道上传输
格式的兼容性
BLE连接后,通信所在的信道会动态变化吗?
LE-Audio走的是广播信道包?还是数据信道包?
BIS走广播信道?CIS走走数据信道?
BIS的接收过程是怎样的?
CIS的连接过程是怎样的?
特征服务可以放到广播包里面吗?跟一般的放在数据信道包有什么区别?
可连接、不可连接、定向、非定向的广播包有什么区别?优劣对比?应用场景分别是?
如何区分BLE连接与非连接情况下的通信?
在数据信道上通信,就是连接状态?
在广播信道上通信,就是非连接状态?
广播信道空中包的间隔有什么要求?一般是多少?设置不同的间隔有什么影响?与数据信道空中包的间隔设计有什么差异?
当广播包(ADV_IND)和扫描响应包(SCAN_RSP)同时包含0x09类型(设备名称)字段且名称内容不同,主机端扫描显示名称结果是怎样的?
取决于主机端的软件设计逻辑
扫描结果的可能表现
(1)优先显示扫描响应包(SCAN_RSP)的名称
原因:扫描设备(如手机)在主动发送SCAN_REQ后,SCAN_RSP被视为对广播数据的补充,部分系统会优先使用SCAN_RSP中的名称覆盖ADV_IND的名称。
示例:
若ADV_IND中设备名为”Device_A”,SCAN_RSP中为”Device_B”,最终显示为”Device_B”。
例如在Nordic SDK中,SCAN_RSP的配置会覆盖ADV_IND的同类型字段。
(2)合并显示或冲突处理
合并逻辑:某些设备可能将两个名称拼接(如”Device_A_Device_B”),但此行为不符合蓝牙规范。
冲突处理:若名称字段重复且内容不一致,部分系统可能触发错误日志或直接忽略其中一个字段。
(3)仅显示首次接收的名称
无主动扫描时:若扫描设备未主动发送SCAN_REQ(如仅被动监听),则只显示ADV_IND中的名称。
主动扫描时:若设备同时接收两个包,可能优先显示SCAN_RSP的最新数据