第2章:蓝牙基础理论——BLE协议栈架构与核心机制
好,咱们正式开始聊蓝牙。说实话,BLE(低功耗蓝牙)这玩意儿,刚接触的时候确实有点懵。协议栈分好几层,什么Controller、Host、Application,听着就头大。但别急,我带你一层层剥开它。
2.1 BLE协议栈架构:三层分工
BLE协议栈,说白了就是一套软件和硬件的分层规范。它把整个蓝牙通信过程拆成了三个大块:Controller(控制器)、Host(主机)和Application(应用)。这三层各司其职,互不干扰。
2.1.1 Controller层——物理世界的“翻译官”
Controller层是离硬件最近的一层。它负责处理射频、基带、链路控制这些底层活儿。你想想看,天线怎么发信号、怎么收信号、怎么跳频,都是它说了算。
我记得第一次调蓝牙模块时,死活连不上手机。折腾了半天,发现是Controller层的射频参数没配好。嗯,这里要注意:Controller层的配置,比如发射功率、信道选择,直接影响通信距离和功耗。
Controller层包含几个关键子层:
- 物理层(PHY):负责调制解调、数据收发。BLE在2.4GHz频段工作,有1Mbps和2Mbps两种速率模式。
- 链路层(LL):负责数据包封装、重传、加密。它决定了设备是广播者还是扫描者。
- 直接测试模式(DTM):用于射频测试,我一般用它来验证天线性能。
2.1.2 Host层——通信的“大脑”
Host层跑在Controller上面,它不关心物理信号,只关心数据怎么组织、怎么交互。说白了,Host层就是协议栈的逻辑核心。
Host层包含:
- 逻辑链路控制与适配协议(L2CAP):负责数据的分段与重组。比如你发一个100字节的数据,L2CAP会把它切成适合底层传输的小包。
- 安全管理器(SM):负责配对、绑定、加密。我遇到过不少设备配对失败的问题,十有八九是SM层的密钥交换没处理好。
- 属性协议(ATT):定义了数据怎么读写。GATT就是基于ATT的。
- 通用属性协议(GATT):这个后面细说。
- 通用访问协议(GAP):这个也后面细说。
2.1.3 Application层——你写的代码
Application层就是咱们开发者直接打交道的地方。你写的业务逻辑、UI交互、数据处理,全在这一层。它通过GAP和GATT的API来调用Host层的功能。
我个人习惯把Application层写得尽量薄,只做业务逻辑。底层通信的细节,交给Host和Controller去处理。这样代码好维护,也方便移植。
2.2 GAP与GATT:两个核心角色
GAP和GATT,这两个词你肯定听过。它们就像蓝牙世界的“身份证”和“通讯录”。
2.2.1 GAP——定义设备角色
GAP(通用访问协议)定义了设备在蓝牙网络中的角色。说白了,就是告诉别人“我是谁,我能干什么”。
GAP定义了四种角色:
| 角色 | 说明 | 典型设备 |
|---|---|---|
| Broadcaster(广播者) | 只发广播,不连接 | 信标、温度传感器 |
| Observer(观察者) | 只收广播,不连接 | 扫描仪、网关 |
| Peripheral(外设) | 可被连接,通常发广播 | 手环、心率带 |
| Central(中心) | 主动扫描并连接外设 | 手机、平板 |
你想想看,咱们的手表配网场景:手表是Peripheral,手机是Central。手表发广播,手机扫描到后发起连接。这就是GAP在起作用。
2.2.2 GATT——定义数据交互
GATT(通用属性协议)定义了连接建立后,数据怎么读写。它把数据组织成“服务(Service)”和“特征(Characteristic)”的层级结构。
举个例子:
- 服务(Service):比如“心率服务”,UUID是0x180D。
- 特征(Characteristic):比如“心率测量值”,UUID是0x2A37。它包含具体的数值和属性(可读、可写、可通知)。
GATT定义了两种角色:
- GATT Server:提供数据的一方。比如手表上的心率传感器,它把心率值放在特征里,等着客户端来读。
- GATT Client:读取数据的一方。比如手机App,它主动去读手表的特征值。
我曾经踩过一个坑:在GATT Server里定义了一个特征,属性设成了“可读+可通知”。结果手机端读数据时,发现读到的值和通知来的值不一样。后来查了半天,发现是特征值的缓存机制没处理好。嗯,这里要提醒大家:如果特征值会动态变化,记得用通知(Notification)而不是读(Read),这样数据才实时。
2.3 广播与扫描机制
广播和扫描,是BLE通信的第一步。没有广播,设备就像大海里的孤岛,谁也找不到谁。
2.3.1 广播机制
广播者(比如手表)会周期性地发送广播包。广播包包含设备信息、服务UUID、设备名称等。广播间隔可以配置,一般在20ms到10.24秒之间。
广播包有两种类型:
- 可连接广播:允许其他设备发起连接。配网场景就用这个。
- 不可连接广播:只广播,不连接。信标设备常用。
广播数据格式是这样的:
广播包结构:
- 前导码(1字节)
- 访问地址(4字节)
- 协议数据单元(PDU)
- 头部(2字节):包含类型、长度等
- 有效载荷(最多31字节):包含设备名、服务UUID等
- CRC(3字节)
我个人习惯把广播间隔设在100ms左右。太短了费电,太长了手机扫描不到。当然,具体要看产品需求。
2.3.2 扫描机制
扫描者(比如手机)会监听广播信道。BLE有3个广播信道(37、38、39),扫描者在这三个信道上轮流监听。
扫描有两种模式:
- 被动扫描:只收广播包,不发任何数据。省电。
- 主动扫描:收到广播包后,发送扫描请求,获取更多信息。比如获取设备完整的名称。
2.3.3 广播与扫描的配合
广播和扫描就像“喊话”和“听声”。广播者喊得越勤(间隔短),扫描者越容易听到。但喊得勤也费电。所以需要权衡。
我一般这样配:
- 配网阶段:广播间隔设短一点(比如50ms),让手机快速发现。
- 正常工作:广播间隔设长一点(比如1秒),省电。
你想想看,手表配网时,用户肯定希望一打开App就能看到设备。如果广播间隔太长,用户等半天,体验就差了。但配网成功后,手表就不需要频繁广播了,省电才是王道。
2.4 小结
这一章咱们聊了BLE协议栈的三层架构、GAP和GATT的角色、以及广播与扫描机制。说白了,这些都是蓝牙通信的“基本功”。
我个人觉得,理解这些基础概念,比直接上手调代码更重要。因为只有懂了原理,遇到问题才知道从哪下手。下一章,咱们会深入GATT,聊聊怎么定义服务和特征,以及怎么实现数据读写。
嗯,今天就到这儿。有问题随时交流。