本文整理经典蓝牙(BR/EDR)中 "channel" 概念的分层体系与 5 种物理信道,以及跳频、发现/连接机制中容易混淆的要点。
物理层(PHY, Physical Layer)
-
功能:负责无线射频信号调制、跳频和基带传输。
-
关键特性:
-
工作频段:2.4 GHz ISM 频段(79个1 MHz信道)。
-
调制方式:GFSK(BR)调频、π/4-DQPSK(EDR 2 Mbps)调相、8DPSK(EDR 3 Mbps)调相。
-
FSK:Frequency Shift Keying,频移键控。
-
PSK:Phase Shift Keying,相移键控。
-
跳频扩频(FHSS):1600跳/秒,抗干扰。
-
一、先厘清:"Channel" 是一个被复用的词
蓝牙协议栈从底到顶有四层都叫 channel,含义完全不同,这是初学最容易混淆的地方。
📌 记住这条主线:设备在某个 physical channel (跳频序列)上,用 79 个 RF channel (频点)跳频,建立 physical link ,上面跑 logical transport (ACL/SCO),再由 L2CAP channel 分发给各上层协议。
分层结构
| 层级 | "channel" 指什么 | 数量 / 标识 |
|---|---|---|
| L2CAP channel | 上层协议复用的逻辑数据管道 | 用 CID 标识,可有多条 |
| Logical transport / link | 承载不同流量类型的逻辑通道 | ACL / SCO / eSCO / ASB / PSB / LC 等 |
| Physical link | 一对设备间的 baseband 连接 | --- |
| Physical channel | 跳频序列 + 时序 + access code 定义的射频占用 | 5 种(本文重点) |
另一个易混概念:RF Channel
-
RF channel(射频信道)= 79 个,频率 2402~2480 MHz,间隔 1 MHz。
-
这是纯粹的物理频点概念,是 physical channel 跳频时"落脚"的那些频率。
-
注意:经典蓝牙是 79 个 RF 信道(不是 80)。
二、5 种 Physical Channel
| 物理信道 | 用途 | 跳频特征 |
|---|---|---|
| Basic piconet physical channel | 已连接 piconet 的正常通信 | 全 79 信道跳频,1600 hops/s |
| Adapted piconet physical channel | 同上,但启用 AFH(自适应跳频) | 跳频序列避开受干扰信道(如被 WiFi 占用的) |
| Page scan physical channel | 被连接方等待被 page(寻呼) | 32 频子集,守频慢跳 |
| Inquiry scan physical channel | 可发现设备等待被 inquiry(查询) | 32 频子集,守频慢跳 |
| Synchronization scan physical channel | Connectionless Slave Broadcast 的同步扫描 | 用于无连接广播场景 |
三、Basic vs Adapted:关键区别不是"跳不跳"
⚠️ 常见误区:以为 Basic channel "不能跳频"。实际上 Basic 和 Adapted 都跳频 ,区别在于跳频时用不用得全 79 个信道。
| Basic piconet channel | Adapted piconet channel | |
|---|---|---|
| 跳频? | 跳 | 跳 |
| 用几个信道跳 | 全部 79 个 | 少于 79(剔除坏信道,至少保留 20 个) |
| 跳频序列 | 标准伪随机序列,覆盖全 79 | 把受干扰信道从序列里映射掉,只跳干净信道 |
生命周期:Basic 是起点,Adapted 是升级
连接刚建立 │ ▼ Basic piconet channel(全 79 跳频) ← 每条连接必然先用这个 │ │ master/slave 交换 AFH 信息,评估哪些信道被干扰 ▼ 切换到 Adapted piconet channel(AFH,避开坏信道) ← 可选,若双方支持 AFH
-
每条连接都从 Basic channel 开始------建连时还没做信道评估,只能全 79 跳。
-
若双方都支持 AFH(现代设备基本都支持),再切到 Adapted。
-
若有一方不支持 AFH,或环境无明显干扰,就一直停在 Basic。
-
结论:Basic 没被淘汰,它是每条连接的起点与 AFH 的回退基线;稳态通信多数升级到 Adapted。
真正"守着固定频率、不跳频"的是 page scan / inquiry scan 这类扫描信道,不是 Basic piconet channel。
四、发现/连接为什么不慢:不对称跳频 + Train A/B
只用 32 个信道,不遍历 79
-
inquiry / page 阶段只用 79 里的 32 个信道。
-
这 32 个再分成两个 train:Train A(16 个)+ Train B(16 个)。
不对称跳频是关键
| 角色 | 跳频速度 | 行为 |
|---|---|---|
| 发起方(inquirer / pager) | ~3200 hops/s(每 slot 2 跳) | 疯狂扫频,~10ms 铺满一个 train 的 16 个频率 |
| 扫描方(scanner) | 每 1.28s 才换一个频率 | 准静止,守在某一频率上监听扫描窗口 |
💡 秘诀:不是让扫描方去追频率,而是让发起方在极短时间内把整个 train 铺满。扫描方原地不动就会被"扫过",一个扫描窗口内即命中。
Train A / B 的作用
-
两端时钟可能有偏差,扫描方守的频率不一定落在 Train A 里。
-
发起方先反复发 Train A(覆盖时钟接近的情况),再切 Train B(覆盖偏差大的情况),来回轮换。
-
inquiry 和 page 都用 Train A/B 机制。
inquiry vs page 的差异
| Page | Inquiry | |
|---|---|---|
| 跳频序列种子 | 目标设备 BD_ADDR | GIAC(0x9E8B33) |
| 发起方知道对方相位 | 大致知道 | 完全不知道 |
| 典型耗时 | ~1.28s 内(最坏 ~2.56s) | 通常跑满 ~10.24s 收全设备 |
| 响应处理 | 一对一,直接建连 | 一对多,持续发现更多设备 |
| 退避机制 | 无 | 有随机 backoff,避免多设备同时响应撞车 |
Inquiry Scan 的退避(Random Backoff)机制
⚠️ 强调:被退避(延迟发送)的是 FHS 响应包,不是 inquiry 请求本身。
解决的问题:多台设备可能在同一时刻收到同一个 inquiry 消息,如果它们立刻同时回 FHS 响应,就会在射频上撞车,发起方一个都收不到。Backoff 用随机延迟把这些 FHS 响应在时间上打散。
生效流程:
-
扫描方在 INQUIRY SCAN 守频监听,收到第 1 个匹配 IAC(GIAC/DIAC)的 inquiry ID 包时,不立即回 FHS。
-
生成随机数 Nrand ∈ 0, 1023,退避 Nrand 个 slot(1 slot = 625µs,最长 ≈ 639.375ms)。
-
退避结束后重新进入 INQUIRY SCAN,直到再次收到 inquiry ID 包,这时才发送 FHS 响应包(携带自己的 BD_ADDR、时钟等;若支持 EIR,紧跟一个扩展响应包)。
为什么能防撞车:
-
随机 Nrand:每台设备退避时长不同,FHS 发送时刻被错开,避免同时 fire。
-
退避后"下一次"收到 inquiry 才发 FHS:发起方一直在疯狂扫频(~3200 hops/s,Train A/B 轮换),下一次命中时频点已变,即使两台设备凑巧同时醒来,各自命中的时刻/频率也不同,天然带频率分集,进一步降低碰撞。
-
每台设备一轮只响应一次:响应完退出,不反复占信道。
对比 page 为何无退避:page 是一对一(种子为目标 BD_ADDR,被叫唯一),不存在多设备抢答;inquiry 是一对多,周围所有设备都可能应答,必须靠随机退避错峰。这也是 inquiry 通常要跑满 ~10.24s 收全设备的原因之一------要给多台设备的退避 + 错峰响应留够时间窗口。
深入:Inquiry 的扫描时序与 backoff 的真实代价
① inquiry 的 Train A/B 不是"猜时钟",与 page 含义不同
-
inquiry 的 32 个频点序列种子是 GIAC(0x9E8B33) ,不是任何一方的地址。所有设备用同一张频点表,各自在表里的相位由自己的时钟决定,双方相位无关、也无需对齐。
-
因此 inquiry 是彻底的 clock-agnostic 暴力覆盖:发起方不知道也不需要知道对方时钟,只是把频点表反复全扫,扫描方迟早被扫过。
-
A/B 的划分是时钟比特进位结构的自然产物:一趟 ~10ms 快速 sweep 由低位时钟比特驱动,只能铺满 16 个(= 一个 train);要够到另外 16 个,得等高位比特推进,所以硬件上一次只出得来一个 train,只能分时打。
-
对比 page:pager 有对方时钟的估计值 CLKE,可以把 train 对准估计的醒频------估得准落 A、飘了落 B,这里"时钟接近/偏差大"才是真实语义。page 是"对准 + 兜底",inquiry 是"没得对准,索性两半都扫穿"。
② inquirer 扫描的时间尺度
| 时间尺度 | 发生什么 |
|---|---|
| 312.5µs | 换一个频点(发或听) |
| 625µs(1 slot) | 发 2 个频点 / 听 2 个频点对应的响应频率 |
| 10ms(16 slot) | 把一个 train 的 16 个频点扫完一趟(one pass) |
| 2.56s(≈256 趟) | 同一个 train 猛重复,罩住扫描方 1.28s 守频窗口(覆盖 2×1.28s 确保对齐无关) |
| A↔B 交替 | 覆盖被时钟比特切成两半的全部 32 个频点 |
| ~10.24s | 整个 inquiry 收全周围设备 |
10ms 只是"扫了一趟",远远不够。扫描方准静止、每 ≤1.28s 才开一次很短的扫描窗口,一趟命中概率极低,所以要把同一个 train 死命重复约 2.56s,再换另一半,A/B 来回轮换。
③ backoff 不会放大 inquirer 的接收窗口(重点澄清)
常见误区:以为 FHS 被 backoff 了,发起方就得开一个几百 ms 的大窗口干等。实际不需要------窗口永远是标准 RX slot(625µs)。
-
scanner 收到第 1 个 inquiry ID 包时不回 ,退避 Nrand 个 slot;退避结束后重新守听,直到收到下一个 ID 包,才在其后 625µs 发 FHS。
-
FHS 的发送时刻锁定在**"触发它的那个 ID 包"后 625µs**,而那个 ID 包是发起方刚发出的 → FHS 恰好落进发起方紧跟的标准 RX slot。
-
所以 backoff 让 scanner"改天再回"(响应未来某一轮 inquiry),而不是让 inquirer"一直等着这次"。代价从"空间(窗口宽度)"转移到"时间(发起方要多扫很多轮、总时长更长)",这也是 inquiry 要跑满 ~10.24s、train 重复上百次的原因之一。
-
别混淆两个窗口:scanner 侧的 inquiry scan window(Tw_inquiry_scan,通常 ≥11.25ms) 要够宽,是为了完整接住至少一整趟 train 的 ID 包,与 backoff 无关;inquirer 侧的 **RX slot(625µs)**是标准大小,永不变。
这 32 个信道是什么?从哪来?固不固定?
结论:这 32 个不是硬编码的某几个固定频率,而是从 79 个 RF 信道里、由 access code(地址)经跳频选择算法算出的子集。"固不固定"要分两个维度:集合固定,但当前落点和 A/B 划分随时钟滚动。
① 由"地址 + 时钟"两类输入算出
跳频选择算法(hop selection kernel)吃两类输入:
-
地址比特 (access code 里的 LAP/UAP)→ 决定挑哪 32 个频点及其排列。
-
时钟比特 (CLKN)→ 决定此刻走到序列的哪个位置。
所以这 32 个频点散布在 2402~2480 MHz 里、彼此散开(为频率分集),不是连续一段,也不是写死的 MHz。
② 按场景看集合是否固定
| 场景 | 种子(决定 32 个) | 集合是否固定 |
|---|---|---|
| General Inquiry | GIAC = 0x9E8B33(全球唯一固定) | 固定,全世界所有设备用同一组 ← 陌生设备能互认的原因 |
| Limited Inquiry | LIAC = 0x9E8B00 | 另一组固定的 32 个(与 GIAC 组不同) |
| Page(寻呼) | 被叫设备 BD_ADDR(LAP) | 每个目标一组,各不相同 |
-
Inquiry 的 32 个是"公共频道":种子是固定的 GIAC,这组 32 个公开、固定、人人相同,所以互不相识的设备也能碰上。
-
Page 的 32 个是"专属频道":种子是被叫设备地址,因目标而异,只有知道对方地址才算得出去哪找它。
③ 集合固定 ≠ 位置固定
对同一个 access code:
-
哪 32 个频点、整体排列 → 由地址定死,不随时钟变。
-
此刻落在哪一个、Train A/B 如何切分 → 由时钟比特(经典蓝牙 CLKN16--12) 决定,随时间滚动。
比喻:32 个频点像一圈固定的座位(座位表由地址定死),时钟决定"此刻指针转到哪个座位"。座位没变,指针在动。Train A(16)/ B(16)就是把这一圈切成前后两半,切点与当前指向由时钟决定。
④ 现代设备可能少于 32
基线是 32,但:早期某些国家用过 23-hop 缩减系统(现已基本淘汰);现代规范给 inquiry/page 也引入 AFH 自适应,可把受干扰的 wake-up 频点从这 32 个里剔除或重映射------实际跳的可能少于 32 或换了成员,但"以 32 为基准子集"的框架不变。
五、Access Code 与 Inquiry 补充要点
-
三种 access code:CAC(piconet 内通信,种子=master LAP)、DAC(paging,种子=被叫 LAP)、IAC(inquiry)。
-
GIAC = 0x9E8B33 ,唯一且固定,通用发现,绝大多数场景只用它。
-
DIAC 取值范围 0x9E8B00~0x9E8B3F,常用的是 LIAC = 0x9E8B00(有限发现,用于主动配对)。
-
DIAC 与 Class of Device(CoD)无对应关系:DIAC 是链路层"暗号"决定响应与否(无类型语义);设备类型过滤靠上层解析响应里的 CoD 字段实现。
六、一句话总结
Physical channel 有 5 种(basic / adapted piconet, page scan, inquiry scan, synchronization scan)。
别把它和 RF channel(79 个频点)、logical transport(ACL/SCO)、L2CAP channel(CID) 混为一谈。
Basic 与 Adapted 都跳频,区别是用不用全 79 个信道;Basic 是起点,Adapted 是 AFH 抗干扰升级。
发现/连接不慢,靠的是不对称跳频 + Train A/B 轮换,只用 32 个信道而非全部。