第3章 BLE协议栈入门:核心概念与SDK初探

好,咱们进入第三章。说实话,这一章是很多TWS开发者的「劝退点」。为什么?因为BLE协议栈太抽象了。一堆缩写——GATT、GAP、HCI、L2CAP……刚接触时我也有点头大。

但别怕。咱们不搞学院派那套,我带你从实际开发的角度,把这些概念一个个拆开。说白了,BLE协议栈就是一套「蓝牙设备之间怎么聊天」的规则。你只要搞懂谁负责打招呼、谁负责传数据、谁负责底层跑腿,就差不多了。

3.1 BLE 5.0/5.2核心概念:GAP与GATT

这两个是BLE协议栈里最上层的两个角色。我习惯这么记:GAP管「能不能连」,GATT管「连上了能干啥」

3.1.1 GAP——通用访问规范

GAP定义了蓝牙设备的角色和连接流程。在TWS耳机里,最常见的角色就是:

  • Broadcaster(广播者):耳机开机后,不断发广播包,告诉手机「我在这儿」。
  • Observer(观察者):手机扫描广播,发现耳机。
  • Peripheral(外设):耳机作为从设备,等待手机连接。
  • Central(中心):手机作为主设备,发起连接。

嗯,这里要注意:TWS耳机里,左右耳之间也有GAP角色。比如左耳做Central,右耳做Peripheral,这就是所谓的「监听模式」或「转发模式」。我在做第一代TWS时,就踩过这个坑——左右耳角色没配好,导致连接后右耳没声音。

GAP核心事件流程:

  1. 设备上电 → 进入广播状态
  2. 手机扫描到广播 → 发起连接请求
  3. 连接建立 → 进入已连接状态
  4. 连接断开 → 回到广播状态

3.1.2 GATT——通用属性规范

GATT才是真正干活的地方。它定义了一套「属性表」的结构。你想想看,手机连上耳机后,怎么知道耳机电量?怎么调节音量?都是通过GATT的读写操作。

GATT的核心概念有三个:

  • Service(服务):比如「电池服务」、「设备信息服务」。每个服务有一个UUID。
  • Characteristic(特征):服务下面的具体数据点。比如「电池电量百分比」就是一个特征。
  • Descriptor(描述符):对特征的补充说明,比如配置通知开关。

举个例子,TWS耳机里最常见的GATT结构:

服务:电池服务 (0x180F)
  └── 特征:电池电量 (0x2A19)
       └── 描述符:客户端特征配置 (0x2902)

手机读这个特征,就能拿到电量值。手机写这个描述符,就能开启电量变化通知。

避坑指南:我曾经在开发时,把特征属性配成了「只读」,结果手机发写请求时一直返回错误。后来查了半天才发现是属性位没配对。GATT的属性位有读、写、通知、指示等,一定要按需配置。

3.2 广播与扫描:设备怎么找到对方

广播和扫描,是BLE连接的第一步。说白了,就是「喊话」和「听喊话」。

3.2.1 广播(Advertising)

广播包分两种:

  • 广播包(Advertising PDU):包含设备名、UUID、厂商自定义数据等。
  • 扫描响应包(Scan Response PDU):手机扫描时,设备可以额外回复更多信息。

广播间隔是个关键参数。间隔越短,手机发现越快,但功耗越高。TWS耳机里,我一般设成100ms左右。连接后可以切换到更慢的广播模式,省电。

注意:BLE 5.0引入了扩展广播,数据包长度从31字节提升到255字节。但TWS耳机里用得不多,因为大部分场景31字节够用了。除非你要广播大量厂商数据。

3.2.2 扫描(Scanning)

手机扫描时,有两种模式:

  • 被动扫描:只收广播包,不发请求。省电。
  • 主动扫描:收到广播后,发扫描请求,获取扫描响应包。信息更全。

我记得有一次,客户反馈耳机连不上手机。排查后发现是手机端扫描窗口设得太短,漏掉了耳机的广播包。嗯,这种问题最难查,因为看起来两边都没错。

3.3 连接:建立稳定的数据通道

连接建立后,手机和耳机之间就有了一个稳定的数据通道。连接参数包括:

参数 说明 TWS典型值
连接间隔 两个连接事件之间的时间 7.5ms ~ 30ms
延迟 设备可以跳过的连接事件数 0 ~ 4
超时时间 超过此时间无数据则断开 4s ~ 6s

连接间隔越小,数据延迟越低,但功耗越高。TWS耳机里,音频传输时一般用7.5ms或10ms。待机时可以放宽到30ms以上。

个人经验:连接参数不是随便设的。手机端和耳机端要协商一致。我遇到过耳机端设了7.5ms,但手机端不支持,结果连接后频繁断连。后来加了连接参数更新请求,才解决。

3.4 HCI层与L2CAP层的作用

这两个层在协议栈中间,平时开发不直接碰,但出了问题就得找它们。

3.4.1 HCI——主机控制器接口

HCI是Host(主机)和Controller(控制器)之间的接口。在nRF5 SDK里,Host是CPU跑的协议栈上层,Controller是蓝牙射频芯片。

HCI定义了命令、事件、数据三种包格式。比如:

  • Host发HCI命令给Controller:启动广播、建立连接等。
  • Controller发HCI事件给Host:连接完成、断开通知等。
  • Host和Controller之间传ACL数据:音频数据、ATT协议包等。

说白了,HCI就是一条「命令通道」和「数据通道」。调试时,抓HCI日志能看清每一笔交互。我习惯用nRF Sniffer抓HCI包,排查连接失败问题特别好用。

3.4.2 L2CAP——逻辑链路控制与适配协议

L2CAP在HCI上面,负责把上层数据打包成固定长度的包,传给HCI。它支持:

  • 分段与重组:大包拆小包,接收端再拼回去。
  • 协议多路复用:同一个连接上,可以同时跑ATT、SMP、RFCOMM等多种协议。
  • 流控与重传:保证数据可靠传输(可选)。

在TWS耳机里,L2CAP最常用的就是ATT协议通道。音频数据走的是另一个通道——Isochronous Channel(BLE 5.2新增)。

避坑指南:我曾经在调试时,发现手机发过来的ATT包总是丢。后来查L2CAP的MTU(最大传输单元)才发现,手机端MTU是512字节,耳机端默认是23字节。包太大,L2CAP分段没处理好,就丢了。所以连接后第一件事,就是交换MTU。

3.5 Nordic nRF5 SDK与Realtek Amebad BLE SDK架构初探

好了,理论讲完了,咱们看看实际开发用的SDK。

3.5.1 Nordic nRF5 SDK

nRF5 SDK是Nordic官方提供的BLE开发包。它的架构大概是:

  • Application层:你的业务代码,比如按键处理、电量上报。
  • SoftDevice层:Nordic的BLE协议栈,以二进制形式提供,用户不能改。
  • HCI层:SoftDevice和Application之间的接口,通过API调用。

开发时,你主要跟Application层打交道。调用SoftDevice的API来启动广播、处理连接、读写GATT。比如:

// 启动广播
sd_ble_gap_adv_start(&adv_params, APP_BLE_CONN_CFG_TAG);

// 处理连接事件
void ble_evt_handler(ble_evt_t const * p_ble_evt) {
    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            // 连接建立
            break;
        case BLE_GAP_EVT_DISCONNECTED:
            // 连接断开
            break;
    }
}

我个人习惯用nRF5 SDK的例程做起点,比如ble_app_uartble_app_hrs。改改服务UUID和特征,就能快速搭起一个原型。

3.5.2 Realtek Amebad BLE SDK

Realtek的SDK跟Nordic不太一样。它把协议栈和应用代码放在一起,你可以直接修改协议栈参数。架构上:

  • Application层:你的业务代码。
  • GAP/GATT层:Realtek封装好的API,比Nordic更上层。
  • HCI层:直接暴露HCI命令接口,方便调试。

Realtek SDK的一个特点是,它提供了很多配置宏,改改头文件就能调参数。比如:

// 配置广播间隔
#define GAP_ADV_INTERVAL_MIN     160  // 100ms
#define GAP_ADV_INTERVAL_MAX     320  // 200ms

// 配置连接间隔
#define GAP_CONN_INTERVAL_MIN    12   // 15ms
#define GAP_CONN_INTERVAL_MAX    24   // 30ms

嗯,这里要注意:Realtek的文档没有Nordic那么全。我刚开始用的时候,经常翻源码找API定义。但好处是,代码完全开源,你可以直接改协议栈行为。

总结一下:

  • Nordic:文档好、社区活跃、SoftDevice稳定。适合快速原型开发。
  • Realtek:代码开源、可定制性强、成本低。适合量产产品。

选哪个?看你的产品定位和团队经验。我个人建议,新手先从Nordic入手,熟悉了再转Realtek。

3.6 本章小结

这一章内容不少,但都是基础中的基础。GAP管连接,GATT管数据,广播和扫描是发现机制,HCI和L2CAP是底层支撑。SDK只是工具,理解了协议栈,换哪个平台都不怕。

下一章,咱们要动手写代码了——搭建开发环境,跑第一个BLE例程。到时候你会发现,理论懂了,写代码其实挺快的。


公众号:蓝海资料掘金营,微信deep3321