第1章:BLE协议栈架构概览

大家好,我是你们的老朋友。今天咱们开始聊蓝牙BLE协议栈。

说实话,我第一次接触BLE协议栈的时候,看着那一堆缩写——PHY、LL、HCI、L2CAP、ATT、GATT、GAP——头都大了。这玩意儿到底怎么串起来的?每个层到底干啥的?

别急,我带你一层层剥开它。

1.1 物理层(PHY)——最底层的“无线电”

物理层,说白了就是负责发信号和收信号的那部分硬件。它决定了你的蓝牙芯片用哪个频段、怎么调制、传输速率多少。

BLE工作在2.4GHz ISM频段,这个频段大家都能用——Wi-Fi、Zigbee、微波炉……嗯,你没听错,微波炉也在这频段。所以干扰是家常便饭。

BLE物理层有几个关键参数:

  • 频段:2.4 - 2.4835 GHz
  • 信道数:40个信道,每个2MHz宽
  • 调制方式:GFSK(高斯频移键控)
  • 传输速率:1 Mbps(BLE 4.x/5.0),2 Mbps(BLE 5.0+)

我个人的经验:在共享单车项目里,物理层最坑的是信号衰减。单车停在金属车棚里,信号直接掉一半。后来我们加了天线匹配电路,才勉强搞定。

1.2 链路层(LL)——连接的管理者

链路层是协议栈里最核心的一层。它负责设备发现、连接建立、数据包重传、加密等等。

你想想看,两个蓝牙设备怎么知道对方存在?怎么建立连接?怎么保证数据不丢?这些都是链路层干的活。

链路层有几个重要概念:

  • 状态机:Standby、Advertising、Scanning、Initiating、Connection
  • 角色:Master(主机)和 Slave(从机)
  • 数据包格式:Preamble + Access Address + PDU + CRC

避坑指南:我曾经在调试连接断开问题时,查了三天代码,最后发现是链路层的连接间隔(Connection Interval)设得太短,导致从机来不及处理。记住,连接间隔不是越小越好。

1.3 主机控制接口(HCI)——软硬件的分界线

HCI是协议栈里一个特殊的存在。它不处理业务逻辑,它只是“传话的”。

HCI定义了主机(Host)和控制器(Controller)之间的通信协议。主机通常是CPU上跑的软件栈,控制器是蓝牙芯片里的固件。

HCI的命令和事件大概有几十种,常用的包括:

  • LE Set Advertising Parameters:设置广播参数
  • LE Create Connection:发起连接
  • LE Read Remote Features:读取对方特性

嗯,这里要注意:HCI的通信方式可以是UART、USB、SPI等。共享单车里最常见的是UART,因为成本低、实现简单。

1.4 L2CAP——数据的分包与重组

L2CAP全称是逻辑链路控制与适配协议。名字很绕,但功能很简单——它负责把上层的大数据包拆成链路层能处理的小包,反过来也负责把小包拼成大包。

为什么需要L2CAP?因为链路层的数据包最大只有几十个字节(BLE 4.x是27字节,BLE 5.0可以到251字节)。你上层要发一个几百字节的配置文件,不拆不行。

L2CAP还提供:

  • 信道复用:多个上层协议共用同一个链路层连接
  • 分段与重组:大包拆小包,小包拼大包
  • 流控:防止发送方太快,接收方来不及处理

我记得有一次,共享单车的固件升级包有几十KB,L2CAP分段参数没调好,导致升级成功率只有60%。后来把MTU(最大传输单元)从23字节调到247字节,成功率直接飙到99%。

1.5 ATT——属性协议

ATT是Attribute Protocol的缩写。它定义了一种“客户端-服务器”模型,用来读写设备上的数据。

在BLE里,数据是以“属性”的形式存在的。每个属性都有一个UUID、一组权限、以及实际的数据值。

ATT的操作包括:

  • Read Request/Response:读属性
  • Write Request/Response:写属性(需要确认)
  • Write Command:写属性(不需要确认)
  • Notify/Indicate:服务器主动通知客户端

说白了,ATT就是BLE世界里的“读写接口”。你手机读单车锁的状态,就是通过ATT读一个属性。

1.6 GATT——属性协议的上层封装

GATT全称是通用属性协议。它是在ATT之上定义的一套规范,用来组织和管理属性。

GATT引入了几个重要概念:

  • Service(服务):一组相关属性的集合,比如“电池服务”、“设备信息服务”
  • Characteristic(特征):一个具体的属性,包含值和描述符
  • Descriptor(描述符):对特征的额外描述,比如单位、范围等

举个例子:共享单车的“开锁”功能,在GATT里就是一个Characteristic。手机往这个Characteristic写一个“开锁指令”,单车收到后执行开锁动作。

我的建议:设计GATT服务时,尽量用标准的UUID(比如蓝牙SIG定义的),不要自己造轮子。标准服务兼容性好,调试工具也支持。

1.7 GAP——设备发现与连接管理

GAP全称是通用访问协议。它负责设备如何被发现、如何建立连接、以及连接后的角色管理。

GAP定义了四种角色:

角色 说明 共享单车场景
Broadcaster 只发送广播,不接收连接 不太常用
Observer 只扫描广播,不发起连接 不太常用
Peripheral 发送广播,等待连接 单车锁(从机)
Central 扫描广播,发起连接 手机(主机)

GAP还定义了广播数据格式、扫描参数、连接参数等。这些参数直接影响功耗和连接速度。

注意:GAP的广播间隔和连接间隔是功耗和响应速度的平衡点。广播间隔越短,设备被发现越快,但功耗越高。共享单车一般设100ms左右,既保证用户扫码后能快速发现,又不至于把电池耗光。

小结

好了,这一章我们把BLE协议栈的七层结构过了一遍。从最底层的PHY到最上层的GAP,每一层都有自己的职责。

你可能会问:这么多层,实际开发中都要自己写吗?

当然不是。大部分蓝牙芯片厂商都提供了完整的协议栈,你只需要调用API就行。但理解每一层的作用,能帮你快速定位问题——比如连接不上,是GAP的问题还是LL的问题?数据传不过去,是L2CAP分段错了还是ATT权限不对?

下一章,咱们深入物理层,聊聊天线设计和信号覆盖那些事。


公众号:蓝海资料掘金营,微信 deep3321