蓝牙协议栈的学习(二)

蓝牙协议栈的学习(二)

  • [Controller 核心机制](#Controller 核心机制)
    • Radio(射频)/射频层(RF/PHY):
    • [Baseband(基带)/基带层(Link Layer,BLE 的"基带"):](#Baseband(基带)/基带层(Link Layer,BLE 的“基带”):)
    • [Link Controller(LC)](#Link Controller(LC))
    • [LMP(Link Manager Protocol)](#LMP(Link Manager Protocol))
      • [LMP 是什么?](#LMP 是什么?)
      • [LMP 负责哪些事情?](#LMP 负责哪些事情?)
      • [LMP 消息格式](#LMP 消息格式)
      • [LMP 的运行流程](#LMP 的运行流程)
    • [HCI(Host Controller Interface)](#HCI(Host Controller Interface))
      • [什么是 HCI(Host Controller Interface)](#什么是 HCI(Host Controller Interface))
      • [HCI 的作用](#HCI 的作用)
      • [HCI 由什么组成?](#HCI 由什么组成?)
      • [HCI 有哪些数据包类型?](#HCI 有哪些数据包类型?)
      • [HCI 的流控(flow control)](#HCI 的流控(flow control))
      • [恒玄芯片 SDK 中的 HCI 对应位置(重点!)](#恒玄芯片 SDK 中的 HCI 对应位置(重点!))

Controller 核心机制

Radio(射频)/射频层(RF/PHY):

发:把基带送来的"小电平"变成大功率无线电磁波,往空中喊。

收:把空中极微弱的电磁波先"听见",再放大、过滤,变成干净的小电平还给基带。

  • 选频道:蓝牙在 2.4 GHz 频段有 79 条(BR/EDR)或 40 条(BLE)小通道,射频先按指令调到对应"电台频率"。
  • 调制/解调:基带的 0/1 要先变成"声音变化"才能通过喇叭发出去------蓝牙用的是 GFSK、π/4-DQPSK、8-DPSK 等调制方式。
  • 功放与低噪放:发时加大音量,收时先悄悄把对方"悄悄话"放大。
  • 天线开关:同一条天线又要发又要收,射频负责"说的时候闭嘴,听的时候闭嘴"。
  • 射频(Radio)------只管"电磁波"这一层;

baseband基础概念

收:把上层(LC/链路控制器)要发的数据拆成"小包裹",加上地址、序号、校验,再交给射频;

发:收到射频给的"小包裹"后验货、拼回完整数据,再送交上层。

  • 基带(Baseband)------只管"0/1 比特"这一层。
  • 打包格式:BR/EDR 里叫"packet",BLE 里叫"PDU",都含:
    -- 访问码(识别这是哪一组设备在通话)
    -- 包头(谁发给谁、第几个包、要不要确认)
    -- payload(真正有用的数据)
  • 跳频调度:经典蓝牙每 625 µs 换一条频道,基带按"跳频图案"表告诉射频下一微秒该跳去哪。
  • ack/重传:对方没回"收到",基带自动重发,直到超时。
  • 时钟同步:靠自身 28 bit 蓝牙时钟(CLK)与对端对齐,保证双方"同时跳"。

baseband包的类型

  • ID 包(ID packet)

    用途:

    只是用来 播报设备地址(AM_ADDR),非常短。

    作用:

    page

    inquiry

    没有 payload,属于最基础的"我在这里"的包。

  • NULL 包

    用途:

    不传数据

    用于维持链路

    不需要对方回复 ACK

  • POLL 包

    和 NULL 很像,但区别:

    需要对方回复 ACK

    主机会用 POLL 去"点名" slave

  • FHS 包(Frequency Hop Synchronization)

    这是非常重要的 Baseband 包。

    用途:

    在 inquiry 过程中,把 跳频序列信息 + 时钟 + BD_ADDR 发给对方

    → 对方才能同步到你的跳频序列。

    特点:

    长度固定:144 bits 信息 + 16 bits CRC(再加 FEC)

    是建立连接前最重要的包之一

  • DM1 包

    这是 ACL(数据链路)最基础的一种数据包格式之一。

    用途:

    传控制消息(LMP)

    传少量用户数据

    "为什么 LMP 消息通过 DM1 发送?"

    因为 DM1 有 FEC + CRC,非常可靠,适合传控制指令。

射频相关控制

  • 切换 TX / RX

    射频芯片同一条天线不能同时"说"和"听"。

    队长看表------625 µs 的时隙一到,立刻吼:

    "下一条时隙是咱发,关接收,打开发射!"

    硬件马上把开关拨到 TX 端。

    下一时隙如果是对方发,队长又吼:

    "闭嘴,切 RX!"

    ------这就是"施工队长"最实时的活。

  • 按时跳频(根据主机 CLKN)

    蓝牙经典模式每 625 µs 换频道,79 条频道跳来跳去。

    队长口袋里有一张"跳频图案表",表的关键字就是本地时钟 CLKN 的若干位。

    时间一到,他照着表喊:

    "CLKN 低 7 位是 0x3A,下条频道 = 3 号,射频给我跳!"

    射频 PLL 立即锁到新频率------节拍错一格就会跟对方对不上,直接失联。

  • 按 slot (时隙)发送和接收数据包

    队长手里拎着"时隙表":

    偶数 slot → 主设备发

    奇数 slot → 从设备发

    他提前把要发的 payload 塞给基带,等时钟走到边界那一刻,吼:

    "发!"------基带立即把 packet 推给射频。

    收的时候也一样,窗口只开 366 µs,超时没收到就标记丢包,准备重传。

  • 控制发射功率(物理层)

    队长还管"嗓门大小"。

    LMP 刚才协商说"对方 RSSI("接收信号强度指示") 太强,降 4 dB"。

    队长转头对射频功放喊:

    "功率寄存器减 4 dB,现在发射!"

    硬件立即调增益,确保既省电量又不炸掉对方接收机。

Baseband 数据包处理

  • 解析 Access Code、Header、Payload

    这部分指的是对接收到的通信数据包进行解码,首先提取其中的Access CodeHeader (报头)和Payload (有效负载)部分。

    Access Code:让接收方知道数据包的起始位置。

    Header:告诉接收方数据包的基本信息(来源、目标、长度等),帮助接收方正确解析和处理数据包。

    Payload:包含你传送的数据或信息,最终接收方需要读取和使用的部分。

  • 生成 HEC/CRC、做 CRC 校验

    • HEC(Header Error Check)是对数据包头部进行错误检测的一种方式,通常用于校验头部数据是否有误。HEC = Header Error Check(包头纠错/校验码),它不是"接收后才有的东西",而是:发送方在发包前,根据 Header 的内容算出来,然后放进 Header 的 HEC 字段里一起发出去。
    • CRC(Cyclic Redundancy Check)是循环冗余校验,用于检测数据包在传输过程中是否发生错误。这里提到的"生成 CRC"指的是在发送数据前根据数据内容计算出 CRC 校验值;而"做 CRC 校验"则是接收方对收到的数据进行 CRC 校验,确认数据是否正确。Payload 末尾固定带一个 16-bit CRC 字段,这个 CRC 就是发送方算出来附在包后面一起发出去的。
  • 判断 ARQN(ACK/NAK)

    在蓝牙 Baseband 里,每个接收方在收到一个包之后,都会在下一次发包时带上一个字段:

    ARQN = Automatic Repeat reQuest Number

    用 1 bit 表示:1 = ACK(收到正确),0 = NAK(收到错误,需要重传),所以,ARQN 就是接收方对"上一包"给发送方的反馈结果

  • 执行 ARQ 重传机制

    如果接收方返回 NAK,表示数据包有错误或丢失,发送方会重新发送该数据包,这是 ARQ 协议中的重传机制

  • 判断 FLOW Control(STOP/GO)

    Flow Control = 流量控制机制

    • STOP 表示接收方的缓存或处理能力达到上限,要求发送方暂停数据发送。
    • GO 表示接收方已经准备好继续接收数据,可以恢复数据的发送。
  • 控制 synchronous / asynchronous buffer

    同步缓冲区(synchronous buffer)是用来存放实时数据(例如语音)的,必须按时间节奏稳定输出。

    异步缓冲区(asynchronous buffer)是用来存放普通数据(例如文件、网络数据)的,不需要严格时间节奏。

    为什么会有两种 buffer?因为蓝牙(BR/EDR)同时支持两种不同类型的连接:

  1. Synchronous(SCO / eSCO)链路:用于实时数据
    数据必须准时到达
    延迟要求严格
    比如:蓝牙语音(耳机、通话)
    → 不能丢包,也不能延迟太久
    → 必须严格按照固定时间间隔发数据(如每 6 个 slot 送一次)
    这类数据需要一个 同步缓冲区。
  2. Asynchronous(ACL)链路:用于普通数据
    数据不要求精确时间
    可以排队等待
    例如:文件传输、APP 数据、消息通信
    → 可以有重传
    → 可以等待空闲 slot
    → 可以做流量控制(STOP/GO)
    这类数据放在 异步缓冲区。

同步(Synchronous)= 必须按固定节奏、固定时间点执行

大家必须一起步调一致,有严格的时间要求。

在通信中:

数据必须"准时到达"

有固定的发送周期

接收方必须"按时"来取数据

不能随意晚或早

异步(Asynchronous)= 不要求在同一时间点进行,随时可以处理

没有固定节奏,想什么时候做就什么时候做。

在通信中:

数据什么时候到达都可以

发送和接收不需要时间同步

可以排队

可以延迟

丢了还能重传(可以等待

状态机处理

所谓"状态机处理"其实就是:

蓝牙设备在不同阶段会处于不同的工作状态,每个状态有不同的行为、不同的允许动作,LC 就负责按照规则在这些状态之间切换。

蓝牙的主要状态组分为两类:

未连接状态(Connectionless States)

连接后状态(Connected States)

未连接状态:Standby / Inquiry / Page

这些状态是在蓝牙设备"还没建立连接"之前使用的。

Standby(待机)

蓝牙设备最普通的空闲状态,没做什么。

不主动发信号

不与其他设备通信

耗电最低

蓝牙平时不开搜索/不连接时,就是 Standby。

Inquiry(搜索)

设备主动"寻找附近的蓝牙设备"。

类似你打开"蓝牙搜索设备"时发生的事情。

发 Inquiry 包

等待别人回应

用于发现设备(但不能连接)

这是 "搜到别人"。

Page(呼叫)

找到设备后,要建立连接 → 必须 Page 对方。

类似你"点连接某个蓝牙耳机"时发生的事情。

根据目标设备的地址呼叫它

成功会进入 Connection 状态

这是 "找到某人然后叫他接电话"。

连接后状态:Connection / Active / Sniff / Hold / Park

Connection(已连接,总状态)

表示设备之间已经建立链路。

下面几个状态都是 Connection 的子状态。

Active(活动状态)

蓝牙正常通信的状态。

设备可以收发数据包

时刻参与连接

功耗最高

Sniff(轻度节能模式)

"间歇性地醒来收包",一种低功耗模式。

设备不是每个 slot 都监听

只在固定间隔醒来

耗电比 Active 低,非常常用

例如蓝牙鼠标键盘通常在 Sniff 模式下工作。

Hold(暂停模式)

临时不接收 ACL 数据,但保持同步。

设备暂时不参与通信

放弃几个 slot 或一段时间

适合短暂省电

比如手机在传 ACL 数据时出现 SCO 语音需要更多资源,会让 ACL 进入 Hold。

Park(深度休眠模式)

连接仍然存在,但设备几乎不参与访问。

不接收大部分数据

只保持 minimal sync 信息

超低功耗

唤醒要更长时间

Park 模式适用于大量设备连接一个主设备时(例如蓝牙广播系统)

ACL / SCO / eSCO 的时序实现

蓝牙在空中通信时,不同类型的数据(ACL、SCO、eSCO)是怎样按照时间排队发送,怎么做重传,以及怎么保证语音链路的固定时间槽。

认识三种链路

类型 用途 是否允许重传 时间要求
ACL 普通数据(如文件、GATT 数据) ✔ 重传 不严格
SCO 传统语音 ❌ 不重传 非常严格(固定时间)
eSCO 升级版语音 ✔ 可重传,但有次数/时间限制 较严格

1)ACL 自动重传、SEQN 切换 ------ 解决丢包的机制

ACL(普通数据)可以重传:

  • 蓝牙每发一包 ACL 数据,会带一个 SEQN 位(序号位)
  • 对方收到包后会回 ACK
  • 如果 ACK 没来,发送方就用同一个 SEQN 重发
  • 每发成功一包后,SEQN 才会切换(0→1 或 1→0)

ACL 就像快递:没送到就重送,送成功才盖章换下一单号。


2)SCO/eSCO 的固定 slot 保留 ------ 语音链路是强实时的

语音数据要求"准点到达",不能乱序、不能迟太久。

蓝牙的做法是:

  • 规定某些时隙(slot)必须让给 SCO/eSCO
  • 这些 slot 不允许普通 ACL 乱占
  • SCO 是最严格的:绝对固定、不能延迟
  • eSCO 稍微灵活一点,但也要预留时间

语音链路就像高铁的固定时刻表,不能因为走货车(ACL)而延误。


3)eSCO 的重传窗口 ------ 在语音链路里留一点小弹性

eSCO 比 SCO "聪明",可以允许:

  • 在两个语音包之间,留一个"小窗口"用来重传
  • 如果语音包丢了,可在窗口内重发
  • 但不能无限重传,因为下一次语音包时间 slot 也要保证

eSCO 就像公交车,虽然固定时间来一班,但允许司机在站和站之间稍微停一下,把刚刚没上车的人补上。


ACL:保证送达 → 允许多次重传 → 时间不紧张
SCO:严格准点 → 不重传 → 时间 slot 必须保留
eSCO:准点 + 允许少量重传 → 在两次语音包之间存在"重传窗口"


LMP 是什么?

LMP = 蓝牙连接的"协商大脑"。负责和对端"对话",把各种配置谈好,再交给 LC 和 Baseband 去执行。

LMP 是 Link Manager 之间通信,用于:

建立/控制 logical transport

控制 physical link

所有 LMP 消息通过 ACL-C 逻辑链路发送

LMP 负责哪些事情?

① 连接控制(建立 / 断开)

LMP 负责:

建立 ACL 连接

断开连接(detach)

设置 supervision timeout


② 功率控制(ARP/功率调整)

LM 可以要求对方 "one step up / one step down" 增减发射功率,只影响这两个设备的 ACL 链路

就是 LMP 在协商设备发射功率,让连接稳定又省电。


③ AFH(自适应跳频)控制

通知对方启用/停 AFH(Adaptive Frequency Hopping)

下发 AFH channel map(哪些频点不能用)


④ SCO / eSCO 链路建立(语音链路)

Master 通过 LMP 发起 SCO 或 eSCO 建链请求

参数例如:

Tesco(包周期)

Desco(offset)

eSCO 重传窗口

包类型(HVx、EV3/EV5...)

耳机语音链路完全由 LMP 建立!


⑤ Sniff、Hold 等低功耗模式控制

LMP 控制:

sniff interval(Tsniff)

sniff offset(Dsniff)

sniff attempt、sniff timeout

蓝牙"省电"都靠它谈判,尤其是 TWS 耳机。


⑥ 加密和认证

Authentication(认证)

Pairing(配对)

Encryption(加密控制)

SSP(Secure Simple Pairing)

也就是密钥交换 → 认证 → 开加密,这些全是 LMP 负责。


⑦ 多槽(multislot)协商(决定能不能发 DH5、DH3)

LM 可以限制 packet slot 数量:

"Limit the number of consecutive slots"

⑧ 版本、特性、名字请求

LMP_version request

LMP_supported_features

LMP_host_name request

这些都是设备互相"介绍自己"。

LMP 消息格式

LMP 消息通过 DM1 包发送

17 字节以内

有 OpCode(操作码)

有 TID(0 = master 发起,1 = slave 发起)

TID 含义

0 Master 发起

1 Slave 发起

例子:

主机发起建立 eSCO → TID=0

从机发起功率调节 → TID=1

LMP 的运行流程

① 建立 ACL(基本连接)

手机(master)→耳机(slave)

LMP 开始对话:

版本交换

功能交换(features)

supervision timeout

piconet 参数


② 建立 eSCO(语音链路)

Master 发 LMP:

LMP_esco_link_req

给出 Tesco/Desco、包类型

Slave 如果支持 → LMP_Accepted

然后 Baseband/LC 就按照这个参数开始排时隙。


③ 调整参数(低功耗等)

在连接中可能:

进入 Sniff → LMP 控制

改变功率 → LMP 控制

更新 AFH → LMP 控制


④ 加密/配对

数据即将传输时:

LMP_pairing

LMP_authentication

LMP_start_encryption

HCI(Host Controller Interface)

下面我根据你提供的 PPT 内容 ,用 小白能完全听懂 的方式,给你详细讲解:

什么是 HCI(Host Controller Interface)

复制代码
APP(应用层)
    ↓
Host 层(协议、GATT、L2CAP......)
    ↓   ← 通过 HCI 交互
Controller 层(底层:Baseband、射频、Link Manager)
    ↓
2.4GHz 无线信号

简单来说:

  • Host(上层):跑在 MCU、操作系统中,处理协议、GATT、连接逻辑等
  • Controller(下层):跑在蓝牙芯片里,负责射频、Baseband、加密、LMP 等

HCI 就是连接 Host 和 Controller 的"桥"


HCI 的作用

HCI 负责:

  1. Host → Controller:发指令

    • 开个蓝牙
    • 扫描
    • 建立连接
    • 发数据
    • 设置发射功率
  2. Controller → Host:回事件

    • 扫描到设备了
    • 连接成功
    • 收到数据
    • 重连失败
    • 配对成功
  3. 双向的数据收发

    • Host 发 ACL 数据(GATT、ATT 等)
    • Controller 收到空口数据后回给 Host

HCI = "上下层通信协议 + 命令集合"


HCI 由什么组成?

PPT 给的说明很标准,我给你转成容易懂的形式:

复制代码
HCI Driver(在 Host 上)
HCI Firmware(在 Controller 上)
HCI Transport(两者之间的通道)

HCI Driver(运行在 Host)

相当于:

  • 驱动程序
  • API 封装
  • 把 Host 的命令装成 HCI 指令

HCI Firmware(运行在控制器)

相当于:

  • 蓝牙芯片上的解析器
  • 接收 HCI 命令并让硬件执行
  • 把事件回报给 Host

HCI Transport(传输通道)

比如:

  • UART(手机、单片机最常用)
  • USB(电脑蓝牙)
  • SPI
  • SDIO

HCI 有哪些数据包类型?

1)HCI Command Packet

Host → Controller

结构:

复制代码
Opcode(命令类型)
参数(比如扫描时间、发射功率)

比如:

  • HCI_Reset
  • HCI_Read_Local_Name
  • HCI_LE_Set_Advertising_Parameters

2)HCI Event Packet

Controller → Host

比如:

  • 扫描结果
  • 连接建立成功
  • 指令执行成功(HCI_Command_Complete)
  • 遇到错误(如拒绝连接)

3)HCI ACL Data Packet

用于传普通数据(GATT、L2CAP、ATT)。

Host → Controller

Controller → Host

这就是 BLE 大部分数据的流动方式。


4)HCI Synchronous Data Packet

用于 SCO/eSCO(语音)数据

只有当控制器把 SCO 传给 Host 才会用(大部分 BLE 产品不会用)。


HCI 的流控(flow control)

  • Packet-based flow control
  • Data-block-based flow control

Host → Controller:

Host 发 ACL 数据太快,会导致芯片 buffer 满。

解决方法:

  • Host 通过 HCI 命令询问控制器 buffer 大小
  • 控制器回 Event 告诉 Host:我处理完多少包了(HCI_Number_Of_Completed_Packets)
  • Host 根据这个信息控制发送速度

Controller → Host:

Host 也有 buffer

Controller 会通过:

  • HCI_Set_Host_Controller_To_Host_Flow_Control
  • HCI_Host_Buffer_Size
  • HCI_Host_Number_Of_Completed_Packets
  • 简单理解:HCI 保证上下层不会"塞车"。

恒玄芯片 SDK 中的 HCI 对应位置(重点!)

恒玄 SDK 中:

  • Controller(BB、PHY、LMP)都是固化在 ROM 中

  • Host 层由你写的 APP 在 MCU 上运行

  • HCI 通常内部实现,不需要你手写
    典型文件:

    bes_hci_interface.c
    hci_tl.c
    bt_hci_if.c
    bt_stack_task.c

常见 API:

复制代码
hci_send_acl_data()
hci_send_cmd()
hci_recv_event()

如果用 BES 的全功能 SDK,你几乎看不到"裸 HCI"

因为 SDK 已经把 HCI+L2CAP+GATT 全封装好了。

相关推荐
ACP广源盛139246256731 小时前
GSV2125D@ACP#GSV6125#HDMI 2.0 转 DisplayPort 1.4 转换器(带嵌入式 MCU)
嵌入式硬件·计算机外设·音视频
ℳ๓. Sweet4 小时前
【从零开发STM32(HAL版)】一、开发硬件环境准备
stm32·单片机·嵌入式硬件
ACP广源盛139246256734 小时前
GSV2202D@ACP#DisplayPort 1.4 到 HDMI 2.0 转换器(带嵌入式 MCU)
单片机·嵌入式硬件·计算机外设·音视频
梓德原5 小时前
【总结】STM32 SPI DMA 的使用
stm32·单片机·嵌入式硬件
三佛科技-134163842125 小时前
LP3610S开关电源45V同步整流芯片17W (5V 3400MA) 典型应用电路
嵌入式硬件·物联网·智能家居·pcb工艺
@good_good_study6 小时前
STM32 TIM+ADC实验
stm32·单片机
hazy1k6 小时前
MSPM0L1306 从零到入门:第六章 UART —— 让单片机与世界“对话”
stm32·单片机·嵌入式硬件·物联网·51单片机·esp32·iot
qq_7391753697 小时前
开源基于STC8的智能浇花与温湿度报警系统
c语言·stm32·单片机·嵌入式硬件
清月电子7 小时前
充电宝新规适配方案:KT6368A 蓝牙芯片应用技术说明
人工智能·单片机·嵌入式硬件·物联网