BLE 协议栈 低功耗蓝牙
目录
一、BLE 的由来与本质
1.1 什么是 BLE
BLE(Bluetooth Low Energy,低功耗蓝牙)是蓝牙技术联盟(Bluetooth SIG)于 2010 年在蓝牙 4.0 规范中引入的低功耗无线通信技术。与经典蓝牙(Bluetooth Classic)相比,BLE 专注于低功耗、低复杂度、低成本,适用于物联网、可穿戴设备、智能家居等场景。
BLE 的本质是用极低的功耗实现短距离、低速率的无线通信。BLE 设备在不通信时处于深度睡眠状态,只在需要时短暂唤醒发送或接收数据,因此功耗可以低到微安级别,一粒纽扣电池可以使用数月甚至数年。
1.2 BLE 的由来
BLE 的前身是诺基亚在 2006 年开发的 Wibree 技术。2007 年,诺基亚与蓝牙技术联盟合作,将 Wibree 纳入蓝牙规范。2010 年,蓝牙 4.0 发布,Wibree 以 Bluetooth Low Energy 的名称正式成为蓝牙标准的一部分。
BLE 的设计目标与经典蓝牙完全不同:
-
经典蓝牙:面向音频流和文件传输,追求高吞吐(可达 24 Mbps),功耗较高。
-
BLE:面向传感器和控制信号,追求低功耗,吞吐较低(最大约 2 Mbps,实际应用通常几十 Kbps)。
蓝牙 4.0 之后,BLE 持续演进:
-
蓝牙 4.2(2014):引入数据包长度扩展(LE Data Length Extension),提高吞吐量。
-
蓝牙 5(2016):引入 2 Mbps 物理层、长距离模式(Coded PHY)、广播扩展(Advertising Extensions)。
-
蓝牙 5.1(2019):引入寻向功能(Direction Finding),支持厘米级定位。
-
蓝牙 5.2(2020):引入 LE Isochronous Channels,支持低延迟音频。
-
蓝牙 5.3(2021):优化连接建立和周期广播。
-
蓝牙 5.4(2023):引入周期性广播响应,支持大规模设备配置。
1.3 BLE 与经典蓝牙的区别
| 维度 | 经典蓝牙 | BLE |
|---|---|---|
| 功耗 | 高(几十 mA) | 极低(几 μA) |
| 传输距离 | 10-100 米 | 10-100 米(长距离模式可达 1000 米) |
| 吞吐率 | 1-24 Mbps | 125 Kbps - 2 Mbps |
| 连接延迟 | 约 100 ms | 约 6 ms |
| 网络拓扑 | 微微网(1 主 7 从) | 星型、Mesh |
| 典型应用 | 耳机、音箱、文件传输 | 传感器、可穿戴、智能家居 |
| 安全性 | SSP | LE Secure Connections |
1.4 BLE 的核心设计理念
BLE 的设计理念围绕"低功耗"展开:
-
快速连接:连接建立只需几毫秒,通信后立即断开,减少射频活动时间。
-
短数据包:数据包长度小,传输时间短,减少射频开启时间。
-
低占空比:设备大部分时间处于睡眠状态,只在广播或连接事件时唤醒。
-
跳频扩频:在 40 个信道上跳频,避免干扰,提高可靠性。
-
星型拓扑:一个主设备连接多个从设备,简化网络管理。
1.5 BLE 与经典蓝牙的共存
蓝牙 4.0 及以后的版本同时支持经典蓝牙和 BLE,称为双模(Dual Mode)蓝牙。双模设备可以同时与经典蓝牙设备和 BLE 设备通信。
还有单模(Single Mode)BLE 设备,只支持 BLE,不支持经典蓝牙。单模设备成本更低、功耗更低,但只能与 BLE 设备通信。
大多数智能手机和电脑是双模设备,大多数物联网传感器是单模设备。
1.6 BLE 的应用场景
BLE 的应用场景广泛,主要包括:
-
可穿戴设备:智能手表、手环、心率带等,通过 BLE 与手机同步数据。
-
智能家居:智能灯、门锁、温控器等,通过 BLE 与手机或网关通信。
-
医疗健康:血糖仪、体温计、血压计等,通过 BLE 上传健康数据。
-
资产追踪:BLE Beacon 用于室内定位和资产追踪。
-
人机接口:蓝牙键盘、鼠标、遥控器等。
-
近场支付:BLE 可以用于近场支付和门禁。
二、BLE 协议分层架构
2.1 BLE 协议栈分层
BLE 协议栈自下而上分为三层:
-
控制器层(Controller):包括物理层(PHY)和链路层(LL),负责射频收发、跳频、连接管理。
-
主机层(Host):包括 L2CAP、ATT、GATT、GAP、SMP,负责数据封装、服务发现、配对安全。
-
应用层(Application):具体的应用程序,定义自定义服务和特征。
控制器层和主机层之间通过 HCI(Host Controller Interface)通信。在单芯片方案中,HCI 是芯片内部接口;在双芯片方案中,HCI 可以是 UART、SPI 或 USB。
HCI 定义了主机和控制器之间的命令、事件和数据包格式。主机通过 HCI 命令控制控制器(如启动广播、发起连接),控制器通过 HCI 事件通知主机(如连接完成、断开),数据包通过 HCI ACL 或 HCI LE ACL 传输。
HCI 的标准化使得主机和控制器可以独立实现和替换,这是 BLE 生态繁荣的基础。
2.2 物理层(PHY)
BLE 物理层工作在 2.4 GHz ISM 频段,分为 40 个信道:
-
3 个广播信道(37、38、39):用于设备发现和连接建立。
-
37 个数据信道(0-36):用于连接后的数据传输,采用跳频。
BLE 支持多种物理层速率:
-
1 Mbps:蓝牙 4.0 起支持,兼容所有 BLE 设备。
-
2 Mbps:蓝牙 5 起支持,吞吐量加倍,适合音频和固件升级。
-
125 Kbps / 500 Kbps(Coded PHY):蓝牙 5 起支持,长距离模式,通过前向纠错提高灵敏度。
2.3 链路层(LL)
链路层负责设备间的射频通信,主要功能包括:
-
广播:设备定期在广播信道发送广播包,宣告自身存在。
-
扫描:设备监听广播信道,发现周围设备。
-
连接建立:发起方收到广播后发送连接请求,建立连接。
-
跳频:连接建立后,双方按约定的跳频序列在数据信道间跳频。
-
流控与重传:通过序列号和确认机制保证数据可靠传输。
-
信道映射:根据信道质量,排除受干扰的信道。
链路层有五种状态:待机(Standby)、广播(Advertising)、扫描(Scanning)、发起(Initiating)、连接(Connection)。
链路层数据包格式
BLE 链路层数据包由四部分组成:
-
前导码(Preamble):1 字节,用于接收机同步。1 Mbps PHY 为 0xAA,2 Mbps PHY 为 0x55。
-
接入地址(Access Address):4 字节,标识数据包所属的连接。广播信道使用固定地址 0x8E89BED6,数据信道使用连接时协商的随机地址。
-
PDU(协议数据单元):2-257 字节,包含数据头和有效载荷。
-
CRC(循环冗余校验):3 字节,用于检错。
PDU 的头包含类型字段,标识数据包的类型(广播、扫描请求、连接请求、数据等)。
跳频机制
BLE 连接使用自适应跳频(Adaptive Frequency Hopping),在 37 个数据信道间跳频。跳频序列由中央设备生成,基于连接的接入地址和中央设备时钟。双方在连接事件中使用相同的跳频序列,保证能在相同信道上相遇。
自适应跳频会根据信道质量排除受干扰的信道。中央设备定期评估信道质量,将差的信道加入黑名单,跳频时跳过这些信道。
2.4 L2CAP(逻辑链路控制与适配协议)
L2CAP 位于链路层之上,提供多路复用和数据分片重组。BLE 的 L2CAP 支持两种信道:
-
固定信道:用于 ATT(0x0004)、SMP(0x0006)、L2CAP 信令(0x0005)。
-
动态信道:用于 LE Credit Based Flow Control Mode,支持自定义协议。
L2CAP 的数据单元称为 SDU(Service Data Unit),L2CAP 将 SDU 分片为链路层的 PDU(Protocol Data Unit)传输。
2.5 ATT(属性协议)
ATT 是 BLE 数据访问的基础协议,定义了客户端如何读取、写入、通知服务器上的属性。ATT 基于客户端-服务器模型:
-
服务器(Server):持有属性数据,响应客户端请求。
-
客户端(Client):读取或写入服务器的属性。
ATT 的操作包括:
-
Read:读取属性值。
-
Write:写入属性值。
-
Notify:服务器主动通知客户端属性变化(无确认)。
-
Indicate:服务器主动指示客户端属性变化(有确认)。
2.6 GATT(通用属性配置文件)
GATT 在 ATT 之上定义了数据的层次结构:
-
服务(Service):一组相关的特征,代表一个功能模块。
-
特征(Characteristic):一个数据项,包含值、属性、描述符。
-
描述符(Descriptor):特征的附加信息,如客户端特性配置(CCCD)。
GATT 定义了多种标准服务(如电池服务、心率服务),厂商也可以定义自定义服务。
2.7 GAP(通用访问配置文件)
GAP 定义了设备如何发现、连接和管理连接。GAP 定义了四种设备角色:
-
广播者(Broadcaster):只发送广播,不接受连接。
-
观察者(Observer):只扫描广播,不发起连接。
-
外设(Peripheral):广播并接受连接。
-
中央(Central):扫描并发起连接。
GAP 还定义了广播数据格式、扫描响应格式、连接参数等。
2.8 SMP(安全管理协议)
SMP 负责设备配对和密钥分发,提供加密和认证。BLE 的配对流程包括:
-
配对特征交换:交换配对能力(输入输出能力、认证要求)。
-
密钥生成:根据配对方法生成短期密钥(STK)。
-
链路加密:使用 STK 加密链路。
-
密钥分发:分发长期密钥(LTK)、身份解析密钥(IRK)等。
BLE 4.2 引入 LE Secure Connections,使用 ECDH 密钥交换,防止中间人攻击。
三、GAP 广播与扫描
3.1 广播类型
BLE 定义了四种广播类型:
-
ADV_IND:可连接可扫描的非定向广播,最常用。
-
ADV_DIRECT_IND:定向广播,只向特定设备发送,用于快速重连。
-
ADV_NONCONN_IND:不可连接的广播,用于广播者角色(如 Beacon)。
-
ADV_SCAN_IND:可扫描但不可连接的广播。
3.2 广播数据格式
广播数据包最大 31 字节(蓝牙 5 扩展广播可达 255 字节),由多个 AD Structure 组成,每个结构包含长度、类型、数据。常见的 AD 类型包括:
-
Flags:设备模式(有限可发现、通用可发现等)。
-
Incomplete List of 16-bit Service UUIDs:设备支持的服务。
-
Complete Local Name:设备名称。
-
TX Power Level:发射功率。
-
Manufacturer Specific Data:厂商自定义数据。
3.3 扫描
扫描设备监听广播信道,接收广播包。扫描有两种模式:
-
被动扫描:只接收广播包,不发送扫描请求。
-
主动扫描:收到广播后发送扫描请求,获取扫描响应数据。
扫描参数包括扫描间隔(Scan Interval)和扫描窗口(Scan Window)。扫描间隔是两次扫描的间隔,扫描窗口是每次扫描的持续时间。占空比 = Scan Window / Scan Interval,占空比越高发现设备越快,但功耗越大。
3.4 连接建立
中央设备收到外设的广播后,可以发送连接请求(CONNECT_IND)。连接请求包含连接参数:
-
连接间隔(Connection Interval):两次连接事件的间隔,7.5 ms - 4000 ms。
-
从设备延迟(Slave Latency):从设备可以跳过的连接事件数。
-
监管超时(Supervision Timeout):连接的超时时间。
连接建立后,双方按连接间隔在数据信道上跳频通信。
四、GATT 与 ATT
4.1 属性表
GATT 服务器维护一个属性表,每个属性包含:
-
句柄(Handle):唯一标识,16 位。
-
类型(Type):属性类型的 UUID(16 位或 128 位)。
-
权限(Permissions):读、写、通知等权限。
-
值(Value):属性数据。
属性表按句柄顺序排列,客户端通过句柄或类型访问属性。
4.2 服务与特征的发现
客户端连接后,需要发现服务器提供的服务和特征。发现过程使用 ATT 的 Read By Type Request:
-
发现主要服务:通过 Read By Group Type 请求获取所有服务。
-
发现特征:通过 Read By Type 请求获取服务中的特征。
-
发现描述符:通过 Find Information 请求获取特征的描述符。
发现完成后,客户端可以通过句柄直接读写特征值。
4.3 通知与指示
通知(Notify)和指示(Indicate)是服务器主动向客户端推送数据的方式:
-
通知:服务器发送属性值,客户端不需要确认。适合不需要可靠传输的场景(如传感器数据)。
-
指示:服务器发送属性值,客户端需要回复确认。适合需要可靠传输的场景。
客户端通过写入 CCCD(Client Characteristic Configuration Descriptor)来启用通知或指示。
4.4 UUID
UUID(通用唯一标识符)用于标识服务、特征和描述符。BLE 使用两种 UUID:
-
16 位 UUID:蓝牙 SIG 定义的标准服务和特征,如电池服务(0x180F)。
-
128 位 UUID:厂商自定义的服务和特征,保证全局唯一。
16 位 UUID 是 128 位 UUID 的简写,格式为 0000XXXX-0000-1000-8000-00805F9B34FB。
4.5 ATT MTU 与数据传输
ATT 的最大传输单元(MTU)决定了一次 ATT 操作能传输的最大数据量。默认 MTU 为 23 字节(1 字节操作码 + 20 字节数据)。连接后双方可以协商更大的 MTU,最大可达 247 字节(蓝牙 4.2+)。
增大 MTU 可以减少分包次数,提高数据传输效率。但 MTU 越大,单个数据包的传输时间越长,可能影响延迟。实际应用中需要根据数据大小和延迟要求选择合适的 MTU。
4.6 GATT 服务示例
以电池服务为例,GATT 层次结构如下:
电池服务(UUID: 0x180F) └── 电池电量特征(UUID: 0x2A19) ├── 值(0-100,表示电量百分比) └── CCCD 描述符(启用通知)
客户端连接后,通过发现服务获取电池服务的句柄,然后读取电池电量特征值,或启用通知以在电量变化时接收推送。
4.7 标准服务与自定义服务
蓝牙 SIG 定义了大量标准服务,覆盖常见应用场景:
-
设备信息服务(0x180A):厂商名称、型号、序列号等。
-
电池服务(0x180F):电池电量。
-
心率服务(0x180D):心率数据。
-
血压服务(0x1810):血压数据。
-
环境传感服务(0x181A):温度、湿度等环境数据。
对于标准服务未覆盖的场景,厂商可以定义自定义服务,使用 128 位 UUID。自定义服务的 UUID 应随机生成,避免与其他厂商冲突。
五、SMP 配对与安全
5.1 配对方法
BLE 根据设备的输入输出能力选择配对方法:
-
Just Works:无输入输出,使用固定 PIN 码(000000)。安全性最低,适合无交互设备。
-
Passkey Entry:一端显示 6 位数字,另一端输入。适合有显示屏和键盘的设备。
-
Numeric Comparison:两端显示相同的 6 位数字,用户确认是否一致。适合有显示屏的设备。
-
Out of Band(OOB):通过其他信道(如 NFC)交换密钥。安全性最高。
5.2 LE Secure Connections
蓝牙 4.2 引入 LE Secure Connections,使用 ECDH(椭圆曲线 Diffie-Hellman)密钥交换,防止中间人攻击。配对流程:
-
双方交换公钥。
-
双方计算共享密钥。
-
双方根据配对方法生成确认值。
-
双方交换确认值并验证。
-
生成长期密钥(LTK)。
LE Secure Connections 提供前向保密(Forward Secrecy),即使 LTK 泄露,历史通信内容也无法解密。
5.3 密钥分发
配对完成后,双方分发以下密钥:
-
LTK(Long Term Key):用于链路加密。
-
IRK(Identity Resolving Key):用于解析私有地址。
-
CSRK(Connection Signature Resolving Key):用于数据签名。
-
EDIV(Encrypted Diversifier)和 Rand:用于 LTK 的标识。
这些密钥存储在双方的安全存储中,用于后续重连时快速加密。
5.4 私有地址
为防止设备被跟踪,BLE 支持私有地址(Private Address):
-
静态私有地址:设备启动时随机生成,重启后变化。
-
可解析私有地址:使用 IRK 生成,可以被配对的设备解析。
私有地址定期变化(默认 15 分钟),防止攻击者通过地址跟踪设备。
5.5 加密与签名
配对完成后,链路使用 AES-CCM 加密,提供机密性和完整性。加密密钥在配对时生成,存储在双方的安全存储中。
BLE 还支持数据签名(Signed Write),允许在未加密的链路上发送经过签名的写入命令。签名使用 CSRK 生成,接收方验证签名后执行写入。
5.6 安全最佳实践
在 BLE 应用中,应遵循以下安全最佳实践:
-
使用 LE Secure Connections:启用安全配对,防止中间人攻击。
-
加密关键特征:敏感特征(如密码、密钥)应要求加密后才能访问。
-
限制广播数据:不要在广播中包含敏感信息。
-
使用私有地址:启用可解析私有地址,防止被跟踪。
-
安全存储密钥:配对密钥应存储在安全区域(如硬件加密区)。
-
定期更换密钥:在某些场景下,定期重新配对可以降低密钥泄露的风险。
六、计费与业务模型
6.1 BLE 本身的计费
BLE 技术本身是开放标准,不需要支付专利费(蓝牙技术联盟成员可免费用)。但使用 BLE 需要:
-
蓝牙认证:产品需要通过蓝牙认证(BQB),认证费用数千美元,确保互操作性。
-
硬件成本:BLE 芯片的成本,从几毛钱到几十元不等。
-
开发成本:BLE 协议栈的开发和集成成本。
6.2 蓝牙认证(BQB)
蓝牙认证(Bluetooth Qualification)是使用蓝牙技术的产品必须通过的认证。认证包括:
-
测试:产品需要通过蓝牙规范的一致性测试。
-
注册:向蓝牙技术联盟注册产品,分配 DIDS(Declaration ID)。
-
费用:会员免费,非会员约 8000 美元起。
BQB 认证确保不同厂商的 BLE 设备可以互操作。未认证的产品使用蓝牙标志可能面临法律风险。
6.3 业务模型
BLE 支持多种业务模型:
-
设备销售:销售带 BLE 的硬件设备,如传感器、可穿戴。
-
数据服务:设备采集数据上传云端,按数据量或订阅收费。
-
生态平台:提供 BLE 设备接入的云平台,按设备数或消息量收费。
-
定位服务:基于 BLE Beacon 的室内定位,按定位次数或面积收费。
6.4 功耗与成本
BLE 的低功耗特性直接影响电池成本和用户体验:
-
电池寿命:低功耗意味着电池寿命更长,减少更换电池的成本和不便。
-
电池容量:可以使用更小的电池,降低设备体积和成本。
-
充电频率:减少充电频率,提升用户体验。
对于大批量的物联网设备,BLE 的低功耗可以显著降低电池和维护成本。
七、架构设计与关键机制
7.1 单芯片与双芯片架构
BLE 协议栈有两种实现架构:
-
单芯片(SoC):控制器和主机集成在一个芯片上,如 nRF52、ESP32。成本低,功耗低,适合简单应用。
-
双芯片:控制器和主机分离,主机运行在 MCU 上,通过 HCI 连接控制器。灵活但成本高,适合需要复杂应用的场景。
大多数物联网设备使用单芯片方案,将 BLE 协议栈和应用程序运行在同一个 MCU 上。
7.2 连接状态机
BLE 连接的状态机管理连接的建立、维持和断开:
-
广播:外设发送广播。
-
扫描:中央扫描广播。
-
发起:中央发送连接请求。
-
连接:双方建立连接,开始通信。
-
更新连接参数:协商连接间隔、延迟、超时。
-
断开:任一方可以断开连接。
连接参数可以在连接后更新,以适应不同的应用场景(如低功耗 vs 高吞吐)。
7.3 多连接管理
中央设备可以同时连接多个外设(典型值 3-8 个)。多连接管理需要:
-
时间调度:为每个连接分配连接事件,避免冲突。
-
跳频协调:每个连接使用不同的跳频序列,避免干扰。
-
缓冲区管理:为每个连接分配独立的收发缓冲区。
外设通常只连接一个中央,但蓝牙 5 支持多角色(Multi-Role),设备可以同时是中央和外设。
7.4 数据传输优化
BLE 的数据传输可以通过以下方式优化:
-
增大 MTU:增大 ATT MTU(默认 23 字节),减少分包次数。蓝牙 4.2 支持最大 247 字节。
-
增大连接事件:在一个连接事件中发送多个数据包,提高吞吐量。
-
使用 2 Mbps PHY:蓝牙 5 的 2 Mbps 物理层,吞吐量加倍。
-
减少连接间隔:减小连接间隔,降低延迟,但增加功耗。
7.5 低功耗模式
BLE 设备的低功耗通过以下机制实现:
-
广播间隔:增大广播间隔,减少射频活动。
-
连接间隔:增大连接间隔,减少连接事件频率。
-
从设备延迟:允许从设备跳过连接事件。
-
深度睡眠:不活动时进入深度睡眠,只保留 RTC 运行。
在连接状态下,从设备可以在连接事件之间进入睡眠,只在下一个连接事件前唤醒。
7.6 广播功率与距离
BLE 的传输距离与发射功率和接收灵敏度有关。常见的功率等级:
-
+8 dBm:长距离,约 100 米视距。
-
0 dBm:标准,约 10-30 米。
-
-20 dBm:近场,约 1 米。
蓝牙 5 的 Coded PHY 通过前向纠错(FEC)提高接收灵敏度,可以在相同功率下实现 4 倍的距离。但 Coded PHY 的吞吐量较低(125 Kbps 或 500 Kbps),适合长距离低速率场景。
7.7 吞吐量与延迟
BLE 的吞吐量和延迟受多种因素影响:
-
连接间隔:间隔越小,延迟越低,吞吐量越高,但功耗越大。
-
从设备延迟:延迟越大,从设备可以跳过更多连接事件,功耗越低,但延迟增加。
-
MTU:MTU 越大,每次传输的数据越多,吞吐量越高。
-
PHY 速率:2 Mbps PHY 的吞吐量是 1 Mbps 的两倍。
-
数据包数量:每个连接事件可以发送多个数据包,提高吞吐量。
实际应用中,需要在吞吐量、延迟和功耗之间取得平衡。
7.8 错误处理与重连
BLE 连接可能因干扰、距离过远等原因断开。应用需要处理断开事件并尝试重连:
-
短断开:监管超时内重新连接,可以恢复加密状态。
-
长断开:超过监管超时,需要重新配对或使用存储的密钥加密。
重连时,双方可以使用配对时存储的 LTK 快速加密,无需重新配对。这提高了重连速度和用户体验。
八、代码实现(改写版)
8.1 GATT 服务与特征定义
/* ble_gatt.h - BLE GATT 服务定义(改写版,参考 Zephyr BLE 和 Nordic SoftDevice) */
#ifndef BLE_GATT_H
#define BLE_GATT_H
#include <stdint.h>
/* UUID 类型 */
#define BLE_UUID_TYPE_16 0
#define BLE_UUID_TYPE_128 1
/* 16 位标准 UUID */
#define BLE_UUID_BATTERY_SERVICE 0x180F
#define BLE_UUID_BATTERY_LEVEL 0x2A19
#define BLE_UUID_DEVICE_INFORMATION 0x180A
#define BLE_UUID_MANUFACTURER_NAME 0x2A29
/* 属性权限 */
#define BLE_PERM_READ (1 << 0)
#define BLE_PERM_WRITE (1 << 1)
#define BLE_PERM_NOTIFY (1 << 2)
#define BLE_PERM_INDICATE (1 << 3)
/* GATT 属性 */
struct ble_gatt_attr {
uint16_t handle;
uint8_t uuid_type;
uint8_t uuid[16];
uint16_t permissions;
uint8_t *value;
uint16_t value_len;
uint16_t value_max_len;
};
/* GATT 特征 */
struct ble_gatt_char {
struct ble_gatt_attr value_attr;
struct ble_gatt_attr cccd_attr; /* 客户端特性配置描述符 */
uint8_t props; /* 特征属性(读/写/通知/指示) */
};
/* GATT 服务 */
struct ble_gatt_service {
uint16_t start_handle;
uint16_t end_handle;
uint8_t uuid_type;
uint8_t uuid[16];
struct ble_gatt_char *chars;
uint8_t char_count;
};
/* 初始化 GATT 服务 */
int ble_gatt_service_init(struct ble_gatt_service *svc);
/* 读取特征值 */
int ble_gatt_char_read(struct ble_gatt_service *svc, uint16_t handle,
uint8_t *buf, uint16_t *len);
/* 写入特征值 */
int ble_gatt_char_write(struct ble_gatt_service *svc, uint16_t handle,
const uint8_t *data, uint16_t len);
/* 发送通知 */
int ble_gatt_char_notify(struct ble_gatt_service *svc, uint16_t conn_handle,
uint16_t value_handle, const uint8_t *data, uint16_t len);
#endif /* BLE_GATT_H */
8.2 GAP 广播配置
/* ble_gap.c - BLE GAP 广播配置(改写版) */
#include "ble_gap.h"
#include <string.h>
/* 设置广播数据 */
int ble_gap_set_advertising_data(const char *name, uint16_t service_uuid)
{
uint8_t adv_data[31];
uint8_t idx = 0;
/* Flags */
adv_data[idx++] = 2; /* 长度 */
adv_data[idx++] = 0x01; /* 类型:Flags */
adv_data[idx++] = 0x06; /* 通用可发现 + 不支持 BR/EDR */
/* 16 位服务 UUID */
adv_data[idx++] = 3; /* 长度 */
adv_data[idx++] = 0x03; /* 类型:完整 16 位服务 UUID */
adv_data[idx++] = service_uuid & 0xFF;
adv_data[idx++] = (service_uuid >> 8) & 0xFF;
/* 设备名称 */
uint8_t name_len = strlen(name);
if (name_len > 0 && idx + name_len + 2 <= 31) {
adv_data[idx++] = name_len + 1; /* 长度 */
adv_data[idx++] = 0x09; /* 类型:完整名称 */
memcpy(&adv_data[idx], name, name_len);
idx += name_len;
}
/* 设置广播参数:100 ms 间隔,可连接非定向广播 */
struct ble_adv_params params = {
.interval_min = 160, /* 100 ms */
.interval_max = 200, /* 125 ms */
.type = BLE_ADV_TYPE_IND,
};
/* ble_gap_adv_set_data(adv_data, idx); */
/* ble_gap_adv_start(¶ms); */
return 0;
}
/* 设置扫描响应数据 */
int ble_gap_set_scan_response_data(const char *manuf_data, uint8_t len)
{
uint8_t sr_data[31];
uint8_t idx = 0;
/* 厂商数据 */
if (len > 0 && len + 3 <= 31) {
sr_data[idx++] = len + 2; /* 长度 */
sr_data[idx++] = 0xFF; /* 类型:厂商数据 */
sr_data[idx++] = 0x00; /* 厂商 ID 低字节 */
sr_data[idx++] = 0x00; /* 厂商 ID 高字节 */
memcpy(&sr_data[idx], manuf_data, len);
idx += len;
}
/* ble_gap_scan_rsp_set_data(sr_data, idx); */
return 0;
}
8.3 连接参数与功耗管理
/* ble_conn.c - BLE 连接管理(改写版) */
#include "ble_conn.h"
/* 连接参数 */
struct ble_conn_params {
uint16_t min_conn_interval; /* 最小连接间隔(单位 1.25 ms) */
uint16_t max_conn_interval; /* 最大连接间隔 */
uint16_t slave_latency; /* 从设备延迟 */
uint16_t supervision_timeout; /* 监管超时(单位 10 ms) */
};
/* 低功耗连接参数:连接间隔 1 秒,从设备延迟 4 */
static const struct ble_conn_params low_power_params = {
.min_conn_interval = 800, /* 1000 ms */
.max_conn_interval = 800, /* 1000 ms */
.slave_latency = 4,
.supervision_timeout = 400, /* 4000 ms */
};
/* 高吞吐连接参数:连接间隔 15 ms */
static const struct ble_conn_params high_throughput_params = {
.min_conn_interval = 12, /* 15 ms */
.max_conn_interval = 12, /* 15 ms */
.slave_latency = 0,
.supervision_timeout = 200, /* 2000 ms */
};
/* 更新连接参数 */
int ble_conn_update_params(uint16_t conn_handle,
const struct ble_conn_params *params)
{
/* 发送 L2CAP 连接参数更新请求 */
/* ble_l2cap_conn_param_update_req(conn_handle, params); */
return 0;
}
/* 根据应用场景选择连接参数 */
const struct ble_conn_params *ble_conn_select_params(bool low_power)
{
return low_power ? &low_power_params : &high_throughput_params;
}
九、Linux 平台 BLE 实践
9.1 BlueZ 协议栈
BlueZ 是 Linux 官方蓝牙协议栈,支持经典蓝牙和 BLE。BlueZ 提供了命令行工具和 D-Bus API:
-
bluetoothctl:交互式命令行工具,用于扫描、连接、配对。
-
hciconfig:配置蓝牙控制器。
-
hcitool:低层次 HCI 工具(已过时,被 bluetoothctl 替代)。
-
btmon:蓝牙监控工具,抓取 HCI 数据包。
-
D-Bus API:应用通过 D-Bus 访问 BlueZ 的功能。
BlueZ 的 BLE 实现包括:
-
GATT 服务器:通过 D-Bus 注册 GATT 服务。
-
GATT 客户端:通过 D-Bus 发现和访问远程 GATT 服务。
-
广播/扫描:通过 D-Bus 启动广播或扫描。
-
配对管理:通过 D-Bus 处理配对和密钥。
9.2 Linux BLE 编程
Linux 上开发 BLE 应用有多种方式:
-
D-Bus API:直接调用 BlueZ 的 D-Bus 接口,适合复杂应用。
-
bluetoothctl 脚本:通过命令行脚本控制蓝牙,适合简单应用。
-
第三方库:如 bluepy(Python)、Bleak(Python 跨平台)、SimpleBLE(C++)。
Python 是 Linux 上 BLE 开发的常用语言,因为有成熟的库和快速的开发周期。
BlueZ D-Bus 接口示例
BlueZ 的 D-Bus 接口提供了丰富的 BLE 功能。以下是使用 D-Bus 连接 BLE 设备并读取特征的伪代码:
1. 启动蓝牙适配器:org.bluez.Adapter1.StartDiscovery() 2. 发现设备后获取设备路径:org.bluez.Device1 3. 连接设备:Device1.Connect() 4. 发现服务:等待 ServicesResolved 属性变化 5. 遍历服务和特征:org.bluez.GattService1, GattCharacteristic1 6. 读取特征:GattCharacteristic1.ReadValue() 7. 启用通知:GattCharacteristic1.StartNotify() 8. 接收通知:监听 PropertiesChanged 信号
D-Bus 接口的优势是与语言无关,任何支持 D-Bus 的语言都可以使用。
9.3 Linux BLE 调试
-
btmon:抓取 HCI 数据包,分析 BLE 通信。
-
bluetoothctl:查看设备状态、连接、配对信息。
-
hcidump:旧版 HCI 抓包工具。
-
Wireshark:通过 btmon 导出的数据包分析。
十、Android 平台 BLE 实践
10.1 Android BLE 架构
Android 的 BLE 功能通过 android.bluetooth 包提供,核心类包括:
-
BluetoothAdapter:蓝牙适配器,管理蓝牙开关和扫描。
-
BluetoothDevice:远程蓝牙设备。
-
BluetoothGatt:GATT 客户端,访问远程 GATT 服务。
-
BluetoothGattServer:GATT 服务器,提供 GATT 服务。
-
BluetoothGattCallback:GATT 事件回调。
Android 的 BLE API 是异步的,所有操作通过回调返回结果。
10.2 Android BLE 扫描
Android 提供两种扫描方式:
-
startDiscovery():经典蓝牙扫描,也能发现 BLE 设备,但效率低。
-
BluetoothLeScanner.startScan():BLE 专用扫描,支持扫描过滤(按 UUID、MAC 地址、RSSI)。
Android 8.0 引入了未授权扫描限制,后台扫描频率受限。Android 12 要求 BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 权限。
10.3 Android BLE 连接与通信
Android 连接 BLE 设备的流程:
-
扫描发现设备。
-
调用
device.connectGatt()连接。 -
在
BluetoothGattCallback.onConnectionStateChange中处理连接结果。 -
连接成功后调用
gatt.discoverServices()发现服务。 -
通过
gatt.readCharacteristic()和gatt.writeCharacteristic()读写特征。 -
通过
gatt.setCharacteristicNotification()启用通知。
10.4 Android BLE 功耗与兼容性
Android 设备的 BLE 实现差异较大,不同厂商的 ROM 可能有兼容性问题。常见问题包括:
-
后台扫描限制:Android 8+ 限制后台扫描频率。
-
连接超时:部分设备连接超时时间较短。
-
MTU 协商:部分设备不支持 MTU 协商。
-
GATT 缓存:GATT 服务变更后缓存未更新。
为了兼容性,建议在应用层做容错处理,如重试连接、刷新 GATT 缓存。
10.5 Android BLE 开发注意事项
Android BLE 开发有一些需要注意的坑:
-
主线程操作:BLE 操作不应在主线程执行,避免 ANR。建议使用专用线程或协程。
-
连接超时:Android 没有提供连接超时设置,需要自己实现定时器。
-
GATT 操作串行化:GATT 操作(读、写、通知)需要串行执行,不能并发。建议使用队列管理 GATT 操作。
-
及时关闭:使用完 BluetoothGatt 后调用 close(),否则会泄漏资源。
-
权限处理:Android 12+ 需要运行时申请 BLUETOOTH_SCAN、BLUETOOTH_CONNECT 权限。
10.6 Android GATT 服务器
Android 也可以作为 GATT 服务器,提供自定义服务。通过 BluetoothGattServer.openGattServer() 创建服务器,注册服务和特征,通过 BluetoothGattServerCallback 处理客户端请求。
GATT 服务器常用于手机与手机、手机与设备的双向通信,或者手机作为网关转发数据。
十一、ESP/嵌入式平台 BLE 实践
11.1 ESP-IDF 的 BLE
ESP32 系列芯片支持 BLE 和经典蓝牙,ESP-IDF 提供了完整的 BLE 协议栈。ESP-IDF 的 BLE 基于 Bluedroid(Android 的蓝牙协议栈),但经过裁剪和优化。
ESP-IDF 的 BLE API 包括:
-
esp_ble_gap_* :GAP 相关 API(广播、扫描、连接)。
-
esp_ble_gatts_* :GATT 服务器 API。
-
esp_ble_gattc_* :GATT 客户端 API。
-
esp_ble_smp_* :安全管理 API。
ESP32 还支持 NimBLE,这是一个更轻量的 BLE 协议栈,RAM 占用比 Bluedroid 小得多,适合资源受限的应用。
11.2 Zephyr 的 BLE
Zephyr RTOS 内置了完整的 BLE 协议栈,支持控制器和主机。Zephyr 的 BLE 实现是开源的,代码结构清晰,易于定制。
Zephyr 的 BLE API 基于回调机制:
-
bt_le_adv_start():启动广播。
-
bt_conn_create_le():发起连接。
-
GATT 服务定义:通过
BT_GATT_SERVICE_DEFINE宏定义服务和特征。 -
GATT 回调:通过
bt_gatt_read_func_t、bt_gatt_write_func_t等回调处理读写。
Zephyr 的 BLE 支持单芯片和 HCI 模式,可以使用 Zephyr 自带的控制器或外部控制器。
11.3 Nordic SoftDevice
Nordic Semiconductor 的 nRF5 系列芯片是 BLE 应用的主流选择。Nordic 提供 SoftDevice,一个预编译的 BLE 协议栈库,应用层通过 API 调用。
SoftDevice 的优势是成熟稳定、通过蓝牙认证、功耗低。劣势是闭源,无法修改协议栈内部。Nordic 也提供了开源的 nRF Connect SDK,基于 Zephyr,可以使用开源协议栈。
11.4 嵌入式 BLE 功耗优化
嵌入式 BLE 设备的功耗优化是核心工作。以下是常用的优化技巧:
-
广播优化:增大广播间隔(如 1-2 秒),减少广播频率。使用定向广播快速重连。
-
连接参数优化:根据数据传输需求选择连接间隔。低频率数据使用大间隔(1-4 秒),高频率数据使用小间隔(15-30 毫秒)。
-
从设备延迟:在低延迟要求不高的场景,增大从设备延迟,减少射频活动。
-
关闭不需要的功能:关闭经典蓝牙、LE Secure Connections(如果不需要)等功能,节省 Flash 和 RAM。
-
使用低功耗时钟:在睡眠时使用 32.768 kHz 低频时钟,降低功耗。
通过合理优化,BLE 设备的平均电流可以降到微安级别,纽扣电池可以使用数年。
11.5 嵌入式 BLE 与 WiFi 共存
许多嵌入式设备同时使用 BLE 和 WiFi(如 ESP32)。两者都工作在 2.4 GHz 频段,可能相互干扰。共存机制包括:
-
时分复用:BLE 和 WiFi 分时使用射频,避免同时传输。
-
信道协调:WiFi 避开 BLE 使用的信道。
-
优先级管理:根据数据类型设置优先级(如 BLE 音频优先于 WiFi 数据)。
ESP32 实现了硬件级的 BLE/WiFi 共存,通过软件调度保证两者都能正常工作。
十二、多平台对比与选型建议
12.1 各平台 BLE 协议栈对比
| 维度 | BlueZ (Linux) | Android BLE | ESP-IDF | Zephyr BLE | Nordic SoftDevice |
|---|---|---|---|---|---|
| 开源 | 是 | 部分开源 | 部分开源 | 是 | 否 |
| RAM 占用 | 高(MB 级) | 高(MB 级) | 中(几十 KB) | 低(十几 KB) | 低(几 KB) |
| 功能完整度 | 高 | 高 | 中 | 高 | 高 |
| 功耗优化 | 一般 | 一般 | 好 | 好 | 极好 |
| 开发难度 | 中 | 低 | 中 | 中 | 低 |
| 认证状态 | 认证 | 认证 | 认证 | 部分认证 | 认证 |
12.2 选型建议
-
Linux 网关/服务器:使用 BlueZ,功能完整,D-Bus API 灵活。
-
Android 应用:使用系统 BLE API,兼容性好,开发简单。
-
嵌入式设备:使用 ESP-IDF 或 Zephyr,根据芯片选择。
-
低功耗设备:优先考虑 Nordic SoftDevice,功耗最优。
-
需要定制协议栈:使用 Zephyr 开源协议栈,可以修改内部实现。
12.3 BLE 与其他无线技术的对比
| 维度 | BLE | WiFi | Zigbee | LoRa |
|---|---|---|---|---|
| 功耗 | 极低 | 高 | 低 | 极低 |
| 距离 | 10-100m | 10-100m | 10-100m | 2-15km |
| 吞吐 | 125K-2M | 1-100M | 20-250K | 0.3-50K |
| 网络拓扑 | 星型/Mesh | 星型 | Mesh | 星型 |
| 典型应用 | 可穿戴/传感器 | 高吞吐数据 | 智能家居 | 远程传感 |
十三、发展历程与未来趋势
13.1 BLE 的发展阶段
BLE 的发展经历了四个阶段:
第一阶段(2010-2013):基础能力。蓝牙 4.0 引入 BLE,支持基础的广播、连接、GATT。主要用于简单的传感器和遥控器。
第二阶段(2014-2016):性能提升。蓝牙 4.2 引入数据包长度扩展和隐私保护。BLE 的吞吐量和安全性提升,开始用于更复杂的应用。
第三阶段(2016-2020):功能扩展。蓝牙 5 引入 2 Mbps、长距离、广播扩展。BLE Audio(蓝牙 5.2)支持低延迟音频,开始挑战经典蓝牙在音频领域的地位。
第四阶段(2020-至今):大规模部署。蓝牙 5.3/5.4 优化连接建立和广播,支持大规模设备配置。BLE Mesh 支持智能家居和工业物联网的大规模网络。
13.2 BLE Audio 的影响
BLE Audio 是 BLE 发展的重要里程碑,它使用 LE Isochronous Channels 传输音频,支持低延迟和多设备连接。BLE Audio 将逐步替代经典蓝牙在耳机和音箱中的应用,因为它功耗更低、功能更丰富(如空间音频、多设备共享)。
13.3 BLE Mesh
BLE Mesh 是蓝牙技术联盟于 2017 年发布的网状网络规范,允许大量 BLE 设备组成自组织网络。BLE Mesh 基于泛洪(Flooding)算法,不依赖路由,适合智能家居和工业自动化等需要大规模设备互联的场景。
13.4 未来趋势
-
BLE Audio 普及:BLE Audio 将成为耳机、助听器等音频设备的标准。
-
室内定位:蓝牙 5.1 的寻向功能支持厘米级定位,将在商场、机场等场所普及。
-
Mesh 网络:BLE Mesh 将在智能家居和工业物联网中大规模部署。
-
更低功耗:新的低功耗技术将进一步延长电池寿命。
-
更高安全:持续增强配对和加密机制,防止攻击。
13.5 总结
BLE 是物联网领域最重要的无线通信技术之一,通过极低的功耗实现了短距离通信。从 2010 年蓝牙 4.0 发布至今,BLE 持续演进,从简单的传感器通信扩展到音频、定位、Mesh 网络等复杂应用。
理解 BLE 的协议分层(Controller + Host + Application)、核心协议(GAP/GATT/ATT/SMP)和低功耗设计,是用好 BLE 的基础。不同平台有不同的实现(BlueZ、Android BLE、ESP-IDF、Zephyr、SoftDevice),但核心协议一致,开发者可以根据应用场景选择合适的平台。
BLE 的未来将更加注重低功耗、高可靠和大规模部署,为物联网的普及提供坚实的通信基础。
13.6 BLE 与其他无线技术的协作
在实际应用中,BLE 通常与其他无线技术协作,各取所长:
-
BLE + WiFi:BLE 用于低功耗控制和传感器数据,WiFi 用于高吞吐数据传输(如固件升级、视频流)。
-
BLE + 蜂窝网络:BLE 用于设备间通信,蜂窝网络用于云端连接。
-
BLE + NFC:NFC 用于快速配对(OOB),BLE 用于后续通信。
-
BLE + UWB:BLE 用于设备发现和连接,UWB 用于精确测距和定位。
这种多模协作可以根据场景动态选择最优的通信方式,平衡功耗、吞吐和距离。
13.7 BLE 在各行业的应用
BLE 已广泛应用于各行各业:
-
消费电子:耳机、手表、手环、智能家居。
-
医疗健康:血糖仪、心率带、体温计、远程监护。
-
工业物联网:资产追踪、环境监测、设备诊断。
-
汽车:无钥匙进入、胎压监测、车载诊断。
-
零售:Beacon 营销、电子价签、库存管理。
-
体育健身:运动追踪、健身器材连接。
BLE 的低功耗和低成本使其成为物联网设备的首选无线技术。
更多推荐

所有评论(0)