第二章 BLE协议栈架构:物理层、链路层、主机层、应用层分层解析
各位同学,咱们今天聊聊BLE协议栈的分层结构。说实话,我刚入行那会儿,看着协议栈的七层八层也是一头雾水。后来做医疗贴片项目,被坑了几次,才真正理解——分层不是用来装样子的,每一层都有它存在的理由。
BLE协议栈,说白了就是一套通信规则。它把复杂的无线通信拆成了四个层次:物理层、链路层、主机层、应用层。每一层只管自己的事,上层调用下层,下层服务上层。嗯,这个思路其实跟软件分层很像。
2.1 物理层(PHY)—— 信号的搬运工
物理层是协议栈的最底层,负责真正的无线信号收发。它决定了数据怎么在空中飞。
核心参数:
- 工作频段:2.4GHz ISM频段,全球通用
- 调制方式:GFSK(高斯频移键控)
- 数据速率:1Mbps(BLE 4.x/5.0)、2Mbps(BLE 5.0+)
- 发射功率:典型范围 -20dBm 到 +10dBm
- 接收灵敏度:一般 -90dBm 到 -97dBm
我个人的经验:做医疗贴片时,发射功率别开太大。我曾经为了追求通信距离,把功率调到+8dBm,结果电池两天就耗光了。后来改成0dBm,距离虽然短了点,但续航从2天变成了7天。医疗贴片嘛,续航比距离重要。
物理层还定义了40个RF通道,其中37个用于数据通信,3个用于广播。为什么会这样设计?你想想看,如果所有设备都在一个频道上喊,那不乱套了?
2.2 链路层(LL)—— 通信的调度员
链路层是BLE协议栈的灵魂。它负责设备间的连接建立、数据包收发、重传控制。说白了,就是管着两个设备怎么“对话”。
链路层的核心职责:
- 广播与扫描:外围设备发广播,中心设备扫描发现
- 连接建立:握手、参数协商
- 数据包调度:连接事件、锚点、间隔
- 重传与确认:丢包了怎么办?重传!
- 加密与安全:链路层加密
这里有个关键概念——连接间隔。两个设备建立连接后,并不是一直在通信,而是每隔一段时间交换一次数据。这个间隔可以设置,范围从7.5ms到4s。
| 连接间隔 | 功耗 | 实时性 | 适用场景 |
|---|---|---|---|
| 7.5ms - 30ms | 高 | 高 | 实时数据采集(如心电) |
| 50ms - 100ms | 中 | 中 | 体温、血氧等慢变信号 |
| 200ms - 1s | 低 | 低 | 状态上报、日志传输 |
避坑指南:我曾经在一个心电贴片项目里,把连接间隔设成了7.5ms,想着数据越实时越好。结果发现设备发热严重,电池半天就没了。后来改成30ms,配合缓存批量发送,功耗降了60%。记住:不是越快越好,够用就行。
2.3 主机层(Host)—— 协议的翻译官
主机层包含L2CAP、ATT、GATT、SM等子层。它负责把链路层的原始数据包,翻译成应用层能理解的“服务”和“特征值”。
主机层各子层的作用:
- L2CAP:数据包的分段与重组。链路层一次只能发几十个字节,L2CAP帮你把大数据包切碎,到对端再拼起来。
- ATT:属性协议。定义了客户端-服务器模型,客户端读写服务器的属性。
- GATT:通用属性配置文件。在ATT之上定义了服务(Service)和特征值(Characteristic)的概念。
- SM:安全管理。负责配对、绑定、加密。
我建议你重点理解GATT。因为医疗贴片的数据交互,几乎都是通过GATT服务来实现的。比如一个体温贴片,会定义一个“体温服务”,里面包含“温度值”特征值和“测量间隔”特征值。
举个例子:一个血氧贴片的GATT服务结构
服务:血氧服务 (UUID: 0x180F)
├── 特征值:血氧饱和度 (UUID: 0x2A5F)
│ ├── 属性:通知
│ └── 值:98%
├── 特征值:脉搏率 (UUID: 0x2A5E)
│ ├── 属性:通知
│ └── 值:72 bpm
└── 特征值:测量间隔 (UUID: 0x2A21)
├── 属性:读写
└── 值:5秒
2.4 应用层(App)—— 业务逻辑的实现者
应用层是离用户最近的一层。它定义了设备的具体行为——什么时候广播、怎么处理数据、如何响应命令。
在医疗贴片里,应用层通常包含:
- 设备配置:采样率、测量模式、报警阈值
- 数据管理:本地存储、数据压缩、批量上传
- 状态机:待机→测量→传输→待机
- 低功耗策略:什么时候休眠、什么时候唤醒
嗯,这里要注意。应用层虽然叫“层”,但它其实不是协议栈的一部分,而是你写的业务代码。协议栈只负责把数据传过去,至于数据是什么意思、怎么处理,那是应用层的事。
警告:很多新手容易犯一个错误——把业务逻辑写在协议栈的回调函数里。比如在连接事件回调里做数据处理、写Flash。这会导致协议栈卡死,因为回调函数需要快速返回。我建议:回调里只做数据搬运,业务逻辑放到任务队列里处理。
2.5 分层架构的实际意义
你可能会问:搞这么复杂干嘛?直接发数据不就行了?
我举个例子。假设你要做一个体温贴片,用Nordic的nRF52832芯片。如果你不懂分层,可能会直接操作RF寄存器发数据。但这样做有几个问题:
- 手机端怎么收?你得自己写手机端的RF驱动
- 多个设备同时发怎么办?你得自己处理冲突
- 数据丢了怎么办?你得自己实现重传
有了分层架构,你只需要关心应用层。物理层和链路层的事,芯片厂商的协议栈帮你搞定了。主机层的GATT服务,你配置一下就行。这就是分层的好处——各司其职,降低复杂度。
我的习惯:做医疗贴片时,我会先画一个分层框图,标出每一层我要做什么、用什么API。这样代码写起来思路清晰,出了问题也知道去哪一层排查。你也不妨试试。
2.6 本章小结
BLE协议栈的四层架构,每一层都有明确的职责:
- 物理层:管信号,别让它飞丢了
- 链路层:管连接,别让它断了
- 主机层:管数据,别让它乱了
- 应用层:管业务,别让它傻了
下一章,我们会深入链路层,聊聊连接事件、广播包格式、以及那些让你头疼的时序参数。到时候我会拿一个实际的心电贴片项目来拆解,保证你听完就能上手。
好,今天就到这儿。有问题随时问我。