type
status
date
slug
summary
tags
category
password
icon
蓝牙

蓝牙广播
蓝牙信道
低功耗蓝牙一共有 40 个信道
频道范围从 2402MHz 到 2480MHz ,每 2MHz 一个信道
其中 37,38,39 是广播信道

一个广播数据包最长 37 个字节
其中包含 6 个字节用作蓝牙设备的 MAC 地址,剩余 31 个字节称为广播数据包,其又被分为若干个广播数据结构体(AD Structure)

当广播数据包内容不够 31 个字节时,系统会自动补 0,凑够 31 个字节
常见的广播类型如下:

蓝牙设备名称采用 UTF-8 编码,完整的广播类型文档参考链接
特别注意:
当 AD Type 为 0x01 表示的是设备标识,含义如下:
数据位 | 含义 |
Bit0 | LE有限可发现模式 |
Bit1 | LE普通可发现模式 |
Bit2 | 不支持 BR/EDR(经典蓝牙) |
Bit3 | 控制器端同时支持 BR/EDR 和LE(低功耗蓝牙) |
Bit4 | 主机端同时支持 BR/EDR 和 LE |
Bit 5 - 7 | 保留 |
如果设备只支持 LE (低功耗蓝牙),不支持 BR/EDR (经典蓝牙),一般都将设备设为处于普通发现模式,所以只设置 Bit1 和 Bit2 ,即 0x06(b00000110)
扫描请求和扫描响应
蓝牙设备除了可以通过上述方式,主动的发射广播数据外,还可以接受其他设备的扫描请求,从而响应额外的数据,二者的区别如下:
广播是蓝牙从机设备主动发出的数据。
而扫描响应是,当蓝牙主机收到从机的广播数据后,如果想要进一步了解该从机设备的信息,可以向从机设备发送扫描请求,从机收到扫描请求后,向对应的主机回复扫描响应。

我们前文中讲到,蓝牙的广播数据最多是 31 个字节,如果广播数据太多,这 31 个字节装不下时,我们就可以将一部分不太重要的数据放到扫描响应数据里面,来分担广播数据的工作。
在 Android 蓝牙开发中广播包有两种:
- 广播包(Advertising Data):大小限制在 37 字节
- 响应包(Scan Response)
外围设备在开启广播时可以带上广播包(必带)或响应包(可选),中心设备扫描到广播时,二者会一起被接收,并放在同一 buffer 中
状态切换和事件处理
蓝牙状态机
蓝牙链路层的状态机有五种状态,分别是就绪态,广播态,链接态,扫描态,发起连接态,各个状态间的转换路径如下图所示:

以手机连接某个蓝牙模块为例,手机作为主机设备,蓝牙模块作为从机设备。上电之后二者都将处于就绪态,蓝牙模块设置广播数据并开始广播后将转换到广播态;手机扫描附近范围内的蓝牙设备时,手机将处于扫描态,手机尝试连接某个设备时,手机的蓝牙处于发起连接态,连接成功后,二者将都处于链接态。断开连接之后,二者将都再回到就绪态!
服务(Service)和特性(Characteristic)
UUID
UUID是 University Unique Identifie 的缩写,翻译成中文为 通用唯一标识符。是蓝牙组织联盟定义的用于区分蓝牙服务和特性的的标识符,总长度为 128Bit。例如:
128Bit 的 UUID 占用 16 个字节,在变成个传输的时候都很不方便,所以蓝牙联盟定义了一个 UUID 的基地址,允许在此基础上使用 16Bit 的 UUID。
UUID 基地址:
0x0000xxxx-0000-1000-8000-00805F9B34FB
比如 16Bit 的 UUID : 0x2A37 转换成 128Bit 的 UUID 为:
低功耗蓝牙设备之间通信,都是基于服务和特性。一个蓝牙设备中可以包含若干个服务,一个服务中可以包含若干个特性,每一个服务或者特性都要有一个 UUID 。

蓝牙的数据交互都是基于一个个特性进行的,数据交互的方式有五种,分别是
Read
,Write
,Write WithOutRespons
,Notify
,Indication
。上述没说到,每个特性还可以包含若干个
Descriptor
描述,如果想要外围设备的某个特征具有 Notify
,那么就需要为这个特征添加一个代表能够主动通知的描述(UUID=”0x2902”
)服务和特性的创建
蓝牙设备要在进入广播态之前创建服务和特性,在 MicroPython 中大概分为四步:
- 创建要使用的 UUID;
- 使用 UUID 创建特性并设置特性的读写权限;
- 将创建好的特性添加到服务集合中;
- 将服务集合注册到协议栈中
数据交互
低功耗蓝牙之间的数据交互都是基于特性,以手机连接蓝牙模块为例,手机读取蓝牙模块的数据,使用的是 Read 方法,手机发送数据给蓝牙模块使用的是 Write 方法,蓝牙模块发送数据到手机,一般使用的是 Notify 方法,而且手机端还要打开 Notify 监听。 低功耗蓝牙设备之间通信常用的方式是 Read,Write 和 Notify ,必须在创建特性时赋予对应的权限,才能在通信中使用。如果某个特性在创建的时候,没有开启 Write 权限,则手机将无法通过该特性发送数据到设备;
已定义的 16Bit UUID
对于一些常用的功能,蓝牙组织联盟已经为其定义好了 UUID,我们在开发产品的时候直接使用即可。
16Bit UUID 定义文档下载地址
数据收发
包格式:
一帧低功耗蓝牙的数据包一般情况下最多有261个字节,包含如下内容:
- 预补码:1个字节,用于时钟同步和信道估计
- 访问地址: 4个字节
- 数据位: 2~253字节
- CRC校验位: 3字节
经典蓝牙和低功耗蓝牙的区别

📎 参考文章
- 作者:shuouyang
- 链接:https://notion-tree.vercel.app/article/f430a15e-d9fa-4d62-be55-e10a18178818
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。