目录
1. 蓝牙基础概念
1.1 蓝牙协议分类
蓝牙协议主要有两种模式:
- 经典蓝牙(BR/EDR, Bluetooth Classic)
- 适用于音频传输、数据同步,如蓝牙音箱、无线耳机。
- 特点:数据速率高(最大3Mbps),功耗大,点对点连接,实时性强。
- 蓝牙低功耗(BLE, Bluetooth Low Energy)
- 适用于智能家居、物联网设备,如蓝牙电机、智能手环。
- 特点:数据速率较低(1Mbps或2Mbps),功耗低,支持广播模式,通信灵活。
蓝牙电机系统通常采用 BLE(低功耗蓝牙)模式,因为它可以:
- 降低功耗:适用于长时间待机的电机设备。
- 支持广播模式:允许手机扫描到设备并快速连接。
- 支持低延迟控制:适用于电机的实时开关、调速等操作。
2. BLE协议栈架构
BLE协议栈采用 分层架构,不同层级分别负责不同的功能:
+--------------------------------------------------+
| 应用层(Application Layer) |
+--------------------------------------------------+
| GATT(Generic Attribute Profile) |
| ATT(Attribute Protocol) |
+--------------------------------------------------+
| L2CAP(Logical Link Control and Adaptation) |
+--------------------------------------------------+
| HCI(Host Controller Interface) |
+--------------------------------------------------+
| 链路层(Link Layer) |
+--------------------------------------------------+
| 物理层(PHY) |
+--------------------------------------------------+
各层功能解析如下:
层级 | 功能 |
---|---|
应用层(Application Layer) | 处理具体应用逻辑,如窗帘开关、速度调节 |
GATT(通用属性协议) | 规定数据交互方式,如特征值的读取、写入等 |
ATT(属性协议) | 定义数据结构(Attribute),支持设备发现 |
L2CAP(逻辑链路控制) | 数据分片、重组、错误控制 |
HCI(主机控制接口) | 设备主机(手机)与蓝牙控制器(电机)的通信 |
链路层(Link Layer) | 设备连接管理、广播、数据交换 |
物理层(PHY) | 负责无线信号传输(2.4GHz,GFSK 调制) |
💡 重点关注 GATT 层,它是蓝牙电机数据交互的核心!
3. GATT数据模型与数据交互方式
GATT(通用属性协议)是BLE设备数据交互的核心,采用层级结构组织数据:
Service(服务)
├── Characteristic(特征)
│ ├── Value(数据值)
│ └── Descriptor(描述符)
3.1 服务与特征示例(以蓝牙电机为例)
服务名称 | 服务UUID | 特征名称 | 特征UUID | 数据属性 |
---|---|---|---|---|
电机控制服务 | 0xFFF0 | 开关状态 | 0xFFF1 | 读/写 |
速度调整 | 0xFFF2 | 读/写 | ||
设备信息服务 | 0x180A | 序列号 | 0x2A25 | 只读 |
电池电量 | 0x2A19 | 读 |
- 读取(Read): 手机可通过读取0xFFF1特征获取当前电机开关状态。
- 写入(Write): 手机通过写入特征值来控制电机开关或调速。
- 通知(Notify): 电机状态变化时,主动发送通知给手机,确保实时反馈。
3.2 数据交互方式
- Read(读取): 例如,手机请求当前电机状态:
ble_read_characteristic(0xFFF1, &status);
Write(写入): 例如,发送指令打开电机:
uint8_t open = 1;
ble_write_characteristic(0xFFF1, &open);
Notify(通知): 电机状态变化后主动通知手机:
ble_notify_characteristic(0xFFF1, current_state);
Indicate(指示): 类似于Notify,但要求接收端确认收到,适用于关键数据传输。
4. 蓝牙电机的通信流程
蓝牙通信可分为 五个阶段:
- 设备广播(Advertising)
- 设备扫描(Scanning)
- 连接建立(Connection)
- 数据交互(Data Transfer)
- 断开连接(Disconnection)
4.1 设备广播(Advertising)
当蓝牙电机启动后,进入广播模式,向周围设备发送“我是蓝牙电机”信号,等待手机发现并连接。
🔹 广播模式
BLE 设备可以选择不同的广播方式:
- 可连接广播(Connectable Advertising):电机允许手机连接。
- 不可连接广播(Non-connectable Advertising):仅用于设备状态广播,不允许连接。
- 定向广播(Directed Advertising):只允许特定手机连接,提高安全性。
💡 蓝牙电机通常使用“可连接广播”,允许手机随时连接。
🔹 广播包格式
BLE 广播包的有效数据部分(Payload)按照 TLV(Type-Length-Value)格式组织:
字段 | 大小(字节) | 说明 |
---|---|---|
Length | 1 | 该字段数据的长度(不包括自身) |
Type | 1 | 数据类型 |
Value | n | 具体数据值 |
一个标准的 BLE 广播包包含:
字段 | 字节数 | 描述 |
---|---|---|
Preamble | 1 | 同步头,接收端用于识别信号 |
Access Address | 4 | 广播设备的固定地址 |
PDU Header | 2 | 指明数据类型 |
Advertiser Address | 6 | 设备MAC地址 |
Payload | 0-31 | 设备信息(如UUID、电池电量、电机状态) |
CRC | 3 | 确保数据完整性 |
广播数据类型(Type)示例:
Type 值(十六进制) | 描述 |
---|---|
0x01 | 设备标志(Flags) |
0x02 | 16-bit UUID(部分) |
0x03 | 16-bit UUID(完整) |
0x06 | 128-bit UUID(完整) |
0x09 | 设备名称(Complete Local Name) |
0x0A | 发射功率(Tx Power Level) |
0x16 | 厂商自定义数据(Manufacturer Specific Data) |
0xFF | 自定义数据 |
🔹 具体示例
假设我们的蓝牙电机广播的数据包如下:
02 01 06 03 03 F0 FF 0B 09 44 4F 59 41 5F 4D 4F 54 4F 52
我们逐字段解析:
字段 | 数据 | 含义 |
---|---|---|
Flags(设备标志) | 02 01 06 | 表示设备支持 BLE |
UUID(16-bit,完整) | 03 03 F0 FF | 设备 UUID,0xFFF0 代表电机服务 |
设备名称(Complete Local Name) | 0B 09 44 4F 59 41 5F 4D 4F 54 4F 52 | "DOYA_MOTOR" |
📢 重点:
- 广播包前 2 字节 (
02 01 06
) 说明设备是 BLE 设备(不可配对)。 - UUID 16-bit(0xFFF0) 代表该设备是一个蓝牙电机。
- 设备名称 "DOYA_MOTOR" 通过
0x09
(Complete Local Name)字段表示。
🔹 读取广播包
在实际开发中,我们可以使用 蓝牙调试工具 解析广播包,例如:
- nRF Connect(推荐,支持 iOS 和 Android)
- LightBlue(iOS)
- Wireshark(带 BLE 解析插件)
- HCI Dump(Linux 命令行工具)
📌 使用 nRF Connect 读取广播包
- 打开 nRF Connect,扫描蓝牙设备。
- 选择目标设备(例如 "DOYA_MOTOR")。
- 进入 "Raw Advertising Data",查看广播数据。
- 解析各字段,验证设备名称、UUID、电机状态是否正确。
🔹 BLE 广播包数据的实际应用
在蓝牙电机系统中,广播包可用于:
- 设备发现:手机扫描广播包,识别电机设备(通过 UUID)。
- 状态通知:广播当前开关状态、电池电量。
- 设备配对:部分设备可通过广播包携带配对码,实现免输入连接。
- 节能优化:
- 低频广播(降低功耗):设备待机时,减少广播频率(如每2秒广播一次)。
- 高频广播(快速发现):当设备进入可连接状态,提高广播频率(如每100ms广播一次)。
示例代码(蓝牙广播)
uint8_t adv_data[] = {
0x02, 0x01, 0x06, // Flags: BLE General Discoverable, No BR/EDR
0x03, 0x03, 0xF0, 0xFF, // Complete List of 16-bit UUIDs (0xFFF0)
0x0B, 0x09, 'D', 'O', 'Y', 'A', '_', 'M', 'O', 'T', 'O', 'R' // Local Name
};
ble_set_advertising_data(adv_data, sizeof(adv_data));
📌 上面代码的功能:
- 广播 BLE 设备标志(
0x06
)。 - 广播 UUID(
0xFFF0
)。 - 广播设备名称("DOYA_MOTOR")。
4.2 设备扫描(Scanning)
- 手机(Central)会扫描附近的蓝牙设备,找到符合条件的目标设备(蓝牙电机)。
- 一旦发现蓝牙电机,手机会读取它的UUID,确定是否为可控设备。
📌 扫描流程:
- 手机扫描广播信号
- 解析广播数据包
- 判断是否是蓝牙电机
- 发起连接请求(Connection Request)
4.3 连接建立(Connection)
当手机发起连接请求时,蓝牙电机会:
- 进入连接模式,为手机分配通信信道。
- 确认连接参数(如数据传输间隔、超时时间)。
- 交换密钥(如果需要安全连接)。
📌 连接参数
参数 | 说明 |
---|---|
Connection Interval | 连接间隔(7.5ms-4s),影响功耗 |
Slave Latency | 允许从设备跳过的连接间隔,降低功耗 |
Supervision Timeout | 连接超时时间,超时后断开连接 |
💡 低功耗优化:
- 如果电机在待机状态,可设定较长的
Connection Interval
(如500ms),减少通信频率。 - 如果电机正在运行,则缩短
Connection Interval
(如50ms),提高响应速度。
4.4 数据交互(Data Transfer)
连接建立后,手机和电机通过 GATT(通用属性协议) 进行通信。
📌 数据传输方式
- 读(Read):手机读取电机状态(开/关、速度)。
- 写(Write):手机控制电机(开/关、调速)。
- 通知(Notify):电机主动向手机上报状态变化。
4.5 断开连接(Disconnection)
- 设备可因超时或主动断开(用户关闭蓝牙)断开连接。
- 断开后,电机重新进入 广播模式,等待下次连接。
📌 断开连接的常见原因
原因 | 解决方案 |
---|---|
信号太弱 | 提高发射功率,优化天线 |
超时 | 增加Supervision Timeout 值 |
手机蓝牙关闭 | 提示用户重新连接 |