BLE 协议栈与低功耗蓝牙

本文系统讲解 BLE 协议栈与低功耗蓝牙的工程落地,回答 GAP 与 GATT 怎么分工、连接参数如何影响功耗、广播报文怎么设计、配对绑定怎么选、BLE Mesh 与 Thread 怎么取舍等实战问题。覆盖 Controller 与 Host 分层、连接事件与功耗公式、ATT 与 GATT 数据模型、LE Secure Connections、手机侧兼容性,附权衡取舍与常见坑清单。

引言

BLE(Bluetooth Low Energy,蓝牙低功耗)是物联网里覆盖最广的短距无线:手环、体脂秤、电子价签、门锁、传感器标签、以及几乎所有带电池的消费设备都在用。它的优势不是速率也不是距离,而是「手机天然支持」——iOS 和 Android 都内置协议栈,设备不需要网关、不需要配网路由,掏手机就能连。这一条决定了 BLE 在「配网通道」和「人机交互」两个场景里几乎无可替代。

但 BLE 也是被误解最多的协议。很多人以为它「简单、省电」,实际上一不留神就会踩坑:连接参数设错导致功耗翻十倍;广播报文塞不下数据;MTU 协商不当让传输慢得离谱;配对方式选错导致安全形同虚设。这些问题的共同原因是没理解 BLE 的分层结构——GAP 管广播与连接,GATT 管数据,两者职责完全不同,参数也各管各的。

本文聚焦短距场景,与广域低功耗网络的分工见 LoRa 与 NB-IoT 低功耗广域网 :那篇讲的是几公里外、每天几十字节的广域链路,本文讲的是十米内、手机直连的短距链路,两者在功耗模型和协议栈上几乎没有重叠。BLE 作为配网通道在智能家居组网里的角色不在本文展开。

目录

  1. BLE 在物联网里的定位
  2. 协议栈分层:Controller 与 Host
  3. GAP:广播与设备角色
  4. 广播报文结构与扩展广播
  5. 连接参数与连接事件
  6. ATT 与 GATT 数据模型
  7. 服务、特征与描述符设计
  8. 配对、绑定与安全管理器
  9. 功耗优化与实测
  10. BLE Mesh 概览
  11. 手机侧交互与兼容性
  12. 工具链与调试
  13. 权衡取舍
  14. 常见坑清单
  15. 小结

1. BLE 在物联网里的定位

BLE 属于 WPAN(无线个域网),工作在 2.4GHz ISM 频段,共 40 个信道,其中 3 个是广播信道(37、38、39),37 个是数据信道。它和经典蓝牙(BR/EDR)共用频段但协议不同,双模芯片两者都支持,单模 BLE 芯片只跑低功耗部分。

维度BLEWi-FiThreadLoRa
频段2.4GHz2.4/5GHz2.4GHzSub-GHz
速率1 到 2 Mbps数十 Mbps250 kbps0.3 到 50 kbps
距离10 到 100 m30 到 100 m10 到 100 m2 到 15 km
手机直连原生支持需配网需边界路由器不支持
典型功耗极低高极低极低
适合手机交互、配网、可穿戴高带宽、常供电网状组网广域低频上报

BLE 的独特价值是「手机原生支持」:控制器不用自建网关,也不用装 App 之外的硬件。这让它在两个场景里胜出:一是配网通道(Matter 的 commissioning 就走 BLE),二是人机交互(配置、诊断、OTA 触发)。纯粹的多点组网和长距离传输,BLE 不如 Thread 和 LoRa。

BLE 的速率也不是线性可用的:1 Mbps 是物理层速率,实际有效吞吐受连接间隔、MTU、每个连接事件的包数限制,实际能到 100 到 700 kbps 就不错。传大文件(固件升级)时这一点尤其明显。

2. 协议栈分层:Controller 与 Host

BLE 协议栈在工程上分成两半,理解这个分层是排查问题的前提。

层归属职责
物理层 PHYController调制解调、信道选择、GFSK
链路层 LLController广播、连接、跳频、CRC、加密
HCI中间接口Host 与 Controller 的命令与事件
L2CAPHost逻辑信道、分段重组、固定信道
ATT / GATTHost属性协议与数据模型
SMPHost配对与密钥分发
GAPHost角色、广播、连接管理

Controller 通常由芯片厂商固化(如 Nordic SoftDevice、ESP32 的蓝牙控制器),Host 可以是开源实现(Zephyr 的 Bluetooth Host、NimBLE、BlueZ、ESP-IDF 的 Bluedroid)。HCI 是两者之间的接口,可以走物理 UART(传统方案)或共享内存(单芯片方案)。排查「连接建立失败」时,如果 HCI 日志显示 Controller 返回错误码,问题在射频或链路层;如果 HCI 正常但应用行为不对,问题在 Host 的 GAP 或 GATT 配置。

选 Host 实现的考量:NimBLE 代码量小、内存占用低(适合 MCU);Bluedroid(ESP-IDF)功能全但占 RAM;BlueZ 是 Linux 侧标准实现,配合 /linux/ 上的 dbus 接口使用,适合网关类设备。Zephyr 的 Host 与它的设备驱动、电源管理集成得最好,是 nRF 系列的首选。

3. GAP:广播与设备角色

GAP(Generic Access Profile)定义设备如何被发现、如何建立连接,以及设备的四种角色。

角色行为典型设备
Broadcaster只广播,不连接信标、温度标签
Observer只扫描,不连接手机扫描器
Peripheral可被连接手环、传感器
Central发起连接手机、网关

外设(Peripheral)通过广播宣告自己存在,中心设备(Central)扫描到后发起连接。一个设备可以同时扮演多个角色(如既广播又扫描),但角色决定了两端的行为模型:外设不能主动连中心设备,只能等被连。

广播有几种类型,选错会导致连不上或被发现不了:

广播类型可连接可扫描用途
ADV_IND是是通用可连接广播
ADV_DIRECT_IND是否定向快速连接
ADV_NONCONN_IND否否纯信标,只发不收
ADV_SCAN_IND否是可被扫描但不连接
ADV_EXT_IND视配置视配置BLE 5 扩展广播

广播间隔(Advertising Interval)在 20ms 到 10.24s 之间,默认 100ms 左右。间隔越短越容易被发现、连接越快,但功耗越高。纯信标设备可以把间隔拉到 1 秒甚至更长,用一次电池撑一年;需要快速配网的设备用 20 到 100ms,代价是功耗上升。BLE 5 引入扩展广播(Extended Advertising),把单包从 31 字节扩展到最多 255 字节,且支持周期性广播,适合广播更多数据。

4. 广播报文结构与扩展广播

传统 BLE 广播包载荷只有 31 字节(BLE 5 扩展后单包可到 255 字节),每一段叫一个 AD Structure,格式是「长度(1) + 类型(1) + 数据」。常见类型:

AD 类型值内容
Flags0x01可发现模式、是否支持 BR/EDR
Local Name0x08/0x09设备名(完整/缩短)
16-bit Service UUID0x02/0x03广播支持的服务
Manufacturer Specific0xFF厂商自定义数据
TX Power Level0x0A发射功率,用于测距
Service Data0x16服务关联数据

31 字节很快就不够用:一个设备名 10 字节、Flags 3 字节、几个 UUID 各 2 到 4 字节,再想塞传感器数据就没空间了。工程上的三种应对:一是把设备名缩短,把详情留给 GATT 读取;二是用 Manufacturer Specific Data 塞紧凑的二进制数据(如电量、状态位);三是上 BLE 5 扩展广播。

广播载荷示例(按字节顺序):
02 01 06                       Flags: LE General Discoverable, 不支持 BR/EDR
0B 09 54 65 6D 70 53 65 6E 73 6F 72 31   缩短名 "TempSensor1"(10 字节)
05 16 0A 18 34 12             Service Data: 0x180A 服务, 数据 0x1234
06 FF 4C 00 02 15 AA BB       Manufacturer Specific: 厂商 0x004C, 自定义数据

解析广播时的坑:长度字节包含类型字节本身,所以「长度 = 类型 + 数据」;Flags 不是必须出现,扫描时不能假设它存在;设备名可以是缩短的(0x08),也可能是完整的(0x09),解析逻辑要兼容两者。

5. 连接参数与连接事件

连接建立后,两端按「连接间隔」周期性地交换数据,每一次交换叫一个连接事件(Connection Event)。三个核心参数决定了吞吐与功耗:

参数范围含义
Connection Interval7.5ms 到 4s(步进 1.25ms)两次连接事件的间隔
Slave Latency0 到 499从设备可跳过的连接事件数
Supervision Timeout100ms 到 32s超过此时长未收到包则判定断开

功耗的粗略模型是:

平均电流 ≈ (每个连接事件的收发时间 × 峰值电流) / 连接间隔
          + 休眠电流

设连接间隔 100ms、从机延迟 0、单次事件收发约 1ms、峰值电流 8mA、休眠 1uA:
  平均 ≈ 1ms/100ms × 8mA ≈ 80uA
把从机延迟设为 4(跳过 4 个事件),有效间隔变 500ms:
  平均 ≈ 1ms/500ms × 8mA ≈ 16uA

从机延迟(Slave Latency)是省电的关键杠杆:从设备声明「我可以跳过 N 个连接事件不响应」,只要主设备没有数据要发,从机就继续睡。代价是主设备发数据的延迟变大——从机最多要等 (N+1) 个连接间隔才能收到。所以「主设备要下发命令」的场景(如远程开锁)不能把延迟设太大。

参数协商(Connection Parameter Update)由从设备发起请求,主设备可以接受或拒绝。iOS 对参数有自己的偏好,从设备请求的值经常被改。Supervision Timeout 必须满足规范公式:timeout > (1 + latency) × interval × 2,否则连接会被立即断开,这是最常见的连接参数错误。

6. ATT 与 GATT 数据模型

BLE 的数据传输由两层组成:ATT(Attribute Protocol)是传输协议,GATT(Generic Attribute Profile)是建立在其上的数据模型。很多人把两者混为一谈,其实是「怎么传」和「传什么结构」的区别。

ATT 的操作以「句柄(Handle)」寻址,每个属性有一个 16 位句柄。基本操作有:

ATT 操作方向说明
Read Request/Response客户端读读属性值
Write Request/Response客户端写写属性值并等确认
Write Command客户端写写但不确认(快)
Notification服务端推服务端主动推,不确认
Indication/Confirmation服务端推服务端主动推,要确认
Read By Type / Find Information客户端按类型或范围发现属性

GATT 在 ATT 之上定义三种对象:**服务(Service)**是一组功能的容器,**特征(Characteristic)**是服务里的数据点(有值和属性),**描述符(Descriptor)**是特征的元数据。每个特征至少有两个属性:声明(Declaration,说明属性类型与权限)和值(Value),可选一个 CCCD(Client Characteristic Configuration Descriptor,控制通知/指示开关)。

GATT 层次(以电池服务为例):
Service 0x180F (Battery Service)         Handle 0x0010
  ├── Characteristic Declaration         Handle 0x0011  (属性: Read, Notify)
  ├── Characteristic Value 0x2A19        Handle 0x0012  (电量百分比)
  └── CCCD 0x2902                        Handle 0x0013  (通知开关)

特征属性(Properties)决定了客户端能做什么:Read、Write、Write Without Response、Notify、Indicate。Notify 和 Indicate 的区别是后者要确认、更可靠但更慢,传感器周期上报用 Notify,关键指令用 Indicate。CCCD 是客户端用来打开通知的开关,忘记实现 CCCD 是「设备能连上但收不到推送」的常见原因。

7. 服务、特征与描述符设计

UUID 有两种:16 位(SIG 分配的标准 UUID,如 0x180F 电池、0x180A 设备信息、0x180D 心率)和 128 位(自定义,基于 UUID v4 随机生成)。设计自定义服务时,先查 SIG 有没有现成的标准服务,能用标准就用标准——标准服务能被通用 App 直接识别。

常见标准服务:

服务UUID用途
Generic Access0x1800设备名、外观
Device Information0x180A厂商、型号、固件版本
Battery Service0x180F电量百分比
Heart Rate0x180D心率
HID over GATT0x1812键盘、鼠标

自定义服务的设计原则:一是把「读」和「写」分成不同的特征,不要用一个特征既读又写(语义混乱,权限也难配);二是长数据(如日志、固件块)用「句柄 + 偏移」的分片读取,而不是塞进一个大特征;三是把固件版本、序列号放进 Device Information 服务,让诊断工具能直接读到。

MTU 是传输效率的关键。默认 ATT MTU 是 23 字节(净荷 20 字节),BLE 4.2 起支持 MTU 交换,最大 517 字节(净荷 512)。MTU 越大,同样数据量需要的包越少,吞吐越高。但 MTU 是两端协商的,取双方支持的最小值,Android 常能到 517,iOS 通常 185 左右。写数据时要注意「写长特征」需要「准备写 + 执行写」两步流程,或直接用长写(Long Write)。

7.1 大数据的分片传输

固件块、日志这类超过 MTU 的数据必须分片。标准做法是用两个特征:一个「控制点」特征接收「请求下一块(含偏移与长度)」,一个「数据」特征返回该块内容。客户端循环请求直到传完,服务端按偏移从存储里读。这种「句柄加偏移」的拉取模型比服务端主动推送更好控流——客户端按自己的处理速度请求,不会因为推送过快丢包。分片大小取 MTU - 3(ATT 操作码与句柄占 3 字节),每片都带偏移,客户端据此检测丢片与乱序。

8. 配对、绑定与安全管理器

BLE 的安全由 SMP(Security Manager Protocol)负责,分三个阶段:配对(Pairing,协商密钥)、加密(Encryption,用密钥加密链路)、绑定(Bonding,保存密钥以便下次免配对)。

配对方式有四种,安全性依次不同:

配对方式前提抗中间人说明
Just Works无否最方便,最不安全
Passkey Entry一端有键盘是输入 6 位数字
Numeric Comparison两端有屏是双方比对数字
OOB有带外通道是用 NFC 等传密钥

Just Works 没有中间人防护,任何能收发的设备都能冒充,只适合非敏感数据。带敏感操作(开锁、支付)的设备必须用 Passkey 或 Numeric Comparison。BLE 4.2 引入的 LE Secure Connections 用 ECDH 做密钥交换,比旧版(LE Legacy Pairing)的密钥交换强得多,新设备应强制开启。

绑定(Bonding)会把长期密钥(LTK)存到两端。绑定信息存在 MCU 的 Flash 里,容量有限(通常几十条),绑定表满了要按策略淘汰。隐私(Privacy)特性用可解析私有地址(RPA)防止设备被长期跟踪——设备定期更换地址,只有持有 IRK(Identity Resolving Key)的绑定方能解析。开锁类设备应开启隐私,否则设备地址固定,容易被追踪。

SMP 配对流程(LE Secure Connections):
1. Pairing Request/Response:协商 IO 能力、是否需要绑定、MITM 保护
2. 密钥生成:双方用 ECDH 生成共享密钥,配合随机数派生 LTK
3. 认证(可选):Passkey 或 Numeric Comparison 验证,抵御中间人
4. 密钥分发:交换 IRK(隐私)、CSRK(签名)等
5. 加密启动:用 LTK 加密链路,后续 ATT 操作受保护

9. 功耗优化与实测

BLE 设备的功耗几乎完全由「射频开着的时间占比」决定。三种工作模式的功耗量级差别巨大:

模式电流(典型)说明
广播(100ms 间隔)200 到 500 uA持续广播,可被连接
连接中(100ms 间隔)80 到 150 uA周期性收发
连接中(1s 间隔 + 从机延迟)5 到 20 uA长间隔低频通信
深度睡眠(无射频)0.5 到 2 uA仅 RTC 与唤醒源

优化手段按收益排序:

  1. 拉长连接间隔并加从机延迟:这是最有效的一招,间隔从 100ms 拉到 1s、延迟设 4,功耗能降一个数量级。前提是业务能容忍延迟。
  2. 广播改连接:纯广播设备如果只是周期性发数据,可以改成「周期性广播 + 短连接」或直接用扩展广播的周期性模式,避免一直开着接收窗口。
  3. 减少通知频率:批量上报(攒几个采样发一包)比每条都通知省电。
  4. 关闭未用外设:BLE 芯片的功耗还受其他外设影响,未用的 ADC、传感器要断电,悬空引脚要配成确定电平。
  5. 降低发射功率:近距离场景把 TX Power 从 0dBm 降到 -12dBm,能省不少电,但要用 RSSI 确认链路余量够。

实测时要注意:平均电流要用高精度电流表或库仑计测,普通万用表采样率不够,看不到连接事件的瞬时尖峰;峰值电流用示波器配电流探头,BLE 发射峰值能到 5 到 10mA。

10. BLE Mesh 概览

BLE Mesh 是在 BLE 之上构建的网状网协议(2017 年发布),用于需要多点组网的场景(如智能照明、楼宇控制)。它和「点对点 BLE」是两套东西:

维度点对点 BLEBLE Mesh
拓扑星型(一主一从)网状(多对多)
寻址无(靠连接)元素地址、组地址、虚拟地址
数据模型GATT 服务与特征元素、模型、状态
配网配对绑定Provisioning(PB-ADV / PB-GATT)
中继无支持中继与好友
典型设备手环、传感器灯、开关、楼宇

Mesh 的配网(Provisioning)通过 PB-GATT(手机作为配网器)或 PB-ADV(Mesh 设备互配)完成,配网后设备获得一个单播地址并加入网络。Mesh 用「发布/订阅」模型:设备发布状态到一个地址,订阅该地址的设备都能收到。中继(Relay)节点转发消息扩展覆盖,好友(Friend)节点为低功耗节点缓存消息。

Mesh 与 Thread 的选择:两者都能组网,但 Mesh 跑在 BLE 上、手机能直接配网、生态更偏照明;Thread 原生 IPv6、能与 Matter 和 IP 世界互通。新建智能家居项目倾向 Thread 加 Matter,存量照明和楼宇项目多用 BLE Mesh。

11. 手机侧交互与兼容性

BLE 设备最常见的对端是手机,而 iOS 和 Android 的 BLE 行为差异是兼容性问题的根源。

差异点iOSAndroid
后台扫描严格限制,需声明后台模式较宽松,Android 8 后也有限制
最大 MTU约 185 字节常可到 517 字节
连接数单 App 约 8 到 16 个依机型,常见 7 个
地址使用随机地址也使用随机地址
参数协商强制自己的偏好相对宽松

几个实用建议:一是不要在后台依赖持续扫描,iOS 后台扫描有诸多限制,关键功能要设计成「前台触发」;二是 MTU 不要假设,每次连接后协商再决定分片大小;三是连接数有限,App 同时连多台设备时要排队复用;四是 Android 的 BLE 栈各厂商实现差异大,兼容性测试必须覆盖主流机型。

手机侧的开发在 HarmonyOS 上也有对应的蓝牙 API,如果目标是国内多设备生态,需要同时覆盖 Android、iOS 与鸿蒙三套实现。设备侧的协议设计要尽量简单、少依赖手机侧的高级特性,才能在碎片化的手机环境里稳定工作。

一个常被忽略的点是「连接建立时间」:iOS 从发起连接到服务发现完成通常要 1 到 3 秒,Android 各机型差异更大。如果产品体验要求「秒开」,要把关键信息(如电量、状态)放进广播包,让 App 在连接前就能展示,连接只用于下发命令。这也是很多设备把「广播加连接」组合使用的原因:广播负责快速展示,连接负责交互。

12. 工具链与调试

BLE 调试有一套成熟工具:

btmon                                  # Linux 下抓 HCI 日志,看每条命令与事件
bluetoothctl                           # 交互式扫描、连接、GATT 读写
hcitool lescan                         # 扫描 BLE 设备(旧工具,仍可用)
gatttool -b AA:BB:CC:DD:EE:FF --primary   # 列出主服务

移动端用 nRF Connect(Nordic 官方,可扫描、连接、读写、看广播解析),是现场排查的首选。它能把广播包按 AD 类型逐段解析,直接看到 Flags、设备名、厂商数据,是判断「广播设计是否合理」的最快方式。抓包用 Ellisys、Frontline 或 Nordic Sniffer,Wireshark 能完整解析 BLE 链路层到 GATT 的报文,是分析连接失败、配对失败、通知丢失的终极手段。抓包前要确认嗅探器与目标设备的信道跟随设置正确,否则会漏掉跳频后的数据信道报文。

排查思路:连不上先看广播是否发出(nRF Connect 能否扫到),再看连接参数是否被拒绝;连上后读写失败看 GATT 权限与 CCCD;收不到通知先确认 CCCD 已打开,再看服务端是否真的调用了通知 API。HCI 日志(btmon)能区分「协议栈问题」和「应用问题」,是第一步该看的。

13. 权衡取舍

决策点方案 A方案 B判据
广播间隔短(20 到 100ms)长(1s 以上)快速配网用短,长待机信标用长
数据承载GATT 连接广播 / 扩展广播双向交互用连接,单向广播用广播包
推送方式NotifyIndicate周期数据用 Notify,关键指令用 Indicate
配对方式Just WorksPasskey / Numeric敏感操作必须用带认证的配对
组网点对点 BLEBLE Mesh少量设备点对点,多点照明用 Mesh
连接参数短间隔低延迟长间隔加从机延迟交互型设备用前者,上报型用后者

一条原则:BLE 的每一个参数都在「延迟、吞吐、功耗」之间做交换,先把业务的延迟容忍度和功耗预算定下来,再倒推连接参数,而不是照抄某个示例的默认值。

14. 常见坑清单

  1. 现象:设备广播发出但手机扫不到。原因:广播间隔太长或广播类型不可发现。规避:确认用 ADV_IND 且间隔在 100ms 以内,检查 Flags 的可发现位。
  2. 现象:连接频繁断开。原因:Supervision Timeout 不满足 (1+latency)×interval×2 约束。规避:按规范公式校验参数,超时至少设为间隔的数倍。
  3. 现象:功耗比预期高十倍。原因:连接间隔太短或从机延迟为 0。规避:按业务容忍度拉长间隔并设置从机延迟。
  4. 现象:连接后收不到数据推送。原因:CCCD 未实现或客户端未打开通知。规避:实现 CCCD 描述符并确认客户端写入 0x0001。
  5. 现象:传输大文件极慢。原因:MTU 仍是默认 23 字节且未协商。规避:连接后主动交换 MTU,用最大双方支持值并分片。
  6. 现象:Android 上偶发连不上。原因:厂商 BLE 栈差异或连接数已满。规避:做机型兼容测试,连接池排队复用。
  7. 现象:配对后重连还要重新配对。原因:绑定信息未持久化或绑定表满被淘汰。规避:把 LTK 存进 Flash,管理绑定表容量与淘汰策略。
  8. 现象:设备地址变化导致无法重连。原因:开启了隐私(RPA)但对方没有 IRK。规避:绑定后再启用隐私,或关闭隐私用固定地址。
  9. 现象:广播里塞不下数据。原因:传统广播 31 字节限制。规避:缩短设备名、用厂商数据紧凑编码,或上 BLE 5 扩展广播。
  10. 现象:写特征只写进去一部分。原因:写了超过 MTU 的数据未用长写流程。规避:分片写或使用「准备写加执行写」流程。

15. 小结

BLE 的工程本质是「用参数换功耗」:GAP 决定设备如何被发现和连接,GATT 决定数据如何组织,SMP 决定如何安全配对,三者分工明确但参数互相牵制。掌握连接间隔、从机延迟、MTU、配对方式这四个杠杆,就能在延迟、吞吐、功耗、安全之间找到平衡点。

落地时的优先级:先把连接参数调对(这是功耗的大头),再把 GATT 数据模型设计清楚(这是兼容性的基础),最后处理安全与隐私(这是产品合规的前提)。手机侧兼容性要靠真实机型测试,不能只在开发板上验证。

下一步建议:在 MCU 上落地 BLE 的工程细节、协议栈内存占用与低功耗模式配合见 ESP32 与 STM32 嵌入式开发 ;BLE 作为配网通道在智能家居里的完整用法属于智能家居组网一文的范围。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「物联网」更多文章

  1. 工业物联网协议与网关
  2. 边缘 AI 推理
  3. 设备配网与批量运维