3、BLE协议栈详解(上):物理层(PHY)、链路层(LL)、主机控制接口层(HCI)

好,咱们开始啃协议栈了。

说实话,很多做蓝牙开发的朋友,一看到协议栈这几个字就头大。我当年也一样,觉得这东西太抽象了,不如直接调API来得痛快。但后来踩了几个坑才明白——不懂底层,出了问题你连排查方向都没有。

这一章,咱们先聊BLE协议栈的下三层:物理层、链路层、主机控制接口层。这三层是蓝牙通信的基石,也是你调试时最常打交道的部分。

3.1 物理层(PHY)—— 信号怎么在空中飞

物理层,说白了就是决定「信号怎么发出去、怎么收回来」的那一层。它不关心你传的是什么数据,只关心比特流能不能在空气里跑通。

3.1.1 频段与信道

BLE工作在2.4GHz ISM频段,这个频段是免费的,但也很拥挤——Wi-Fi、Zigbee、微波炉都在这里混。BLE把2.4GHz频段划分成了40个信道,每个信道2MHz宽。

这40个信道里,有3个是广播信道(37、38、39),剩下的37个是数据信道。为什么要单独留3个广播信道?我刚开始也纳闷,后来在项目中调试连接成功率时才明白——广播信道专门用来做设备发现和连接建立,把它们放在2.4GHz频段的不同位置,可以有效避开干扰。

关键点: BLE的跳频技术就是在这37个数据信道之间快速切换,抗干扰能力比固定频段强得多。

3.1.2 调制方式与速率

BLE物理层用的是GFSK调制,也就是高斯频移键控。你可以简单理解为:用频率的变化来表示0和1。

BLE 4.x/5.0支持1Mbps和2Mbps两种速率。2Mbps速率快,但传输距离会缩短。我在做智能牙刷项目时,一开始图快用了2Mbps,结果发现手机隔一堵墙就断连了。后来老老实实切回1Mbps,连接稳定多了。

速率模式 优点 缺点 适用场景
1Mbps(LE 1M) 传输距离远,兼容性好 速率较低 智能牙刷、传感器等低功耗设备
2Mbps(LE 2M) 速率高,延迟低 距离短,功耗略高 音频传输、OTA升级
125kbps/500kbps(LE Coded) 传输距离极远(可达几百米) 速率极低 工业物联网、远距离控制
我的经验: 智能牙刷这种穿戴设备,建议用1Mbps。距离和功耗的平衡点最好,而且兼容市面上绝大多数手机。

3.2 链路层(LL)—— 连接是怎么建立和维护的

链路层是BLE协议栈里最核心的一层。它负责设备间的数据收发、连接管理、以及最重要的——功耗控制。

3.2.1 链路层的两种角色

链路层定义了两种角色:

  • Advertiser(广播者):定期发送广播包,告诉周围设备「我在这里」。
  • Scanner(扫描者):监听广播包,发现周围的设备。

连接建立后,角色会变成Master(主设备)和Slave(从设备)。在智能牙刷场景里,牙刷通常是从设备,手机是主设备。

3.2.2 连接事件与跳频

BLE的连接不是持续不断的通信,而是基于「连接事件」的。主设备和从设备约定好时间,每隔一段时间交换一次数据。这个间隔叫连接间隔(Connection Interval),范围是7.5ms到4s。

连接间隔越大,功耗越低,但延迟也越大。我做过一个项目,客户要求牙刷数据实时显示,我把连接间隔设成了7.5ms,结果牙刷电池两天就没电了。后来改成30ms,延迟用户根本感觉不到,续航却翻了一倍。

注意: 连接间隔不是越小越好。对于智能牙刷这种非实时性设备,30ms-50ms是比较合理的范围。太小的间隔会严重增加功耗。

每次连接事件发生时,主从设备会按照预定义的跳频序列切换到下一个信道。这就是BLE的抗干扰秘诀——即使某个信道被Wi-Fi占了,下一跳就换到干净的信道去了。

3.2.3 链路层的状态机

链路层有5种状态:Standby、Advertising、Scanning、Initiating、Connection。设备在这几个状态之间切换。

嗯,这里要注意:从Advertising到Connection,中间必须经过Initiating状态。也就是说,扫描者必须先发起连接请求,才能进入连接状态。这个细节我在调试时忽略过,结果代码写好了,设备就是连不上,查了半天才发现是状态机没走对。

3.3 主机控制接口层(HCI)—— 芯片内部的分界线

HCI层,你可以把它理解为协议栈内部的一道「防火墙」。它把蓝牙芯片分成了两部分:

  • 主机(Host):运行在应用处理器上,负责高层协议(如GATT、ATT、L2CAP)。
  • 控制器(Controller):运行在蓝牙芯片上,负责底层协议(PHY、LL)。

HCI就是这两部分之间的通信接口。

3.3.1 HCI的通信方式

HCI支持多种物理传输方式:

  • UART:最常见,用串口通信,速率一般115200bps或更高。
  • USB:用于USB蓝牙适配器。
  • SDIO:用于高速传输场景。
  • SPI:某些专用芯片会使用。

在智能牙刷这种嵌入式设备里,绝大多数情况用的是UART。因为主控芯片(比如STM32、NRF52)和蓝牙芯片之间通过串口连接,成本低、实现简单。

3.3.2 HCI命令与事件

HCI的通信是典型的「命令-事件」模型:

  1. 主机发送HCI命令给控制器(比如「开始广播」)。
  2. 控制器执行命令,返回HCI事件(比如「广播已启动」)。

举个例子,让蓝牙芯片开始广播的HCI命令长这样:

// HCI_LE_Set_Advertising_Enable命令
// 参数:0x01 表示启用广播
HCI Command: 0x08 0x000A 0x01
  Opcode: 0x200A (LE Set Advertising Enable)
  Parameter: 0x01 (Enable)

控制器收到后,会返回一个事件:

HCI Event: 0x0E (Command Complete)
  Opcode: 0x200A
  Status: 0x00 (Success)
调试技巧: 我习惯用逻辑分析仪抓HCI的UART数据,直接看命令和事件的交互。比看代码日志直观多了,能快速定位是主机没发命令,还是控制器没响应。

3.3.3 为什么HCI这么重要?

HCI的存在,让蓝牙协议栈的开发和调试变得模块化。你可以用同一个主机代码,搭配不同的控制器芯片。比如我做过一个项目,前期用NRF52832调试,后期换成国产的BK3432,只需要改HCI底层的驱动,上层代码完全不用动。

另外,HCI也是排查问题的关键入口。如果设备连不上,先看HCI层有没有收到连接完成的命令。如果连HCI都没动静,那问题大概率出在物理层或链路层。

3.4 三层之间的关系

这三层的关系,我打个比方你就明白了:

  • 物理层:就像快递员的自行车,决定了能不能把包裹送到。
  • 链路层:就像快递公司的调度系统,决定了什么时候送、走哪条路。
  • HCI层:就像快递单上的地址标签,让发货方和送货方能对上话。

没有物理层,信号传不出去。没有链路层,连接无法建立。没有HCI层,主机和控制器各说各话。三层缺一不可。

总结一下: 做BLE开发,物理层决定了你的通信距离和速率,链路层决定了你的功耗和连接稳定性,HCI层决定了你的调试效率。这三层搞明白了,后面再学GATT、ATT这些高层协议,就会轻松很多。

下一章,咱们继续聊协议栈的上三层:L2CAP、ATT、GATT。这些才是真正和你的应用数据打交道的部分。到时候我会结合智能牙刷的数据传输,给你讲透。