802.11 前导码与 STF 深度解析(含检测算法与 5G 对比

802.11 前导码与 STF 深度解析(含检测算法与 5G 对比)

一份面向软件无线电 / GNU Radio 实操的学习笔记。所有示例尽量给出具体数字,便于复现与发布。

配套代码以 gr-ieee802-11(OFDM WiFi 解码 OOT 模块)与 HackRF 抓包为背景。


目录

  1. 前导码(Preamble)总览
  2. [STF 是什么](#STF 是什么)
  3. [STF 的频域布局(20 MHz 信道)](#STF 的频域布局(20 MHz 信道))
  4. [STF 调制原理与数据举例](#STF 调制原理与数据举例)
  5. [STF 检测算法(Schmidl-Cox 延迟自相关)](#STF 检测算法(Schmidl-Cox 延迟自相关))
  6. [关于 N=64 与 QAM 阶数的澄清](#关于 N=64 与 QAM 阶数的澄清)
  7. [STF 不携带数据](#STF 不携带数据)
  8. [5 GHz WiFi 也以 STF 开头](#5 GHz WiFi 也以 STF 开头)
  9. [5G 蜂窝基站用 PSS 而非 STF](#5G 蜂窝基站用 PSS 而非 STF)
  10. [PSS 与 STF 检测算法对比](#PSS 与 STF 检测算法对比)
  11. 附录:源码位置与参考规范

1. 前导码(Preamble)总览

在 802.11 OFDM PHY(Clause 17 / 19)里,每个帧的空中接口开头是一段前导码,接收机靠它完成「发现帧 → 粗同步 → 精同步 → 信道估计 → 读帧头」的全过程:

复制代码
STF   LTF        SIGNAL     DATA 符号1   DATA 符号2  ...  DATA 符号M
8µs   8µs        4µs        ───── 用户数据在这里 ─────
已知BPSK 已知BPSK  头(速率/长度)  QAM(每子载波扛数据)
  ↓同步     ↓信道估计   ↓告诉接收机     ↓ 这里才能解出 QPSK/64-QAM
  0 bit     0 bit      24 bit       用户 payload
  • STF(Short Training Field):包检测、AGC、粗定时、粗频偏(CFO)。
  • LTF(Long Training Field):精细频偏、信道估计(CSI)。
  • SIGNAL:24-bit 帧头(Rate 4 / Reserved 1 / Length 12 / Parity 1 / Tail 6),BPSK 1/2。
  • DATA:真正的用户数据,每子载波是 QAM 符号。

2. STF 是什么

STF = Short Training Field(短训练字段)

  • 名字里的 Training = 「训练序列」:接收端已知这段固定重复的波形,用来训练/校准接收机,不传用户数据。
  • 名字里的 Short = 它由 16 个采样(0.8 µs)的短序列 S 重复 10 次构成(10 × 0.8 µs = 8 µs)。相对地 LTF 用 64 采样长序列(所以叫 Long)。
  • 这 16 采样的周期性,正是 sync_short 用「延迟 16 做自相关」检测它的物理基础。

3. STF 的频域布局(20 MHz 信道)

20 MHz 信道做 64 点 FFT ,子载波间隔 = 20 MHz / 64 = 312.5 kHz 。子载波索引 k−32, +31

  • k = 0 是 DC(直流,必须置零)
  • 可用数据子载波:k = −26 ... −1, +1 ... +26(共 52 个)

STF 只点亮 12 个子载波(BPSK ±1,间隔 4 个取一个,跳过 DC):

复制代码
子载波 k :  -24   -20   -16   -12    -8    -4    |   +4    +8   +12   +16   +20   +24
频率(MHz): -7.5  -6.25  -5   -3.75  -2.5  -1.25  | +1.25  +2.5  +3.75  +5   +6.25  +7.5

换算:频率 = k × 312.5 kHz,例如 k = ±24 → ±7.5 MHz

要点:

  • 对称居中:能量关于 DC(信道正中心 5240 MHz)左右对称,最远到 ±7.5 MHz,正好落在 20 MHz 信道中心区域(整个 OFDM 占用约 ±8.125 MHz,边缘为保护带)。
  • 不是铺满:STF 是一把稀疏的「梳子」------DC 附近的 ±1/±2/±3 不用,最外层 ±25~±28 在 STF 阶段也不点亮。铺满 52 子载波要到 LTF/DATA 阶段。

频率轴直观图(横轴 0 = 信道中心):

复制代码
MHz:   -8   -6   -4   -2    0   +2   +4   +6   +8
      |           *   *  |  |  *   *           |
           *       *     |  |     *       *
               *         |  |         *
                         DC(空)
* = STF 子载波   中间空着 DC 和邻近的 ±1~±3

4. STF 调制原理与数据举例

4.1 原理

STF 的每个子载波用 BPSK(二相移相键控) 调制,取值固定为 ±1(相位 0° 或 180°),且这 12 个 ±1 是规范规定好的「已知图案」(见 802.11 Table 17-4),不携带任何用户数据。

OFDM 把频域符号变回时域(IFFT):

复制代码
          1   N-1
s[n] = ---- · Σ  X[k] · e^{j·2π·k·n/N}      n = 0..63,  N = 64
          N   k=0

STF 里只有 12 个子载波非零:X[k] = ±1(其余 X[k] = 0)。因为占用的子载波都是 4 的倍数(±4, ±8, ... ±24),算出的 s[n]16 个采样重复一次 → 这 16 个采样即短序列 S,重复 10 次 = 8 µs STF。

4.2 数据举例:一对子载波怎么「调制」出波形

拿最简单的一对 对称子载波 k=+4k=-4 举例(真实 STF 是 6 对,原理相同)。

(A)两个都是 +1(BPSK = +1)

复制代码
s[n] = (1/64)[ e^{j2π·4·n/64}  +  e^{-j2π·4·n/64} ]
     = (1/32)·cos(π·n/8)         ← 实数余弦,周期 16 采样
n cos(π·n/8) sn = (1/32)·cos(π·n/8)
0 1.0000 +0.03125
1 0.9239 +0.02887
2 0.7071 +0.02210
3 0.3827 +0.01196
4 0.0000 0
8 −1.0000 −0.03125

→ BPSK 取 +1 时,这对子载波「调制」出的时域波形是一段实数余弦波,周期 16 采样。

(B)把 k=−4 翻成 −1(BPSK = −1)

复制代码
s[n] = (1/64)[ e^{+j2π·4·n/64}  −  e^{-j2π·4·n/64} ]
     = (1/32)·j·sin(π·n/8)       ← 变成纯虚数正弦

只把那个 ±1 从 +1 改成 −1,波形就从「实数余弦」变成「虚数正弦」。这就是 STF 调制的本质:每个 ±1 决定该频率分量贡献 cos 还是 sin(相位 0° 还是 180°)。

4.3 回到真实 STF:6 对叠加

真实 STF 是 6 对(±4, ±8, ±12, ±16, ±20, ±24),每对按规范给定的 ±1 取值,各自贡献一项 (1/32)·cos 或 (1/32)·j·sin,6 项相加得 16 采样构成的 S

复制代码
S[n] = 各对余弦/正弦项之和   (c ∈ {+1,−1} 来自规范 Table 17-4)
STF 时域 = S S S S S S S S S S    (S 重复 10 次,共 160 采样 = 8 µs)

注:gr-ieee802-11/utils/sync_words.py 里定义了时域 64 采样版本的 STF(short 元组),其内部样本形如 1+1j-1-1j,正是上述 BPSK 子载波经 IFFT 后的结果。接收端的 sync_short 并不需要这张表------下文解释原因。


5. STF 检测算法(Schmidl-Cox 延迟自相关)

5.1 公式

核心思想:STF 每 16 采样重复一次,所以把信号和它自己错开 16 采样比,重复段会对得上、出现大相关峰。

复制代码
C(d) = Σ_{k=0}^{15} r[d+k] · conj(r[d+k+16])      ← 延迟-16 自相关(复数)
P1(d) = Σ_{k=0}^{15} |r[d+k]|²                    ← 窗口 A 功率
P2(d) = Σ_{k=0}^{15} |r[d+k+16]|²                ← 窗口 B 功率
M(d) = |C(d)|² / (P1·P2)                          ← 归一化相关,∈ [0, 1]
  • 平方 |C|² 再除以 P1·P2 把信号强度归一掉 → 阈值在 −40 dBm 和 −70 dBm 下同样适用。
  • arg(C)/16 给出粗频偏 CFO(残留 Δf 的估计)。

5.2 sync_short.cc 状态机(源码逻辑)

gr-ieee802-11/lib/sync_short.cc 实现 SEARCH → COPY 状态机:

复制代码
读 in_cor(归一化相关 M,来自 blocks_divide)和 in_abs(复数相位,来自 moving_average)
if in_cor[i] > d_threshold(默认 0.56):   d_plateau++
if d_plateau >= MIN_PLATEAU(默认 2):     → COPY 状态
    d_freq_offset = arg(in_abs[i]) / 16
    插入 stream tag,key = "wifi_start"
    MIN_GAP = 480, MAX_SAMPLES = 540*80  (防重复触发 / 超时)

min_plateau=2 表示相关峰要持续 ≥2 采样,滤掉单采样噪声毛刺。

5.3 具体数值举例(可手算验证)

取一个周期恰为 16 的伪随机 ±1 短序列(真实 STF 的 16 采样 S 结构类似,检测数学完全一致):

复制代码
S = [ 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1 ]   (16 个采样)
接收信号 r = S 重复两次(32 采样)

(对齐 d=0) 窗口 A = 窗口 B = S:

复制代码
C(0) = Σ S[k]·S[k] = Σ (±1)² = 16
P1 = P2 = Σ |S[k]|² = 16
M(0) = 16² / (16·16) = 256 / 256 = 1.0        ← 完美峰值

(错开 1 采样 d=1) 窗口 B 变成 S 循环移 1 位:

复制代码
S[k+1] = [ -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1 ]
逐点乘积 S[k]·S[k+1] = -1,-1,+1,-1,-1,-1,+1,-1,+1,-1,+1,-1,-1,-1,-1,-1
C(1) = 4×(+1) + 12×(−1) = −8
M(1) = (−8)² / (16·16) = 64 / 256 = 0.25       ← 明显低于峰值

(纯噪声窗口) 无周期性 → 各乘积相位随机、互相抵消 → M ≈ 0

→ 接收机看到 M 从 ~0 跳到 ~1.0 并持续 ≥2 采样,即判定「抓到 STF」,在 M 峰值处打 wifi_start 标签。后续 sync_long已知 LTF 序列做互相关,给出精定时与精频偏。


6. 关于 N=64 与 QAM 阶数的澄清

常见误区:「N=64 表示最多 64 个子载波,意味着最大 QAM64?」------不对,这是两个独立维度

概念 决定什么 802.11a 的值
N=64(IFFT 点数) 子载波数量 / 信道带宽 64 点 FFT → 20 MHz,52 可用子载波
64-QAM(调制阶数) 每子载波携带几位 最高调制,1 子载波扛 6 bit
  • IFFT 只负责把 64 个频域符号搬成时域,不关心 Xk 里是 BPSK 还是 64-QAM。
  • 你完全可以用 64 点 IFFT + 最低档 BPSK ,或 64 点 IFFT + 最高档 64-QAM,IFFT 点数不变。

反例(打破「巧合」):

  • 802.11ac(80 MHz):256 点 IFFT,支持 256-QAM
  • 802.11ax(HE):256/512 点 IFFT,支持 1024-QAM

→ FFT 点数从 64 涨到 256/512,QAM 从 64 涨到 256/1024,二者各自独立增长。802.11a 里它俩都顶到 64 只是命名巧合


7. STF 不携带数据

STF 上的 12 个子载波是 BPSK 固定图案,收发双方都预先知道 → 熵为 0,没有信息量可解。STF 对接收机是「参考音调」,不是「消息」。

  • STF / LTF :已知 BPSK 图案 → 0 个数据比特,纯同步/信道估计。
  • SIGNAL :1 个 OFDM 符号,BPSK 1/2,24 bit(帧头:Rate/Length/Parity/Tail)→ 告诉接收机后面 DATA 用啥速率、多长,不是用户数据
  • DATA :从这里开始,每个 OFDM 符号的 48 个数据子载波各自扛一个 QAM 符号。

每帧可解数据量:

复制代码
M_data 符号数  = 由 SIGNAL 的 Length(帧字节数)算出
每符号数据子载波 = 48
每子载波比特    = 调制阶数 (BPSK=1, QPSK=2, 16QAM=4, 64QAM=6)

例:encoding:4 - length:32 - symbols:3(Probe Request)
    → 3 个 DATA 符号,对应那 32 字节 MAC 帧 + 开销

你在 Wireshark 看到的每个 MAC 帧,都是从 DATA 符号解出来的,跟 STF 无关。


8. 5 GHz WiFi 也以 STF 开头

是的。 STF 是 802.11 OFDM 前导码的一部分,与频段(2.4G 还是 5G)无关。5 GHz 只跑 OFDM 系列 PHY(11a / 11g ERP-OFDM / 11n HT / 11ac VHT / 11ax HE),而 11b(CCK) 只在 2.4 GHz。所有 OFDM 帧都以 STF 开头。

新协议在前面加了一段兼容旧设备的 Legacy 前导码 (本身就是标准 STF),所以即便后面是 VHT/HE 高速数据,最前面的 L-STF 仍是标准 OFDM STF

协议 5G? 帧开头
11a L-STF → L-LTF → L-SIG → DATA
11n HT L-STF → L-LTF → L-SIG → HT-SIG → HT-LTF → HT-DATA
11ac VHT L-STF → L-LTF → L-SIG → VHT-SIG-A → VHT-STF → ... → VHT-DATA
11ax HE L-STF → L-LTF → L-SIG → ... → HE-DATA
11b (CCK) ❌仅2.4G 无 STF(长/短同步码)

实操联系(HackRF + gr-ieee802-11):

  • AP 的 5G Beacon(0x0008)是 OFDM → 有 STF → 能检测并解码(把默认设成 ch48 / 5240 MHz 后可见)。
  • 路由器→手机的数据帧是 VHT/HE → 有 L-STF(sync_short 能检测),但 DATA 是 VHT → gr-ieee802-11 解不出(它只支持 legacy OFDM)。

9. 5G 蜂窝基站用 PSS 而非 STF

「STF」是 802.11(WiFi)专有名词。5G 蜂窝(NR)基站不用 STF,但干「同步/训练」同一件事的结构叫 PSS / SSS / PBCH(合称 SSB)

5G 基站(gNodeB)周期广播 SSB(Synchronization Signal Block)

NR 组件 作用 对应 WiFi 里的谁
PSS(主同步信号) 粗定时、粗频偏、小区 ID 组 STF
SSS(辅同步信号) 小区 ID(扇区)、帧定时 ≈ STF + 部分 SIGNAL
PBCH(物理广播信道) 携带 MIB(系统帧号、子载波间隔等) SIGNAL 字段
  • 底层波形一样 :5G NR 下行用 CP-OFDM(带循环前缀的 OFDM),和 WiFi OFDM 同宗(子载波 + IFFT)。
  • 同步信号不同 :PSS 是长度-127 的 BPSK m 序列(生成多项式 x⁷+x⁴+1,3 种循环移位对应 N_ID^(2) = 0/1/2),占 SSB 中央 127 个子载波。接收机用互相关/匹配滤波检测,而非 WiFi 的周期性自相关。
  • 信道估计(WiFi 靠 LTF) :5G 用 DM-RS (插在 DATA 里)和 CRS(LTE 用)。

10. PSS 与 STF 检测算法对比

10.1 核心区别

  • STF 检测 = 盲周期自相关:不知道具体序列,只要信号里存在「每 16 采样重复」就触发。
  • PSS 检测 = 已知序列匹配滤波:拿 3 条固定模板去互相关,对上了出峰,同时认出是哪个小区。

10.2 STF 检测(Schmidl-Cox 自相关,复习)

复制代码
已知: 只有重复周期 D=16(无需知道 ±1 图案)
C(d) = Σ r[d+k]·conj(r[d+k+16])   ;   M = |C|²/(P1·P2)
判定: M > 阈值 且 持续 ≥ min_plateau → 抓到 STF
输出: 粗定时 + 粗 CFO = arg(C)/16

10.3 PSS 检测(匹配滤波 / 互相关)

复制代码
接收端本地生成 3 条候选 PSS 时域序列  pss_0 / pss_1 / pss_2
Λ_m(τ) = Σ_n  r[τ+n] · conj(pss_m[n])      ← 匹配滤波
峰值 τ* = argmax |Λ_m(τ)|  →  PSS 定时位置
哪条峰最大 → N_ID^(2)(小区 ID 一部分)
CFO: 由 127 子载波相位斜率 或 CP 相关估出

10.4 逐项对比表

维度 STF(WiFi) PSS(5G NR)
检测本质 延迟自相关(blind) 互相关 / 匹配滤波(known)
是否需已知序列 否,只要知道周期 16 是,必须生成本地 PSS 模板
输出 粗定时 + 粗 CFO 定时 + CFO + 小区 ID
能否区分基站 不能(所有 STF 一样) 能(3 种 PSS → 区分 PCI 组)
大频偏鲁棒性 强(周期结构对 CFO 不敏感) 较弱(大 CFO 让相关峰移位,常需先粗纠或扫 CFO 假设)
定时精度 粗(靠后续 LTF 精修) 较精(相关峰直接给符号边界)
计算量 极小(滑动自相关) 较大(对 3 条序列相关,常配 FFT 快速相关)
检测后动作 sync_long 用 LTF 精修 交 SSS 解完整 PCI,再解 PBCH(MIB)

10.5 一个关键共同点:两者都是「两段式」

复制代码
WiFi:  STF 自相关(粗定时)  ──→  LTF 已知序列相关(精定时+信道估计)
5G:    CP 自相关(粗定时,可选)  ──→  PSS 匹配滤波(定时+ID)  ──→  SSS/PBCH
  • WiFi 把「粗同步」塞进 STF 的周期性自相关,把「精同步+识别」留给 LTF 已知序列。
  • 5G 把「识别小区」提前到 PSS(蜂窝要区分成千上万基站),PSS 一上来就是已知序列匹配;粗定时可用 CP 自相关辅助(和 STF 思路异曲同工)。

10.6 PSS 相关峰小例子

本地模板 pss(127 点 BPSK,幅度 ±1)。接收端在正确偏移 τ 收到干净 PSS 加噪声:

复制代码
Λ(τ) = Σ pss[n]·conj(pss[n] + noise[n])
     = Σ|pss[n]|²  +  Σ pss[n]·conj(noise[n])
     = 127          +  小随机量          ← 真位置 τ 处出现大峰值
错误偏移 τ' :  Λ(τ') ≈ 0 + 随机量        ← 无峰

对比 STF:STF 不生成模板,算 Σ r[k]·conj(r[k+16])------信号自己和自己错开 16 比 ;PSS 是接收信号和已知模板比


11. 附录:源码位置与参考规范

gr-ieee802-11 相关源码

  • lib/sync_short.cc:STF 检测状态机(阈值 0.56、min_plateau 2、wifi_start 标签、CFO = arg/16)
  • lib/sync_long.cc:LTF 已知序列互相关,精定时 + 精频偏,重发 wifi_start
  • lib/frame_equalizer_impl.ccparse_signal 解码 Rate / Length / Parity
  • lib/decode_mac.ccpmt::cons(meta, blob) 输出 MAC 帧
  • utils/sync_words.py:时域 STF/LTF 序列定义(验证 STF 调制用)

参考规范

  • IEEE 802.11-2016:Clause 17(11a OFDM PHY)、Clause 19(11g ERP-OFDM)、Table 17-4(STF 12 子载波 BPSK 取值)、17.3.3(STF 定义)
  • 3GPP TS 38.211:7.4.2(NR PSS/SSS/PBCH 序列与资源映射)
  • Schmidl & Cox, "Robust Frequency and Timing Synchronization for OFDM", 1997(延迟自相关经典论文)

本文基于 gr-ieee802-11 源码研习与 802.11 / 5G 规范整理,示例均可手算复现。

相关推荐
fail_to_code2 小时前
感受deepseek-harness那极端的工程纪律性
人工智能
咖啡星人k2 小时前
Vibe Coding 实战:用 MonkeyCode 一个下午做出可玩的小游戏
人工智能
正经教主2 小时前
AI提示词工程(进阶)第11课:结构化输出与格式化控制
人工智能
GGBond今天继续上班2 小时前
给 DeepSeek Harness 写了个生图插件,补上了原生对话生图能力
人工智能·github·deepseek
AI刀刀2 小时前
Kimi 文档导出格式错乱、排版丢失、导出报错?AI 导出鸭一键智能适配,稳定输出规范 Word、PDF,高效解决各类导出难题
人工智能·pdf·word·ai导出鸭
love530love2 小时前
虚拟显示驱动导致 Photoshop / Camera Raw 卡死?OrayIddDriver 的锅
运维·人工智能·ui·photoshop·orayidddriver·hags 调度
shepherd1112 小时前
国产模型越来越强了:DeepSeek V4、Kimi K3 与 GLM 最新进展
人工智能·llm·ai编程
星火10242 小时前
【LangChain4j系列08】Agentic AI 多智能体协作
人工智能·后端
烟雨江南7852 小时前
离线语音识别为什么一到本地部署,准确率反而会变?
人工智能·语音识别