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频段的不同位置,可以有效避开干扰。
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) | 传输距离极远(可达几百米) | 速率极低 | 工业物联网、远距离控制 |
3.2 链路层(LL)—— 连接是怎么建立和维护的
链路层是BLE协议栈里最核心的一层。它负责设备间的数据收发、连接管理、以及最重要的——功耗控制。
3.2.1 链路层的两种角色
链路层定义了两种角色:
- Advertiser(广播者):定期发送广播包,告诉周围设备「我在这里」。
- Scanner(扫描者):监听广播包,发现周围的设备。
连接建立后,角色会变成Master(主设备)和Slave(从设备)。在智能牙刷场景里,牙刷通常是从设备,手机是主设备。
3.2.2 连接事件与跳频
BLE的连接不是持续不断的通信,而是基于「连接事件」的。主设备和从设备约定好时间,每隔一段时间交换一次数据。这个间隔叫连接间隔(Connection Interval),范围是7.5ms到4s。
连接间隔越大,功耗越低,但延迟也越大。我做过一个项目,客户要求牙刷数据实时显示,我把连接间隔设成了7.5ms,结果牙刷电池两天就没电了。后来改成30ms,延迟用户根本感觉不到,续航却翻了一倍。
每次连接事件发生时,主从设备会按照预定义的跳频序列切换到下一个信道。这就是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的通信是典型的「命令-事件」模型:
- 主机发送HCI命令给控制器(比如「开始广播」)。
- 控制器执行命令,返回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)
3.3.3 为什么HCI这么重要?
HCI的存在,让蓝牙协议栈的开发和调试变得模块化。你可以用同一个主机代码,搭配不同的控制器芯片。比如我做过一个项目,前期用NRF52832调试,后期换成国产的BK3432,只需要改HCI底层的驱动,上层代码完全不用动。
另外,HCI也是排查问题的关键入口。如果设备连不上,先看HCI层有没有收到连接完成的命令。如果连HCI都没动静,那问题大概率出在物理层或链路层。
3.4 三层之间的关系
这三层的关系,我打个比方你就明白了:
- 物理层:就像快递员的自行车,决定了能不能把包裹送到。
- 链路层:就像快递公司的调度系统,决定了什么时候送、走哪条路。
- HCI层:就像快递单上的地址标签,让发货方和送货方能对上话。
没有物理层,信号传不出去。没有链路层,连接无法建立。没有HCI层,主机和控制器各说各话。三层缺一不可。
下一章,咱们继续聊协议栈的上三层:L2CAP、ATT、GATT。这些才是真正和你的应用数据打交道的部分。到时候我会结合智能牙刷的数据传输,给你讲透。