1. 蓝牙技术概览与协议栈架构

各位同学,大家好。我是你们的老朋友,一个在蓝牙协议栈里摸爬滚打了十几年的工程师。今天咱们正式开始《蓝牙芯片协议栈开发实战宝典》的第一章。

说实话,蓝牙这东西,看着简单,用起来也方便,但真要把它吃透,得从根儿上捋清楚。我见过太多开发者,上来就调API,遇到问题就抓瞎。为什么?因为不懂协议栈的骨架。

这一章,咱们就把蓝牙的“前世今生”和“骨架结构”讲明白。你想想看,搞懂了这些,后面写代码、调bug,心里就有底了。

1.1 蓝牙技术演进:从BR/EDR到BLE再到Mesh

蓝牙技术从1994年诞生到现在,经历了几个关键阶段。我个人习惯把它分成三个时代:

  • 经典蓝牙时代(BR/EDR):Basic Rate / Enhanced Data Rate。主打连续数据流,比如蓝牙耳机听歌、蓝牙音箱。特点是功耗高、连接建立慢,但吞吐量大。
  • 低功耗蓝牙时代(BLE):Bluetooth Low Energy。从4.0开始引入,彻底改变了物联网。主打间歇性小数据量传输,比如手环、传感器。功耗极低,一颗纽扣电池能跑一年。
  • 蓝牙Mesh时代:从4.0开始支持,5.0之后成熟。它把蓝牙从“一对一”变成了“多对多”网络。智能灯控、楼宇自动化,靠的就是它。

核心区别一句话总结:

BR/EDR 是“打电话”,一直连着;BLE 是“发短信”,发完就睡;Mesh 是“微信群聊”,大家互相转发。

我记得刚做BLE项目那会儿,有个客户非要用经典蓝牙做传感器,功耗压不下去。我跟他解释了半天,最后换了BLE,电池续航从3天变成了3个月。嗯,选对技术方案,比什么都重要。

1.2 核心协议栈分层:Controller、Host、Application

蓝牙协议栈的分层,说白了就是“各司其职”。你想想看,一个完整的蓝牙系统,从射频信号到应用逻辑,中间隔了多少层?

标准的分层模型是这样的:

层级 包含模块 职责
Application App、Profiles、Services 业务逻辑、用户交互
Host GAP、GATT、ATT、SM、L2CAP 协议封装、安全、数据管理
Controller LL、PHY、RF 射频收发、链路控制、时序

这里我重点说一下 ControllerHost 的分界线。在蓝牙规范里,它们之间通过 HCI(Host Controller Interface)通信。HCI 可以是 UART、USB、SDIO 等物理接口。

我曾经在一个项目里,因为 HCI 的波特率没配好,导致 Host 发命令 Controller 收不到,设备死活连不上。查了两天才发现是 UART 时钟漂移的问题。所以,HCI 是协议栈的“命门”,调试时一定要先确认它通不通。

我的习惯: 在 Host 和 Controller 之间加一个 HCI 日志打印。每次发命令前打印一次,收到事件后打印一次。这样能快速定位是 Host 的问题还是 Controller 的问题。

1.3 Profile 与 Service 概念

很多初学者搞不清 Profile 和 Service 的区别。我打个比方:

  • Service 就像你手机里的一个“功能模块”,比如“心率监测”、“电池电量”。它包含一组数据(Characteristic)和行为。
  • Profile 就像是一个“应用场景”,比如“健康设备”、“智能锁”。它规定了需要哪些 Service,以及它们怎么配合工作。

举个例子,一个蓝牙心率带:

  • 它实现了 Heart Rate Profile (HRP),这个 Profile 要求必须包含 Heart Rate ServiceDevice Information Service
  • Heart Rate Service 里有一个 Heart Rate Measurement Characteristic,用来实时上报心率数据。

在代码里,Service 和 Characteristic 是通过 UUID 来标识的。标准 Service 有固定的 16-bit UUID(比如 0x180D 就是 Heart Rate Service),自定义 Service 用 128-bit UUID。

// 伪代码示例:定义一个自定义 Service
// UUID: 0xAAAA-...-...-...-...
service_t my_service = {
    .uuid = {0xAA, 0xAA, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
             0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB, 0x00, 0x00},
    .characteristics = {
        {
            .uuid = {0xBB, 0xBB, ...},
            .properties = READ | NOTIFY,
            .value = &sensor_data,
        }
    }
};

避坑指南: 我曾经在定义自定义 Service 时,把 UUID 写反了字节序(大端小端搞混)。结果手机端扫描不到 Service,折腾了一整天。记住:蓝牙协议栈里 UUID 默认是小端序,但有些 SDK 会帮你转换,一定要看文档确认。

1.4 知识体系总览图

下面这张图,是我自己总结的蓝牙协议栈知识体系。你把它存下来,后面每学一章,回来对照一下,就知道自己学到哪了。

蓝牙协议栈知识体系总览 Application 层 Profiles (HRP, HID, ANP...) | Services | 用户应用逻辑 接口:API 回调 / 事件通知 Host 层 GAP (广播/扫描/连接) | GATT (属性协议) | ATT | SM (安全管理) | L2CAP 接口:HCI Command / Event Controller 层 LL (链路层) | PHY (物理层) | RF (射频) 接口:HCI Transport (UART/USB/SDIO) 核心:HCI 是 Host 与 Controller 的分界线,也是调试的突破口

这张图里,我特意把 HCI 标红了。为什么?因为在实际开发中,80% 的蓝牙连接问题都出在 HCI 通信上。要么是命令超时,要么是事件丢失。你只要把 HCI 调通了,后面的事就顺了。

1.5 本章小结

这一章,咱们把蓝牙的“骨架”搭起来了:

  • 蓝牙技术从 BR/EDR 到 BLE 再到 Mesh,本质是“功耗”和“网络拓扑”的进化。
  • 协议栈分三层:Controller 管射频,Host 管协议,Application 管业务。
  • Profile 是“场景”,Service 是“功能模块”,Characteristic 是“数据通道”。

嗯,内容不多,但都是基础。你把这些概念刻在脑子里,后面学 ATT、GATT、L2CAP 的时候,就不会觉得乱了。

好,这一章就到这里。下一章咱们深入 HCI,看看 Host 和 Controller 到底是怎么“对话”的。


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