第2章 协议栈架构总览:BLE协议栈分层模型
各位同学,欢迎来到第二章。
上一章我们聊了BLE 5.0的来龙去脉。这一章,咱们把协议栈的骨架搭起来。说白了,就是搞清楚BLE到底是怎么分层的,每一层干什么活,Host和Controller怎么分工。
我个人习惯,学任何协议栈,先看架构图。就像盖房子,先看图纸,再砌砖。否则你一头扎进细节,很容易迷路。
2.1 BLE协议栈分层模型
BLE协议栈,官方叫法是「蓝牙核心规范」定义的那一套。它分两层大块:Controller 和 Host。
你想想看,为什么这么分?
其实是为了灵活性。Controller管硬件,Host管软件。两者之间通过HCI(Host Controller Interface)通信。这样芯片厂商可以只做Controller,应用开发者只关心Host,互不干扰。
我画个简化的分层图给你看:
+-----------------------------+
| Application | ← 你的APP代码
+-----------------------------+
| Host |
| +-----------------------+ |
| | GATT/GAP | |
| +-----------------------+ |
| | ATT/SMP | |
| +-----------------------+ |
| | L2CAP | |
| +-----------------------+ |
+------ HCI 接口 ------------+
| Controller |
| +-----------------------+ |
| | Link Layer | |
| +-----------------------+ |
| | Physical Layer | |
| +-----------------------+ |
+-----------------------------+
嗯,这里要注意:HCI 不一定是物理线。在单芯片方案里,它只是软件接口。但在双芯片方案(比如手机+蓝牙芯片)里,HCI就是UART、USB或者SDIO。
2.2 各层功能简介
咱们从下往上,一层层说。
2.2.1 物理层(PHY)
物理层是真正的「无线电」。它负责把数据变成电磁波发出去,也负责把收到的电磁波变回数据。
BLE 5.0在物理层最大的变化,就是引入了2M PHY和Coded PHY。2M PHY把速率翻倍到2Mbps,Coded PHY则通过冗余编码把传输距离拉到400米以上。
我记得第一次用Coded PHY做远距离测试,在空旷公园里走了300米还能连上,当时挺震撼的。
2.2.2 链路层(LL)
链路层是Controller的核心。它管三件事:
- 广播:设备发广播包,告诉别人「我在这儿」。
- 扫描:设备监听广播包,找周围设备。
- 连接:两个设备建立连接后,按约定的时序收发数据。
链路层还负责白名单、加密、跳频这些事。说白了,它就是个精密的调度器,确保数据在正确的时间、正确的频率上发送。
重要概念:BLE的链路层是状态机驱动的。设备在Standby、Advertising、Scanning、Initiating、Connection这五个状态之间切换。你写代码时,本质上就是在操作这个状态机。
2.2.3 HCI(Host Controller Interface)
HCI是Host和Controller之间的「翻译官」。Host发命令给Controller,Controller回事件给Host。
常见的HCI命令有:LE_Set_Advertising_Parameters、LE_Create_Connection 等等。
我曾经调试过一个诡异问题,设备连上就断。抓HCI日志一看,发现Controller返回了Connection Timeout事件。原来是链路层没收到Host的响应,超时了。嗯,这种问题不看HCI日志根本猜不到。
2.2.4 L2CAP(逻辑链路控制与适配协议)
L2CAP在Host这一层。它把上层的数据包拆成适合链路层发送的小包,也把收到的碎片重组回去。
BLE的L2CAP比经典蓝牙简单得多。它主要支持ATT和SMP两个通道。ATT通道传数据,SMP通道传安全相关的信息。
2.2.5 ATT(属性协议)
ATT是BLE的灵魂。它定义了一种「客户端-服务器」模型:
- 服务器:持有数据,以「属性」的形式组织。
- 客户端:读写服务器的属性。
每个属性都有UUID、句柄、权限。你平时读心率、写LED开关,底层都是ATT在干活。
2.2.6 GATT(通用属性配置文件)
GATT在ATT之上,定义了数据怎么组织。它引入了Service(服务)和Characteristic(特征)的概念。
举个例子:一个心率服务,包含一个心率测量特征。特征的值就是实时心率数据。
我个人习惯,设计BLE产品时,先把GATT的Service/Characteristic结构画出来。结构清晰了,代码写起来就顺了。
2.2.7 GAP(通用访问配置文件)
GAP管设备的角色和连接行为。它定义了四种角色:
| 角色 | 说明 | 典型设备 |
|---|---|---|
| Broadcaster | 只发广播,不连接 | 信标 |
| Observer | 只收广播,不连接 | 扫描器 |
| Peripheral | 可被连接,通常作为服务器 | 传感器 |
| Central | 主动连接,通常作为客户端 | 手机 |
2.2.8 SMP(安全管理协议)
SMP负责配对、绑定和加密。它定义了三种配对方式:Just Works、Passkey Entry、Out of Band。
你想想看,为什么BLE的配对这么简单?因为它的设计目标就是低功耗、低复杂度。不需要像经典蓝牙那样搞复杂的PIN码输入。
2.3 Host与Controller分工
这是很多初学者容易混淆的地方。我直接说结论:
- Controller:管时间敏感的事。比如广播时序、连接间隔、跳频、加密引擎。这些事必须由硬件或底层固件完成,延迟要控制在微秒级。
- Host:管逻辑复杂的事。比如GATT服务管理、配对流程、数据解析。这些事可以用软件慢慢处理,毫秒级延迟也能接受。
避坑指南:我曾经把一个GATT写操作放在Controller层处理,结果导致连接不稳定。后来才明白,Controller应该只做数据搬运,逻辑处理交给Host。这个教训让我记住了:别让Controller干它不该干的活。
2.4 物理层与链路层基础
最后,咱们深入一下物理层和链路层的基础知识。
2.4.1 物理层核心参数
| 参数 | BLE 4.x | BLE 5.0 |
|---|---|---|
| 速率 | 1 Mbps | 1 Mbps / 2 Mbps / 125 kbps (Coded) |
| 调制方式 | GFSK | GFSK |
| 信道数 | 40 (3广播 + 37数据) | 40 (3广播 + 37数据) |
| 信道间隔 | 2 MHz | 2 MHz |
| 发射功率 | 典型 0 dBm | 典型 0 dBm,可调 |
为什么BLE用GFSK调制?因为它抗干扰能力强,而且实现简单。你想想看,低功耗芯片的射频前端,越简单越省电。
2.4.2 链路层核心机制
链路层最核心的机制是跳频。BLE在37个数据信道上跳来跳去,每发一个包换一个信道。这样能有效避开干扰。
跳频的算法很简单:根据当前信道索引和跳频增量,计算下一个信道。公式是:
next_channel = (current_channel + hop_increment) mod 37
嗯,这里要注意:hop_increment 在连接建立时协商好,之后双方同步跳频。如果一方跳错了,连接就断了。
链路层还定义了连接事件的概念。每个连接事件里,主设备和从设备可以交换多个数据包。连接间隔从7.5ms到4s可调。间隔越短,延迟越低,但功耗越高。
警告:连接间隔不是越小越好。我见过有人把连接间隔设成7.5ms,结果设备发热严重,电池半天就耗光了。实际项目中,要根据数据量和功耗要求,找到一个平衡点。一般传感器用100ms左右就够。
2.5 本章小结
这一章,我们搭起了BLE协议栈的骨架。从物理层的无线电,到链路层的调度,再到Host层的GATT/GAP,每一层各司其职。
我个人觉得,理解分层模型是学好BLE的第一步。后面每一章,我们都会深入一层,把细节抠清楚。
下一章,咱们专门讲物理层,把2M PHY和Coded PHY的细节掰开揉碎。到时候见。
公众号:蓝海资料掘金营,微信deep3321