802.11 前导码与 STF 深度解析(含检测算法与 5G 对比)
一份面向软件无线电 / GNU Radio 实操的学习笔记。所有示例尽量给出具体数字,便于复现与发布。
配套代码以
gr-ieee802-11(OFDM WiFi 解码 OOT 模块)与 HackRF 抓包为背景。
目录
- 前导码(Preamble)总览
- [STF 是什么](#STF 是什么)
- [STF 的频域布局(20 MHz 信道)](#STF 的频域布局(20 MHz 信道))
- [STF 调制原理与数据举例](#STF 调制原理与数据举例)
- [STF 检测算法(Schmidl-Cox 延迟自相关)](#STF 检测算法(Schmidl-Cox 延迟自相关))
- [关于 N=64 与 QAM 阶数的澄清](#关于 N=64 与 QAM 阶数的澄清)
- [STF 不携带数据](#STF 不携带数据)
- [5 GHz WiFi 也以 STF 开头](#5 GHz WiFi 也以 STF 开头)
- [5G 蜂窝基站用 PSS 而非 STF](#5G 蜂窝基站用 PSS 而非 STF)
- [PSS 与 STF 检测算法对比](#PSS 与 STF 检测算法对比)
- 附录:源码位置与参考规范
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=+4 和 k=-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_startlib/frame_equalizer_impl.cc:parse_signal解码 Rate / Length / Paritylib/decode_mac.cc:pmt::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 规范整理,示例均可手算复现。