第四节:4FSK 文件收发 视频 GitHub 码云 | 2026-03-16 14:25 | 阅读: 4 ### 深入进阶:从 BFSK 到 4FSK 的高性能全双工通信系统实战 在软件无线电(SDR)的学习路径中,FSK(频移键控)系列是理解数字调制从理论走向实践的最佳切入点。在之前的教程中,我们详细探讨了正交解调的数学基础([Lesson 57](https://beautifulzzzz.com/gnuradio/tutorial/lesson/57))、BFSK 的波形仿真([Lesson 58](https://beautifulzzzz.com/gnuradio/tutorial/lesson/58))以及基于音频 FSK 的数据包传输([Lesson 59](https://beautifulzzzz.com/gnuradio/tutorial/lesson/59))。 本篇博客将通过一个完整的 **4FSK 全双工文件传输系统**,展示如何结合自定义 Python 模块、高性能向量化计算以及 Gardner 同步算法,构建一个工业级的 SDR 通信链路。 </br> ### 一、 4FSK 调制理论:频谱效率的跨越 #### 1. 为什么是 4FSK? 在 [Lesson 58](https://beautifulzzzz.com/gnuradio/tutorial/lesson/58) 中,我们使用的 BFSK 只能在两个频点间切换。而 **4FSK** 属于多进制频移键控(M-FSK),其核心优势在于提高了**带宽效率**: * **二进制(BFSK)**:1 个符号 = 1 个比特 。 * **四进制(4FSK)**:1 个符号 = 2 个比特 。 这意味着在同样的波特率下,4FSK 的信息传输速率是 BFSK 的 2 倍。 </br> #### 2. 映射逻辑与频率规划 本项目中,我们定义了四个符号(Symbol),分别对应四个不同的频率偏移。假设中心频率为 $f_c = 650\text{ kHz}$ : * **符号 0 (00)**:偏移 $-150\text{ kHz}$,即 $500\text{ kHz}$ 。 * **符号 1 (01)**:偏移 $-50\text{ kHz}$,即 $600\text{ kHz}$ 。 * **符号 2 (10)**:偏移 $+50\text{ kHz}$,即 $700\text{ kHz}$ 。 * **符号 3 (11)**:偏移 $+150\text{ kHz}$,即 $800\text{ kHz}$ 。 </br> 通过下面模块实现调制: ![][p2] 通过设置 `fsk_deviation = 150 kHz` 和 `f_spacing = 100 kHz` ,我们确保了四个频点之间有足够的保护带宽,降低了符号间的干扰(ISI)。 </br> ### 二、 发送端:基于 Python Block 的高性能协议封装 不同于 Lesson 59 中简单的 `char_list` 发送,本系统采用了一个更为严谨的 `4FSK Sender Final` 模块。 ![][P3] #### 1. 物理层帧格式 为了在接收端实现零误差同步,每一帧都包含以下结构 : ``` +----------------+--------+-----------------------+------------------------------------------+ | 字段名称 | 字节数 | 内容 / 值 | 说明 | +----------------+--------+-----------------------+------------------------------------------+ | 前导码(Preamble)| 30 | 0x55 (01010101) | 唤醒同步器,在断流后用于重建符号时钟锁 | +----------------+--------+-----------------------+------------------------------------------+ | 同步头(Sync) | 2 | 0xAA 0xBB | 帧起始标志,用于在比特流中定位字节边界 | +----------------+--------+-----------------------+------------------------------------------+ | 序列号(SN) | 1 | 0x00 - 0xFF | 循环计数,接收端依靠此字段进行重试包去重 | +----------------+--------+-----------------------+------------------------------------------+ | 长度(Length) | 1 | 0x00 - 0xFF | 标识 Data 字段的实际字节数 | +----------------+--------+-----------------------+------------------------------------------+ | 数据(Data) | 变长 | UTF-8 字符串 | 实际传输的消息内容 | +----------------+--------+-----------------------+------------------------------------------+ | 校验和(CS) | 1 | Header+Data 的和 | 取累加和的低8位,用于验证数据完整性 | +----------------+--------+-----------------------+------------------------------------------+ | 结束符(End) | 1 | 0xFF | 帧结束标志,辅助解析器判断数据包合法性 | +----------------+--------+-----------------------+------------------------------------------+ | 帧间隙(Gap) | 5+ | 0x55 (01010101) | 确保重试包之间有物理间隔,防止接收端粘包 | +----------------+--------+-----------------------+------------------------------------------+ ``` </br> #### 2. 打断与打散机制 针对文件传输,模块内置了分片逻辑(Payload Size 默认为 36 字节)。 * **打断逻辑**:当系统正在发送大文件时,如果收到新的紧急文本消息,模块会立即清除文件任务并响应新消息。 * **打散处理**:`Unpack/Pack` 逻辑被整合在模块内部,通过控制样点生成率来减小由于 `Repeat` 模块造成的数据突发冲撞,使数据输出更加平滑 。 </br> #### 3. 采用重复编码 可以在 4FSK Sender Final 中调节 Msg_Repeat 和 Data_Repeat,主要是将原属的数据重复 n 遍发送,其中前者是对发送普通信息的重复次数;后者是对发送文件时的重复次数。调节变小可以让文件发送速度变快但成功率变低,否则会变慢变高。 </br> ### 三、 接收端:正交解调与高效切片 接收端的设计吸收了 [Lesson 57](https://beautifulzzzz.com/gnuradio/tutorial/lesson/57) 关于正交解调的精华,并结合了向量化技术。 ![][P4] #### 1. 下变频与预处理 * **Frequency Xlating FIR Filter**:将 650 kHz 的信号平移至基带 (0 Hz),并进行低通滤波 。 * **Simple Squelch**:设置 $-70\text{ dB}$ 阈值,只有当信号强度足够时才开启解调链路,防止底噪导致系统误触发 。 #### 2. 正交解调 (Quadrature Demod) 该模块将频率变化转化为瞬时幅度 。 * **增益计算**:根据公式 $Gain = \frac{f_s}{2\pi \cdot \Delta f}$ 。 * 在 Lesson 57 中提到,合理的增益设置能将输出幅度归一化到 $\pm 1.0$ 之间,这直接影响后续 Symbol Sync 的准确性。 #### 3. 符号同步 (Symbol Sync) 沿用 [Lesson 59](https://beautifulzzzz.com/gnuradio/tutorial/lesson/59) 中详细讨论的 **Gardner 算法** : * **Timing Error Detector (TED)**:通过检测过零点来修正采样相位。 * **Samples per Symbol (SPS)**:从 12 倍过采样降采样至 1 倍(每符号 1 个采样点)。这一步解决了时钟漂移问题,确保提取的是符号中心点的电压。 #### 4. 向量化 4FSK 切片 (Vectorized Slicer) 这是一个基于 NumPy 优化的自定义模块 `vectorized_4fsk_slicer`。 * **逻辑实现**:使用 `np.where` 实现四电平切片,阈值设为 `[-0.75, 0, 0.75]`。 * **性能优势**:相较于 Python 循环,向量化操作极大提升了数据处理吞吐量,能够支撑 MHz 级别的实时采样流。 </br> ### 四、 应用层:全双工文件收发与进度管理 系统的最高层是 `4FSK Receiver Final` 模块,它不仅处理协议解析,还负责复杂的文件重组逻辑。 #### 1. 指令控制流 当发送端发出 `send file:lefa.png size:1234bytes` 这样的指令时,接收端会解析该指令并进入文件模式: * **自动创建文件**:在本地创建 `recv_` 前缀的文件。 * **进度计算**:根据已接收的字节数动态计算百分比,并通过 `msg_out` 端口发布 `Progress: XX%` 消息。 #### 2. 全双工 ZMQ 架构 * **ZMQ PUSH/PULL Sink/Source**:系统使用本地回环地址 `tcp://127.0.0.1:12345` 连接发端和收端 。这种设计使得发送和接收逻辑在 GNU Radio 中相互独立,实现了真正的全双工并发。 [p1]:https://tuchuang.beautifulzzzz.com:3000/?path=202603/4fsk_old_lesson.png [p2]:https://tuchuang.beautifulzzzz.com:3000/?path=202603/4fsk_mod.png [p3]:https://tuchuang.beautifulzzzz.com:3000/?path=202603/4fsk_tx_grc.png [p4]:https://tuchuang.beautifulzzzz.com:3000/?path=202603/4fsk_rx_grc.png