第3章 BLE协议栈详解:从物理层到应用层

BLE协议栈,说白了就是一套分层的通信规则。我刚开始接触时也觉得层数太多,有点懵。但后来发现,每一层各司其职,理解起来并不复杂。

咱们先看整体架构,再逐层拆解。

核心要点:BLE协议栈分为三层——控制器(Controller)、主机(Host)和应用层(Application)。控制器负责射频和链路控制,主机负责逻辑链路和属性协议,应用层直接面向开发者。

BLE协议栈分层架构 BLE协议栈分层架构 应用层(Application) 主机(Host) GATT / ATT / L2CAP / SM HCI(主机-控制器接口) 控制器(Controller) LL(链路层) / PHY(物理层) PHY(物理层) 实际开发中,应用层和主机层通常在MCU上实现,控制器层在BLE芯片内部完成

3.1 物理层(PHY)—— 信号的起点

PHY层是协议栈的最底层。它负责把数据变成无线电波发出去,也负责把收到的无线电波还原成数据。

BLE工作在2.4GHz ISM频段,和Wi-Fi、ZigBee共用这个频段。BLE定义了40个信道,每个信道间隔2MHz。其中3个是广播信道(37/38/39),37个是数据信道。

参数 BLE 1M PHY BLE 2M PHY BLE Coded PHY (S=2) BLE Coded PHY (S=8)
数据速率 1 Mbps 2 Mbps 500 kbps 125 kbps
调制方式 GFSK GFSK GFSK + 编码 GFSK + 编码
通信距离 ~100m ~50m ~200m ~400m
典型场景 通用 高速数据传输 中等距离 远距离

我的经验:做智能门锁项目时,我一开始用了1M PHY,穿墙后信号衰减严重。后来换成Coded PHY (S=8),距离从30米提升到100米以上。代价是速率降到125kbps,但门锁那点数据量完全够用。

3.2 链路层(LL)—— 连接的指挥官

链路层是BLE协议栈里最核心的一层。它管理着设备的状态机,控制着广播、扫描、连接建立和数据传输。

LL层定义了5种设备状态:

  • Standby:空闲状态,不发送也不接收
  • Advertising:广播状态,向外发送广播包
  • Scanning:扫描状态,监听广播包
  • Initiating:发起连接状态,主动建立连接
  • Connection:连接状态,已建立连接

设备可以在这些状态之间切换。比如一个传感器平时在广播状态,手机扫描到后发起连接,传感器进入连接状态。

注意:同一时刻,设备只能处于一种状态。不能一边广播一边扫描,除非你用了多模芯片。我曾经踩过这个坑——想用同一个芯片同时做广播和扫描,结果发现LL层不支持。

3.3 L2CAP层 —— 数据的分包与重组

L2CAP(逻辑链路控制与适配协议)位于主机层底部。它负责把上层的大数据包拆成LL层能处理的小包,反过来也负责把LL层的小包拼回大包。

BLE的L2CAP和经典蓝牙不太一样。经典蓝牙的L2CAP支持多种通道,BLE的L2CAP只支持面向连接的通道(CoC)和面向无连接的通道(CL)。

默认的MTU(最大传输单元)是23字节。但可以通过MTU协商增大到512字节甚至更大。

关键点:MTU协商是提升数据传输效率的重要手段。默认23字节意味着每次最多传20字节有效数据(3字节L2CAP头)。协商到247字节后,一次能传244字节,效率提升10倍以上。

3.4 ATT层 —— 属性的读写

ATT(属性协议)定义了设备之间如何读写数据。它把数据抽象成"属性"(Attribute),每个属性都有:

  • 句柄(Handle):属性的唯一ID,16位
  • 类型(UUID):标识属性是什么数据
  • 权限(Permissions):可读、可写、可通知等
  • 值(Value):实际数据

ATT定义了6种PDU(协议数据单元):

操作 方向 说明
Read Request / Response Client → Server → Client 客户端读取属性值
Write Request / Response Client → Server → Client 客户端写入属性值,需要确认
Write Command Client → Server 客户端写入属性值,不需要确认
Notify Server → Client 服务器主动通知,不需要确认
Indicate / Confirm Server → Client → Server 服务器主动指示,需要确认

我的建议:Notify和Indicate的区别一定要搞清楚。Notify不确认,速度快但不可靠;Indicate有确认,可靠但慢。做传感器数据上报时,我一般用Notify,丢一帧无所谓。做控制指令时,必须用Indicate,确保对方收到了。

3.5 GATT层 —— 数据的组织方式

GATT(通用属性协议)在ATT之上,定义了数据的组织方式。它把属性组织成Service(服务)和Characteristic(特征)的层次结构。

一个典型的GATT结构是这样的:

  • Profile:最顶层,定义了一组Service
  • Service:一组相关的Characteristic,比如电池服务、设备信息服务
  • Characteristic:一个具体的数据点,包含值、属性、描述符
  • Descriptor:对Characteristic的补充说明,比如配置通知开关

举个例子,电池服务(Battery Service)包含一个电池电量特征(Battery Level),这个特征的值是0-100的整数,表示剩余电量百分比。

理解GATT的关键:GATT定义了"数据长什么样",ATT定义了"怎么读写这些数据"。两者配合,构成了BLE应用层通信的基础。

3.6 BLE广播与扫描 —— 发现彼此

广播和扫描是BLE设备互相发现的方式。广播者(Advertiser)在3个广播信道上轮流发送广播包,扫描者(Scanner)在这些信道上监听。

广播包的类型:

  • 可连接广播(Connectable):其他设备可以发起连接
  • 可扫描广播(Scannable):其他设备可以请求扫描响应
  • 不可连接广播(Non-connectable):只广播,不接受连接
  • 定向广播(Directed):指定目标设备

广播间隔通常设置在20ms到10.24s之间。间隔越短,被发现越快,但功耗越高。

避坑指南:我曾经把广播间隔设成20ms,结果功耗飙升,纽扣电池两天就没电了。后来改成100ms,功耗降了80%,发现延迟也才多了一两百毫秒。广播间隔不是越小越好,要平衡功耗和实时性。

3.7 BLE连接建立流程

连接建立是BLE通信的关键步骤。流程如下:

  1. 广播阶段:外设(Peripheral)在广播信道上发送广播包
  2. 扫描阶段:中央设备(Central)扫描到广播包
  3. 发起连接:中央设备发送连接请求(CONNECT_REQ)
  4. 连接确认:双方进入连接状态,开始按连接参数通信

连接请求中包含连接参数:

参数 范围 说明
连接间隔 7.5ms ~ 4s 两个连接事件之间的时间
延迟 0 ~ 499 设备可以跳过的连接事件数
超时时间 100ms ~ 32s 超过此时间未收到包则断开连接

我的经验:连接间隔设得越小,延迟越低,但功耗越高。做手环项目时,我设了30ms连接间隔,延迟低但电池撑不到一天。后来改成100ms,配合延迟参数,续航到了3天。用户感知不到那几十毫秒的差别。

3.8 BLE数据通道

连接建立后,双方在数据信道上通信。数据通道使用跳频机制,每发一个包就跳到下一个信道。BLE有37个数据信道,跳频算法由LL层管理。

数据通道的通信模式:

  • 连接事件(Connection Event):每个连接间隔发生一次,双方交换数据
  • 主从角色:中央设备是Master,外设是Slave。Master决定何时发送
  • 数据包格式:前导码(1字节)+ 访问地址(4字节)+ PDU + CRC(3字节)

数据通道的PDU类型:

  • LL Data PDU:承载L2CAP层的数据
  • LL Control PDU:链路层控制命令,如更新连接参数、加密等

总结:BLE数据通道的核心是"连接事件+跳频"。每个连接事件里,Master先发,Slave在150μs后回复。这种机制保证了低功耗和抗干扰能力。