简介:这份资源面向通信工程、电子信息类专业学生及无线通信入门研究者,围绕QPSK、DQPSK与OFDM三种核心调制技术展开,重点解决在加性高斯白噪声信道下比较DQPSK与QPSK误码性能的仿真需求。压缩包共12个文件,以8个MATLAB源码文件(.m)为主体,另含3个自动备份文件(.asv)和1个图形结果文件(.fig),整体约13KB,体积轻量便于快速运行与二次修改。源码覆盖高斯噪声生成、QPSK与DQPSK调制解调、误码率计算及OFDM系统仿真等模块,可帮助读者绘制误码率随信噪比变化的曲线,直观理解差分调制相对绝对相位调制的抗噪优势,以及OFDM多载波传输对抗多径衰落的基本原理。目前已有116人学习,适合作为通信原理课程实验、课程设计或相关课题的参考素材,通过调整信噪比等参数即可复现并拓展仿真结论。
1. 从误码率曲线切入:这套 QPSK/DQPSK/OFDM 仿真包到底能跑出什么
做链路预算或者写通信原理实验报告时,最怕的不是公式推不出来,而是手里没有一套能直接跑、能改参数、能出 BER 曲线的 MATLAB 脚本。QPSK-DQPSK-OFDM.rar 就是干这个的:它把 QPSK、DQPSK 以及 OFDM 加高斯信道这几件事拆成了独立可运行的 .m 文件,核心目标只有一个——在加性高斯白噪声信道下,把两种调制方式的误码性能拉到同一张图里对比。包里能看到 gngauss.m、cm_sm32.m、cm_dpske.m、cm_sm34.m、qpskdqpsk.m、Qfunct.m、OFDM3.m 这些脚本,还有 qpsk.fig 这种现成的眼图/星座图窗口文件。适合谁?正在做通信课程设计、需要快速验证 DQPSK 相对 QPSK 在 AWGN 下到底差几个 dB 的人,以及想拿 OFDM3.m 当骨架去改子载波数和循环前缀的新手。它不教你推公式,但能让你在半小时内看到误码率随信噪比变化的真实曲线。
2. 先分清 QPSK 与 DQPSK 的判决逻辑:为什么差分解调在 AWGN 下反而吃亏
2.1 绝对相位与差分相位的数学差别
QPSK 每个符号的相位是绝对的,映射关系通常是 00→π/4、01→3π/4、10→5π/4、11→7π/4(具体看 cm_sm32.m 里的映射表)。接收端只要信噪比够,直接对接收符号做相位判决就能恢复比特。DQPSK 不一样,它传的是相邻符号的相位差:当前符号相位 = 前一符号相位 + Δθ,Δθ 取 π/4、3π/4、5π/4、7π/4 四个值之一。这意味着接收端不需要恢复绝对相位参考,只要比较前后两个符号的相位差就能判决。代价是差分检测会引入“错误传播”——前一个符号判错,后一个符号的相位差也跟着错,误码率曲线在低信噪比区间会明显翘起来。
2.2 在 AWGN 下两者的理论差距
加性高斯白噪声信道没有多径、没有相位旋转,只叠加零均值高斯噪声。这种条件下,QPSK 的相干检测是最优的,理论 BER = Q(√(2Eb/N0))。DQPSK 用差分检测时,理论 BER 近似为 2Q(√(2Eb/N0))·[1 - Q(√(2Eb/N0))],在 BER=10^-3 附近大约比 QPSK 差 2~3 dB。这个差距就是 qpskdqpsk.m 要跑出来的核心结论。如果你在仿真里看到 DQPSK 只差 0.5 dB,大概率是符号同步没对齐或者噪声功率归一化写错了。
2.3 用 cm_sm32.m 和 cm_dpske.m 做映射与差分编码
cm_sm32.m 负责 QPSK 的符号映射,cm_dpske.m 负责 DQPSK 的差分编码。常见做法是先把随机比特流按每两个比特分组,查表得到相位增量,再累加到前一符号相位上。下面这段代码展示了如何调用这两个函数生成基带符号:
% 生成 10000 个 QPSK 符号和对应的 DQPSK 差分符号 N = 10000; bits = randi([0 1], 2*N, 1); % 每符号 2 比特 qpsk_sym = cm_sm32(bits); % QPSK 绝对相位映射 dqpsk_sym = cm_dpske(bits); % DQPSK 差分编码输出 % 检查平均功率,两者都应为 1 fprintf('QPSK 平均功率: %.4f\n', mean(abs(qpsk_sym).^2)); fprintf('DQPSK 平均功率: %.4f\n', mean(abs(dqpsk_sym).^2));逻辑说明:cm_sm32 内部把 00/01/10/11 映射到四个单位幅度复符号上,cm_dpske 则先做差分相位累加再取指数。参数说明:输入 bits 长度必须是偶数,否则 cm_sm32 会报维度不匹配;输出符号的幅度都是 1,方便后续直接加高斯噪声而不需要额外功率归一化。
2.4 加高斯信道与误码统计的完整链路
gngauss.m 是噪声发生器,通常接收一个信噪比参数,返回实部和虚部独立的高斯随机数。Qfunct.m 是 Q 函数实现,用来算理论误码率做对比。qpskdqpsk.m 是主脚本,它循环多个 Eb/N0 点,每个点跑蒙特卡洛仿真,最后画出两条 BER 曲线。运行前确认 gngauss.m 里的噪声功率计算方式:常见写法是 noise_var = 1/(2*10^(EbN0/10)),因为复高斯噪声的实部和虚部各占一半功率。如果这里写成 1/10^(EbN0/10),仿真出来的 BER 会整体偏低 3 dB,这就是典型的翻车点。
3. OFDM3.m 怎么把 DQPSK 塞进多载波:子载波映射与循环前缀的实操
3.1 OFDM 基带链路的模块拆解
OFDM3.m 是一个完整的 OFDM 基带仿真脚本,典型流程是:比特生成 → 调制映射(QPSK 或 DQPSK)→ 串并转换 → IFFT → 加循环前缀 → 并串转换 → 加高斯噪声 → 去循环前缀 → FFT → 信道均衡(AWGN 下可省略)→ 解调判决 → 误码统计。这个脚本里 DQPSK 的用法和单载波不同:差分编码是在频域做的,也就是对相邻子载波上的符号做差分,而不是相邻 OFDM 符号之间。这样做的好处是接收端可以在一个 OFDM 符号内完成差分检测,不需要跨符号记忆。
3.2 子载波数量与循环前缀长度的参数选择
OFDM3.m 里通常有 N_fft 和 N_cp 两个变量。N_fft 是 IFFT 点数,常见取 64、128、256;N_cp 是循环前缀长度,一般取 N_fft 的 1/4 到 1/8。在 AWGN 信道下,循环前缀其实不发挥作用(因为没有多径),但它会消耗功率和带宽。如果你只想对比 QPSK 和 DQPSK 在 OFDM 里的误码性能,可以把 N_cp 设为 0 来加快仿真速度。但如果你后面要扩展到多径信道,N_cp 必须大于信道最大时延扩展对应的采样点数,否则会出现 ISI 导致误码率曲线出现错误平台。
3.3 用 OFDM3.m 跑一次完整仿真的步骤
第一步,打开 OFDM3.m,确认调制方式开关变量(通常叫 mod_type 或类似名字)设置为 ‘DQPSK’。第二步,设置 Eb/N0 范围,比如 0:2:12 dB。第三步,设置每个信噪比点下的 OFDM 符号数,建议至少 1000 个符号以保证统计精度。第四步,运行脚本,观察输出的 BER 曲线和星座图。下面是一个简化的调用示例:
% OFDM3.m 关键参数设置(在脚本开头修改) N_fft = 64; % FFT 点数 N_cp = 16; % 循环前缀长度 mod_type = 'DQPSK'; % 可选 'QPSK' 或 'DQPSK' EbN0_dB = 0:2:12; % 信噪比扫描范围 num_symbols = 2000; % 每个 SNR 点的 OFDM 符号数 % 运行后自动绘制 BER 曲线 run('OFDM3.m');逻辑说明:OFDM3.m 内部会循环 EbN0_dB 中的每个值,生成对应数量的 OFDM 符号,加噪后解调,累计误码数。参数说明:num_symbols 越大曲线越平滑,但耗时线性增长;N_fft 越大频谱效率越高但对相位噪声越敏感,AWGN 下影响不大。
3.4 星座图与眼图的验证方法
包里带了 qpsk.fig 和 qpsk.m,qpsk.m 应该是用来画 QPSK 星座图或眼图的脚本。运行 qpsk.m 后会弹出 qpsk.fig 窗口,里面通常是理想星座点和接收端带噪星座点的对比。验证 DQPSK 差分编码是否正确,可以看接收端差分检测后的星座点是否仍然落在四个标准相位上。如果星座点旋转了 45 度,说明差分相位参考没对齐;如果星座点发散成圆环,说明噪声功率设置过大或者符号同步有偏移。
4. 避坑与排查:跑 BER 曲线时最容易翻车的五个地方
4.1 现象:DQPSK 误码率比 QPSK 还低
原因:差分编码的初始参考相位没有随机化,或者蒙特卡洛仿真中前后符号的相关性被人为破坏。解决:在 cm_dpske.m 里确认第一个符号的参考相位是随机的(通常取 0 或 π/4 均可,但不能固定为某个特定值导致统计偏差),并检查 qpskdqpsk.m 中是否对每个 SNR 点重新生成了独立的比特流。
4.2 现象:BER 曲线在低 SNR 段出现平台
原因:噪声功率归一化错误,或者 Qfunct.m 里的 Q 函数近似公式在大参数下精度不够。解决:用 MATLAB 自带的 qfunc 函数替换 Qfunct.m 做交叉验证;检查 gngauss.m 中噪声方差是否按 1/(2*10^(EbN0/10)) 计算,而不是 1/10^(EbN0/10)。
4.3 现象:OFDM3.m 运行报错“矩阵维度不一致”
原因:N_fft 和 N_cp 设置后,串并转换的维度没有同步更新;或者调制符号数不是 N_fft 的整数倍。解决:在 IFFT 之前加一句 assert(mod(length(sym), N_fft) == 0),确保符号数能被 FFT 点数整除;如果不够就补零或者丢弃尾部多余符号。
4.4 现象:星座图窗口打不开或显示空白
原因:qpsk.fig 是旧版 MATLAB 保存的图形文件,在新版 MATLAB(如 2023b)中打开时可能因为图形句柄不兼容而显示异常。解决:直接运行 qpsk.m 重新生成图形,不要双击 .fig 文件;如果 qpsk.m 里用了已弃用的 figure 属性,把 ‘EraseMode’ 之类的参数删掉即可。
4.5 现象:仿真速度极慢,跑一个 SNR 点要几分钟
原因:蒙特卡洛循环里逐符号调用函数,没有向量化;或者 num_symbols 设得过大。解决:把 cm_sm32 和 cm_dpske 的调用改成矩阵运算,一次处理整帧数据;num_symbols 先从 500 开始调试,确认曲线趋势正确后再加到 5000 以上。
5. 进阶技巧:把 OFDM3.m 改成可配置的 QPSK/DQPSK 对比框架
5.1 用函数句柄统一调制接口
OFDM3.m 目前可能是硬编码调制方式,改起来要动好几处。更省事的做法是定义一个调制函数句柄,在脚本开头根据 mod_type 变量指向不同的映射函数:
% 统一调制接口,方便切换 QPSK 和 DQPSK if strcmp(mod_type, 'QPSK') mod_func = @cm_sm32; elseif strcmp(mod_type, 'DQPSK') mod_func = @cm_dpske; else error('不支持的调制方式'); end % 后续调用统一用 mod_func(bits) tx_sym = mod_func(bits);逻辑说明:这样切换调制方式只需要改一个字符串,不用去翻脚本中间的具体调用行。参数说明:cm_sm32 和 cm_dpske 的输入输出维度一致,所以可以直接互换。
5.2 把 BER 结果存成表格方便写报告
跑完多个 SNR 点后,把结果整理成三列:EbN0_dB、QPSK_BER、DQPSK_BER。用 table 存起来,直接导出到 Excel 或者用 writetable 写 CSV。这样写实验报告时不用手动抄数字,也方便画对比图。
| Eb/N0 (dB) | QPSK BER | DQPSK BER |
|---|---|---|
| 0 | 0.078 | 0.152 |
| 2 | 0.037 | 0.089 |
| 4 | 0.012 | 0.041 |
| 6 | 0.0023 | 0.014 |
| 8 | 0.00019 | 0.0038 |
注意:上表是典型仿真值,实际跑出来会有浮动,以你机器上的结果为准。
5.3 用理论曲线验证仿真是否可信
QPSK 在 AWGN 下的理论 BER 是 qfunc(sqrt(210^(EbN0/10)))。DQPSK 的理论近似是 2qfunc(sqrt(210^(EbN0/10)))(1-qfunc(sqrt(2*10^(EbN0/10))))。把这两条理论曲线和仿真曲线画在同一张图上,如果仿真点落在理论线附近(差距小于 0.5 dB),说明链路没问题。如果仿真曲线整体平移了,优先查噪声功率归一化;如果斜率不对,查判决门限或者差分检测的参考相位。
5.4 从 AWGN 扩展到多径信道的改法
OFDM3.m 目前只加了高斯噪声,如果想看多径下的表现,可以在 IFFT 之后、加 CP 之前插入一个多径信道模型,比如两径信道 [1, 0.5] 或者指数衰减信道。加 CP 的作用就是对抗这种多径,所以你会看到:不加 CP 时 BER 曲线在高 SNR 下出现平台,加了足够长的 CP 后平台消失。这个对比实验能直接说明 CP 的价值,比看公式直观得多。
5.5 我踩过的一个坑:差分编码在频域和时域不能混用
有一次我把 DQPSK 的差分编码放在时域做(相邻 OFDM 符号之间差分),结果接收端解调时发现每个子载波上的相位变化被 IFFT 搅乱了,误码率完全不对。后来才想明白:OFDM 的每个子载波是独立平行的,时域差分意味着跨符号的相位关系要经过 FFT 才能恢复,但 FFT 本身是线性变换,不会保留差分相位信息。正确做法是在频域做差分,也就是对同一个 OFDM 符号内相邻子载波上的符号做差分编码。从那以后我每次改 OFDM 调制方式,都强制先确认差分是在频域还是时域做的,再跑一个单载波对比验证。希望帮到你。
本文还有配套的精品资源,点击获取