1. 蓝牙协议栈概览:从射频层到应用层的全链路解析

做蓝牙开发这么多年,我见过太多人一上来就调 API、写代码,结果遇到连接不稳定、丢包、断连,完全不知道问题出在哪。说白了,你不了解协议栈的全貌,就像修车不看发动机舱——能修好才怪。

这一章,我带你把蓝牙协议栈从下到上捋一遍。不搞虚的,全是实际开发中绕不开的东西。

1.1 蓝牙协议栈的整体分层

蓝牙协议栈,说白了就是一套通信规则的分层实现。每一层只干自己的事,层与层之间通过标准接口交互。我习惯把它分成三大部分:控制器层、主机层、应用层。

核心要点:蓝牙协议栈的分层设计,让硬件厂商和软件开发者可以各管各的。你换了一颗蓝牙芯片,只要 HCI 接口不变,上层的协议栈代码基本不用动。

下面这张图,是我自己画的一个简化版协议栈结构。你盯着看两分钟,后面讲每一层的时候你心里就有谱了。

蓝牙协议栈全链路分层结构 应用层 (Application) GATT / GAP / 自定义 Profile 主机层 (Host) L2CAP — 数据分包与重组 SMP — 安全管理协议 ATT — 属性协议 HCI (Host 侧) — 命令/事件/数据 控制器层 (Controller) HCI (Controller 侧) — 固件接口 Link Layer (LL) — 连接状态机 Baseband / PHY — 基带与射频 RF — 物理无线收发 2.4GHz ISM 频段 物理信道 HCI 是主机与控制器之间的分界线,实际开发中很多稳定性问题就出在这条线上

1.2 控制器层:射频与链路控制

控制器层,是蓝牙最靠近硬件的那部分。它跑在蓝牙芯片的固件里,你作为应用开发者通常不直接碰它,但它的行为直接影响你的连接稳不稳。

1.2.1 射频层(RF)

射频层负责把数字信号变成电磁波发出去,再把收到的电磁波变回数字信号。工作在 2.4GHz ISM 频段,这个频段 Wi-Fi、Zigbee、微波炉都在用。嗯,这里要注意——同频干扰是蓝牙不稳定的头号杀手。

我曾经在一个智能家居项目里,蓝牙门锁老是莫名其妙断连。排查了三天,最后发现是客户把 Wi-Fi 路由器贴在门锁旁边。2.4GHz 频段互相打架,蓝牙根本抢不过 Wi-Fi 的发射功率。后来把门锁天线位置挪了 30 厘米,问题解决。

1.2.2 基带与物理层(Baseband / PHY)

基带层负责调制解调、跳频、定时同步。蓝牙用的是 GFSK 调制,BLE 还支持 LE Coded PHY 来提升距离。

你想想看,蓝牙为什么比 Wi-Fi 抗干扰?因为它每秒跳频 1600 次。一个信道被干扰了,下一个跳频周期就换到干净的信道去了。但前提是——你的跳频算法要跟对端同步,同步丢了,连接就断了。

1.2.3 链路层(Link Layer)

链路层是控制器层的核心。它管理连接状态机:Standby、Advertising、Scanning、Initiating、Connection。每一个状态切换,都对应着蓝牙芯片内部的中断和定时器。

状态 说明 常见问题
Standby 空闲,不发射也不接收 功耗优化不到位,待机电流偏高
Advertising 广播自身存在,等待扫描 广播间隔设置不合理,设备发现慢
Scanning 监听周围广播包 扫描窗口太小,漏包严重
Initiating 主动发起连接 连接参数协商失败,导致连不上
Connection 已建立连接,周期性收发数据 连接间隔漂移、超时断连

个人习惯:调试链路层问题时,我第一件事就是抓 HCI 日志,看连接事件是不是准时触发。如果连接事件有 jitter,大概率是射频干扰或者芯片内部调度出了问题。

1.3 主机层:数据与安全

主机层跑在应用处理器上,通常是 Linux、RTOS 或者 Android/iOS 的协议栈。它不关心射频怎么发,只关心数据怎么组织、怎么加密、怎么传输。

1.3.1 HCI(主机控制器接口)

HCI 是主机和控制器之间的通信桥梁。它定义了命令、事件、数据的传输格式。常见的物理传输方式有 UART、USB、SDIO。

我在项目中遇到过最坑的事:UART 波特率设置不匹配,导致 HCI 命令丢字节,蓝牙芯片直接死机。后来我在 HCI 驱动里加了 CRC 校验和重传机制,才彻底解决。

1.3.2 L2CAP(逻辑链路控制与适配协议)

L2CAP 负责把上层数据拆成适合链路层传输的小包,也负责把收到的包重组回去。它还管理着 MTU(最大传输单元) 的协商。

为什么 MTU 重要?你想想看,如果你要发 500 字节的数据,但 MTU 只有 23 字节(BLE 默认值),那就要拆成 22 个包。任何一个包丢了,整个数据就得重传。所以,连接建立后第一件事就是协商 MTU,我一般建议协商到 247 字节以上。

1.3.3 ATT 与 GATT

ATT(属性协议)定义了如何读写蓝牙设备上的数据属性。GATT 在 ATT 之上,定义了数据的组织方式——Service、Characteristic、Descriptor。

说白了,GATT 就是蓝牙世界的文件系统。Service 是文件夹,Characteristic 是文件,Descriptor 是文件的属性描述。你读写数据,本质上就是在操作这个文件系统。

1.3.4 SMP(安全管理协议)

SMP 负责配对、绑定、加密。它定义了 Just Works、Passkey Entry、Numeric Comparison、OOB 四种配对方式。

我曾经在一个医疗设备项目里,客户要求必须加密传输。结果 SMP 配对时,双方支持的加密算法不一致,配对失败。后来我在代码里加了算法降级逻辑,才兼容了老版本手机。

1.4 应用层:Profile 与业务逻辑

应用层是你写业务代码的地方。蓝牙 SIG 定义了很多标准 Profile,比如 HID(键盘鼠标)、ANP(通知)、HTP(体温计)。你也可以自定义 Profile。

我个人习惯,在应用层只做两件事:数据解析和业务逻辑。所有跟连接管理、重连、超时处理相关的逻辑,都放在主机层或者单独的状态机里。这样代码好维护,出问题也好定位。

1.5 全链路数据流:一个实际例子

假设你的手机要读取一个蓝牙温度计的温度值。数据是怎么从温度计芯片一路跑到手机 App 的?

  1. 温度计芯片的传感器采集温度,应用层把温度值写入 GATT 的 Temperature Characteristic。
  2. ATT 把写请求封装成 ATT Write Command,交给 L2CAP。
  3. L2CAP 检查 MTU,如果数据太大就拆包,加上 L2CAP 头,交给 HCI。
  4. HCI 把数据封装成 HCI ACL Data Packet,通过 UART 发给控制器。
  5. 链路层 把数据包放到连接事件里,加上 LL 头,交给基带。
  6. 基带 做 GFSK 调制,跳频到当前信道,通过射频发出去。
  7. 手机端 反向走一遍:射频→基带→链路层→HCI→L2CAP→ATT→GATT→App。

你看,一个简单的读温度操作,要经过 7 层处理。任何一层出问题,你 App 上看到的就是「连接不稳定」或者「数据读不到」。

核心观点:蓝牙稳定性不是某一层的事。射频干扰、链路层状态机异常、HCI 丢包、L2CAP 缓冲区溢出、ATT 超时——每一层都可能成为瓶颈。你只有理解了全链路,才能快速定位问题。

1.6 本章小结

这一章我们把蓝牙协议栈从射频到应用层完整过了一遍。你不需要记住每一层的所有细节,但脑子里要有这张分层地图。后面每一章,我们都会深入到某一层,讲具体的稳定性问题和解决方案。

嗯,记住一句话:蓝牙不稳定,90% 的问题出在你不了解的那一层。