2. BLE协议栈架构:协议栈分层模型、Controller层、Host层、Application层、各层职责
做嵌入式通信开发,尤其是搞蓝牙低功耗,第一件事就是得把协议栈的架构搞清楚。我见过太多新手一上来就调API,结果遇到连接断连、数据丢包、功耗下不来,完全不知道问题出在哪一层。
说白了,BLE协议栈就是一套分层的软件体系。每一层只管自己的事,层与层之间通过标准接口通信。这种设计的好处很明显——你换芯片、换协议栈版本,只要接口不变,上层代码基本不用动。
核心观点:BLE协议栈分为三大层——Controller层、Host层、Application层。Controller管物理收发,Host管逻辑控制,Application管业务逻辑。
2.1 分层模型总览
先看一张整体架构图,我习惯把它记成「下中上」三层结构。底层是Controller,中间是Host,顶层是Application。每一层内部又细分了几个子层。
嗯,这张图我建议你多看两眼。每一层都有自己明确的边界,这也是BLE能保持低功耗、低成本、高可靠性的关键原因。
2.2 Controller层——管好物理世界
Controller层是离硬件最近的一层。它直接操作射频收发器,负责把数据变成无线电波发出去,也负责把收到的无线电波还原成数据。
Controller层内部又分两个子层:
- PHY(物理层):定义无线信号的调制方式、频率、功率。BLE工作在2.4GHz ISM频段,有40个信道,每个信道2MHz带宽。PHY决定了你能传多远、功耗多少。
- LL(链路层):这是Controller的核心。它管理设备状态——待机、广播、扫描、发起连接、已连接。还负责数据包的组装、拆解、重传、加密。
我的经验:有一次客户反馈设备连接距离只有5米,怎么调天线都没用。后来发现是LL层配置了过短的连接间隔,导致接收窗口太小。把连接间隔从7.5ms调到15ms,距离直接翻倍。你看,问题往往不在硬件,在协议栈配置。
2.3 Host层——管好逻辑与数据
Host层在Controller之上,它不关心无线电怎么收发,只关心数据怎么组织、怎么交互。Host层内部有三个关键子层:
2.3.1 L2CAP
L2CAP是逻辑链路控制和适配协议。它干两件事:
- 复用:把上层多个协议(ATT、SMP等)的数据流合并到一条物理链路上。
- 分段重组:上层数据包太大?L2CAP帮你切小。收到小包?帮你拼回去。
2.3.2 ATT
属性协议。BLE里所有数据都以「属性」的形式存在。一个属性就是一个数据单元,包含句柄、UUID、权限、值。ATT定义了六种操作——读、写、通知、指示、广播、发现。
2.3.3 GATT
通用属性配置文件。它基于ATT,定义了更高级的数据交互模型。比如Service、Characteristic、Descriptor这些概念,都是GATT层引入的。
关键区别:ATT管的是「怎么读写数据」,GATT管的是「数据长什么样、怎么组织」。你写应用代码时接触最多的就是GATT层。
2.4 Application层——管好业务
Application层就是你的代码所在的地方。它调用GATT API,定义自己的Service和Characteristic,处理业务逻辑。
举个例子,你做一个温度传感器:
- Application层定义了一个「温度Service」,里面包含一个「温度值Characteristic」。
- 当传感器采集到新温度,Application层调用GATT的Notify接口,把数据发出去。
- 手机端收到通知,解析出温度值,显示在App上。
Application层不关心底层是哪个芯片、射频怎么配置、数据包怎么重传。它只关心业务。
2.5 HCI——连接Host与Controller的桥梁
HCI(Host Controller Interface)不是独立的一层,它是Host和Controller之间的通信接口。在单芯片方案里,HCI是内部函数调用;在双芯片方案里(比如Host跑在MCU上,Controller跑在蓝牙芯片上),HCI走UART、SPI或USB。
| 特性 | 单芯片方案 | 双芯片方案 |
|---|---|---|
| HCI实现方式 | 内部函数调用 | UART/SPI/USB |
| 延迟 | 低(微秒级) | 较高(毫秒级) |
| 功耗 | 更低 | 略高(额外通信开销) |
| 灵活性 | 低(芯片绑定) | 高(可更换Host或Controller) |
| 典型场景 | 低功耗传感器、穿戴设备 | 网关、手机、复杂嵌入式系统 |
我曾经踩过的坑:双芯片方案里,HCI的UART波特率设置不对,导致Host发命令给Controller时偶尔丢包。设备连接成功率从99%掉到70%。排查了三天,最后发现是波特率不匹配。所以,HCI通信参数一定要在初始化阶段做握手校验,别想当然。
2.6 各层职责速查表
为了方便你快速回顾,我整理了一张职责清单:
| 层级 | 子层/模块 | 核心职责 |
|---|---|---|
| Controller | PHY | 射频收发、调制解调、信道选择 |
| LL | 设备状态管理、数据包收发、重传、加密 | |
| Host | L2CAP | 协议复用、数据分段重组 |
| ATT | 属性读写操作、数据交互 | |
| GATT | 数据模型定义(Service/Characteristic) | |
| Application | 用户代码 | 业务逻辑、数据处理、用户交互 |
2.7 数据流在协议栈中的旅程
你想想看,一个温度值从传感器到手机App,在协议栈里是怎么走的?
- Application层:采集温度,调用GATT的Notify接口,把温度值传给GATT。
- GATT层:把温度值封装成Attribute PDU,加上句柄和UUID,传给ATT。
- ATT层:生成ATT协议数据单元,传给L2CAP。
- L2CAP层:加上L2CAP头(包含通道ID),如果数据太大就分段,传给HCI。
- HCI:封装成HCI数据包,通过UART/SPI传给Controller。
- LL层:拆开HCI包,组装成Link Layer数据包,加上接入地址、CRC等,传给PHY。
- PHY层:调制成射频信号,在2.4GHz信道上发出去。
接收端反过来走一遍。每一层只处理自己该处理的部分,不越界。这就是分层设计的美妙之处。
我个人习惯:调试BLE问题时,先确定问题出在哪一层。如果是连不上,查Controller层;如果是数据读不到,查Host层;如果是业务逻辑不对,查Application层。分层排查,效率最高。
好了,这一章的内容就这些。协议栈的分层模型是后续所有章节的基础,你把它吃透了,后面讲连接、广播、配对、功耗优化,都会轻松很多。