Python Matplotlib 绘制 8 种数据编码波形图从 NRZ 到 PPM 的完整实现与工程实践在数字通信和物联网领域数据编码技术是确保信息可靠传输的基础。本文将带您使用 Python 和 Matplotlib 库从零实现八种经典数据编码方式的波形可视化包括 NRZ、曼彻斯特编码、单极性归零码等并提供可直接运行的模块化代码。1. 数据编码基础与环境准备数据编码是将数字信息转换为适合传输的电信号的过程。不同的编码方案在同步能力、抗干扰性和带宽效率等方面各有优劣。我们先配置 Python 环境并准备基础工具函数。首先安装必要的库pip install matplotlib numpy创建基础配置函数import matplotlib.pyplot as plt import numpy as np from typing import List, Tuple def configure_plot(title: str, width: int 10, height: int 6): 配置绘图参数 plt.figure(figsize(width, height)) plt.rcParams[savefig.dpi] 300 plt.rcParams[figure.dpi] 300 plt.title(title, fontsize14, pad20) plt.grid(True, alpha0.3)2. 基础编码方案实现2.1 不归零码 (NRZ)NRZ 是最简单的编码方式用高电平表示1低电平表示0def nrz_encode(bits: List[int], low: float -1, high: float 1) - Tuple[List[float], List[float]]: 生成NRZ编码的坐标点 x, y [], [] for i, bit in enumerate(bits): x.extend([i, i1]) y.extend([high if bit else low]*2) return x, y典型应用场景NRZ 编码简单高效常用于短距离通信和存储系统如硬盘数据记录。2.2 单极性归零码 (Unipolar RZ)与 NRZ 不同RZ 编码在每个比特周期中间会归零def rz_encode(bits: List[int], low: float -1, high: float 1) - Tuple[List[float], List[float]]: 生成单极性归零码坐标点 x, y [], [] for i, bit in enumerate(bits): x.extend([i, i0.5, i0.5, i1]) y.extend([high if bit else low, high if bit else low, low, low]) return x, y提示归零特性使得 RZ 编码可以直接提取时钟信号常用于需要严格同步的场景。3. 同步编码方案实现3.1 曼彻斯特编码曼彻斯特编码通过电平跳变携带数据和时钟信息def manchester_encode(bits: List[int], low: float -1, high: float 1) - Tuple[List[float], List[float]]: 生成曼彻斯特编码坐标点IEEE 802.3标准 x, y [], [] for i, bit in enumerate(bits): x.extend([i, i0.5, i0.5, i1]) if bit: y.extend([high, high, low, low]) # 1: 高→低跳变 else: y.extend([low, low, high, high]) # 0: 低→高跳变 return x, y编码对比表编码类型同步能力带宽需求抗干扰性典型应用NRZ差低一般短距离通信RZ好高较好时钟恢复曼彻斯特优秀最高优秀以太网3.2 差分曼彻斯特编码差分曼彻斯特通过跳变位置编码数据具有更强的抗干扰能力def diff_manchester_encode(bits: List[int], low: float -1, high: float 1) - Tuple[List[float], List[float]]: 生成差分曼彻斯特编码坐标点 x, y [], [] last_level high for i, bit in enumerate(bits): x.extend([i, i0.5, i0.5, i1]) # 比特开始处总是跳变 y.extend([last_level, last_level, -last_level, -last_level]) # 比特中间根据数据决定是否跳变 if not bit: y[-2], y[-1] -last_level, -last_level last_level y[-1] return x, y4. 高级编码方案实现4.1 米勒编码 (Miller)米勒编码通过控制跳变位置提高编码效率def miller_encode(bits: List[int], low: float -1, high: float 1) - Tuple[List[float], List[float]]: 生成米勒编码坐标点 x, y [], [] last_level high for i, bit in enumerate(bits): x.extend([i, i1]) if bit: # 1: 周期中间跳变 x.extend([i0.5, i0.5]) y.extend([last_level, -last_level, -last_level, last_level]) else: # 0: 周期结束跳变 y.extend([last_level, last_level, -last_level, -last_level]) last_level y[-1] return x, y4.2 脉冲位置编码 (PPM)PPM 通过脉冲在时间窗口中的位置编码数据def ppm_encode(bits: List[int], slots: int 4) - Tuple[List[float], List[float]]: 生成脉冲位置编码坐标点 x, y [0], [0] for i in range(0, len(bits), 2): # 每两位编码为一个脉冲位置 pos int(.join(map(str, bits[i:i2])), 2) pulse_pos i pos/slots x.extend([pulse_pos-0.1, pulse_pos, pulse_pos, pulse_pos0.1, i2]) y.extend([0, 1, 1, 0, 0]) return x, y5. 完整实现与可视化将所有编码集成到统一的可视化系统中def visualize_encodings(bits: List[int], save_path: str None): 可视化所有编码方案 encodings [ (NRZ, nrz_encode(bits)), (RZ, rz_encode(bits)), (Manchester, manchester_encode(bits)), (Diff Manchester, diff_manchester_encode(bits)), (Miller, miller_encode(bits)), (PPM, ppm_encode(bits)) ] configure_plot(fEncoding Comparison for Bits: {.join(map(str, bits))}, height12) plt.subplots_adjust(hspace0.5) for i, (name, (x, y)) in enumerate(encodings, 1): plt.subplot(len(encodings), 1, i) plt.plot(x, y, b-, linewidth2) plt.step(x, y, wherepost, colorr, alpha0.5) plt.title(name, pad5) plt.xlim(0, len(bits)) plt.ylim(-1.5, 1.5) plt.grid(True) if save_path: plt.savefig(save_path) plt.show()使用示例if __name__ __main__: # 示例编码学号各位数字之和的二进制表示 student_id 20230001 bit_sum sum(int(d) for d in student_id) bits [int(b) for b in f{bit_sum:08b}] visualize_encodings(bits, encoding_comparison.png)6. 工程实践建议性能优化对于长比特流考虑使用 NumPy 向量化操作替代循环自定义配置通过参数暴露电平幅度、周期长度等可配置项实时应用结合 PyQt 或 Dash 构建交互式编码演示工具测试验证添加单元测试验证编码/解码的正确性def test_manchester(): bits [1, 0, 1, 1, 0] expected_y [1,1,-1,-1, -1,-1,1,1, 1,1,-1,-1, 1,1,-1,-1, -1,-1,1,1] _, y manchester_encode(bits) assert np.allclose(y, expected_y), Manchester编码测试失败通过本文的实现我们不仅掌握了各种编码的原理还构建了可扩展的编码可视化工具。在实际项目中可根据具体通信需求选择合适的编码方案NRZ 适合简单低功耗场景而曼彻斯特编码则适用于需要严格同步的高速通信。