第一章:蓝牙协议栈概览

大家好,我是你们的老朋友。今天咱们正式开始《体温计蓝牙通信协议栈开发实战》的第一课。

做嵌入式蓝牙开发这么多年,我见过太多新手一上来就扎进代码里,结果被各种回调、事件、状态机搞得晕头转向。其实,搞懂蓝牙协议栈的整体架构,就像盖房子先看图纸一样重要。今天,我就带你把这张“图纸”看明白。

1.1 BLE协议栈架构:Controller、Host、Application

BLE协议栈,说白了就是一套分层的软件体系。它把复杂的无线通信任务,拆成了三个清晰的层次:Controller(控制器)Host(主机)Application(应用)

为什么要分层?你想想看,如果所有代码都揉在一起,换个芯片平台就得重写一遍,那得多痛苦。分层之后,每一层各司其职,层与层之间通过标准接口通信。这样,硬件厂商只需要关心Controller层,芯片厂商关心Host层,而我们做产品的,主要跟Application层打交道。

层次 主要职责 典型模块
Application 实现具体业务逻辑(如体温测量、数据显示) GATT Profile、应用任务
Host 管理连接、数据封装、安全加密 GAP、GATT、L2CAP、SMP
Controller 物理层收发、链路层控制 PHY、LL、HCI

我个人习惯把Controller层比作“邮递员”,它只管把信(数据包)送到对方手里,至于信里写了什么,它不关心。Host层是“邮局”,负责分拣、打包、挂号。而Application层就是“写信的人”,决定信的内容和格式。

核心要点:在体温计项目中,我们主要工作在Application层,但必须理解Host和Controller的行为,否则遇到连接不稳定、数据丢包等问题时,你会无从下手。

1.2 协议栈分层模型详解

咱们再往细了看。BLE协议栈从下到上,每一层都有自己明确的职责。我挑几个跟体温计开发最相关的层,重点说说。

1.2.1 物理层(PHY)

这是最底层,负责在2.4GHz频段上发送和接收无线电信号。体温计通常使用1M PHY,功耗低,距离也够用。我记得早期有个项目,为了省电选了更低的发射功率,结果隔着一堵墙就断连了。嗯,这里要注意,物理层的参数直接影响通信距离和功耗,不能盲目调低。

1.2.2 链路层(LL)

链路层负责设备间的连接建立、数据重传和功耗管理。它定义了两种角色:Master和Slave。体温计通常是Slave(从设备),手机是Master(主设备)。

链路层有个重要的概念叫连接事件。说白了,就是Master和Slave约定好,每隔一段时间(连接间隔)交换一次数据。体温计在两次连接事件之间可以进入休眠,这就是BLE省电的秘密。

避坑指南:我曾经把连接间隔设得太短(比如7.5ms),结果体温计的电池两天就耗光了。后来我调整到100ms左右,配合数据批量发送,续航直接提升到半年。连接间隔的取舍,是功耗和实时性的平衡艺术。

1.2.3 主机控制接口层(HCI)

HCI是Controller和Host之间的“翻译官”。在单芯片方案(比如Nordic nRF52系列)中,HCI是内部接口,我们基本不用管。但在双芯片方案(比如Host跑在MCU上,Controller跑在蓝牙芯片上)中,HCI就变成了物理接口(UART、SPI等),需要仔细处理。

1.2.4 逻辑链路控制与适配协议层(L2CAP)

L2CAP负责把上层的数据包拆分成适合链路层传输的小包,也负责把收到的多个小包重组回去。它还提供了MTU(最大传输单元)协商功能。体温计的数据量很小(一次体温值也就2-4字节),所以MTU用默认的23字节就够了。但如果你要传输历史记录列表,建议把MTU协商到247字节,能省不少传输时间。

1.2.5 安全管理层(SMP)

SMP负责配对、绑定和加密。体温计涉及健康数据,加密是必须的。我建议在配对时使用Just Works方式(无需输入密码),用户体验好。但要注意,Just Works方式不提供中间人攻击保护,如果你的产品有更高的安全要求,可以考虑Numeric Comparison或Passkey Entry。

1.2.6 通用访问规范层(GAP)

GAP定义了设备如何被发现、如何建立连接。它有两种角色:Broadcaster(广播者)和Observer(观察者),以及Peripheral(外设)和Central(中心)。体温计通常作为Peripheral,广播自己的存在,等待手机来连接。

1.2.7 通用属性规范层(GATT)

这是咱们做体温计开发最常打交道的层。GATT定义了数据如何组织和交换。它使用Service(服务)Characteristic(特征)的概念。比如,体温计可以定义一个“体温测量服务”,里面包含一个“体温值特征”。手机通过读写这个特征,就能获取体温数据。

举个例子:蓝牙技术联盟(SIG)已经定义了标准的“健康体温计服务”(Health Thermometer Service,UUID为0x1809)。我们直接使用这个标准服务,手机端的健康App就能自动识别并读取体温数据,省去了很多兼容性测试的麻烦。

1.3 体温计应用场景分析

好了,理论讲完了,咱们回到实际场景。体温计蓝牙通信,到底要解决什么问题?

我总结了一下,主要有三个核心需求:

  1. 低功耗:体温计通常使用纽扣电池,要能用几个月甚至一年。每次测量后,蓝牙模块要尽快进入休眠。
  2. 快速连接:用户打开手机App,希望立刻看到体温数据。连接时间超过3秒,体验就很差了。
  3. 数据可靠:体温数据不能出错,也不能丢失。尤其是连续监测场景(比如整夜监测体温变化),丢一个点都可能影响诊断。

针对这些需求,我们的协议栈设计策略是:

  • 广播策略:体温计平时处于低功耗广播状态,广播间隔设为500ms-1s。这样手机扫描时能快速发现,同时功耗可控。
  • 连接参数:连接间隔设为50ms-100ms,从设备延迟设为0-3。这样既能保证数据实时性,又能让体温计在空闲时多睡一会儿。
  • 数据传输:使用Notification(通知)方式,手机订阅体温值特征,体温计测量完成后主动推送数据。这样手机不用轮询,省电又高效。
  • 安全策略:启用加密连接,但配对过程要简单(Just Works)。绑定信息存储在体温计的Flash中,下次连接自动恢复加密。

注意:有些体温计产品需要同时连接两个设备(比如手机和网关)。这种情况下,需要支持多连接功能,对芯片的RAM和Flash要求更高。我建议在选型阶段就确认好芯片是否支持多连接,否则后期改方案代价很大。

好了,第一章的内容就到这里。这一章我们搭建了蓝牙协议栈的整体框架,也分析了体温计场景的特殊需求。下一章,我会带你手把手搭建开发环境,并跑通第一个蓝牙广播程序。到时候,咱们再细聊。