第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在起作用。

我的经验: 设计产品时,先想清楚设备是哪种角色。如果只是单向传数据,用Broadcaster/Observer就够了,功耗更低。如果需要双向通信,那就得用Peripheral/Central。

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),扫描者在这三个信道上轮流监听。

扫描有两种模式:

  • 被动扫描:只收广播包,不发任何数据。省电。
  • 主动扫描:收到广播包后,发送扫描请求,获取更多信息。比如获取设备完整的名称。
注意: 主动扫描会多一次数据交换,功耗更高。如果你的设备对功耗敏感,建议用被动扫描。我曾经在一个低功耗项目里,因为用了主动扫描,电池续航直接少了30%。后来改成被动扫描,问题解决了。

2.3.3 广播与扫描的配合

广播和扫描就像“喊话”和“听声”。广播者喊得越勤(间隔短),扫描者越容易听到。但喊得勤也费电。所以需要权衡。

我一般这样配:

  • 配网阶段:广播间隔设短一点(比如50ms),让手机快速发现。
  • 正常工作:广播间隔设长一点(比如1秒),省电。

你想想看,手表配网时,用户肯定希望一打开App就能看到设备。如果广播间隔太长,用户等半天,体验就差了。但配网成功后,手表就不需要频繁广播了,省电才是王道。

2.4 小结

这一章咱们聊了BLE协议栈的三层架构、GAP和GATT的角色、以及广播与扫描机制。说白了,这些都是蓝牙通信的“基本功”。

我个人觉得,理解这些基础概念,比直接上手调代码更重要。因为只有懂了原理,遇到问题才知道从哪下手。下一章,咱们会深入GATT,聊聊怎么定义服务和特征,以及怎么实现数据读写。

嗯,今天就到这儿。有问题随时交流。