拓冰建站拓冰建站
首页 / 资讯中心 / 正文

DQPSK误码率仿真:matlab实现与差分编码详解

简介面向通信专业学生与科研人员的DQPSK调制解调matlab仿真资源包完整实现DQPSK通信链路的误码率仿真。DQPSK在QPSK基础上引入差分编码发送端将绝对码转换为相对码接收端依据检测到的相位变化将相对码还原为绝对码从而恢复原始二进制序列程序输出调制、解调等各个环节波形并绘制误码率随信噪比变化的曲线可直观与理论误码率对比。资源共3个文件包含2个m脚本主程序与辅助代码和1个txt文件视频演示地址压缩包仅约3KB小巧易用。代码附带详细中文注释并配套操作演示视频讲解运行步骤与注意事项例如MATLAB当前文件夹路径必须设为程序所在位置对新手非常友好。目前已有179人学习适用于课程设计、毕业设计或通信原理实验验证。1. DQPSK误码率仿真为什么差分解调值得手动实现一遍matlab里用comm.DQPSKModulator加一句awgn就能跑出 DQPSK 误码率曲线但你算过差分编码丢掉的那个参考符号吗知道为什么误码在差分解调里常常成对出现吗这两个问题不搞清楚仿真数字再漂亮也只停留在「点了运行」。DQPSK差分四相相移键控把信息放在相邻符号的相位差上接收端不需要估计绝对载波相位天然规避了相干解调的相位模糊问题在卫星链路、地面微波和部分物联网短距通信里都有应用。下面按「原理 → 主程序 → 曲线与交付 → 验证」的顺序把 DQPSK 调制解调通信链路 matlab 误码率仿真完整拆开讲先立住相位映射和参数选型再给出可复现的主程序与中文注释规范最后用三个必查项校验结果可信度。新手照着章节一步步跑熟手直接拉到参数表和验证清单。2. DQPSK调制解调链路的相位映射与matlab参数选型2.1 DQPSK差分编码的相位映射规则与格雷映射表DQPSK 的每个符号携带 2 比特。调制时不把「比特 → 绝对相位」直接映射而是先做差分编码当前符号的相位等于上一符号相位加上当前比特对应的相位增量。接收端解调只关心相邻两个符号的相位差信道引入的固定相偏会在相位相减时自动抵消这是 DQPSK 与普通 QPSK 的本质区别。相干 QPSK 在接收端必须估计绝对载波相位锁相环一旦锁定在 π/2 的整数倍上解调比特会整体错位或反相这就是经典的相位模糊问题。DQPSK 把信息从绝对相位转移到相位差四相位模糊被从根源上绕开代价是同等信噪比下误码率比相干解调高 2~3dB这是后面所有曲线解读的前提。格雷映射表如下2比特输入相位增量相位角度0000°01π/290°11π180°103π/2270°表中相邻相位只差 1 个比特翻转这是格雷映射的核心意义符号被误判到相邻星座点时只产生 1 个比特错误。若用自然二进制映射00、01、10、11相邻相位差 2 个比特误码率曲线会整体变差。仿真时SymbolMapping属性设为Gray或Binary都可以但调制端和解调端必须一致一端 Gray 一端 Binary 会直接破坏映射关系。这张表背后还有一个隐含约定参考相位取 0第一个发射符号作为参考符号不携带信息。手动实现时发送端要么多发一个参考符号要么统计误码时跳过第一个符号对应的比特。System Object 把参考符号的处理封装在对象内部初学者很容易忽略但它解释了为什么差分解调输出的第一个判决结果不能直接与第一个发送比特对齐。DQPSK 还有 π/4-DQPSK 变体每个符号额外旋转 π/4避免信号经过原点适合非线性功率放大器场景。程序里把PhaseOffset从 0 改成pi/4即可切换链路其余部分不用动对比两条曲线能直观看到相位旋转对包络的影响。2.2 matlab仿真链路的模块划分与函数选型完整链路分四块信源与比特生成、DQPSK 调制含差分编码、AWGN 信道、DQPSK 解调含差分解码与误码率统计。matlab 下有两条实现路线。第一条用 Communications Toolbox 的 System Objectcomm.DQPSKModulator配合comm.DQPSKDemodulator差分编码和解码全部在对象内部完成。代码短、不易写错适合把精力放在参数扫描和曲线分析上。注意两个属性BitInput和BitOutput都要设为true调制器输入比特向量、解调器输出比特向量误码率统计环节可以直接比较如果按符号输入输出统计时还得自己做一次比特映射。第二条全手动randi生成比特、bi2de转符号、循环做相位累加、exp(1j*phase)生成复信号接收端用angle(rxSig(2:end).*conj(rxSig(1:end-1)))提取相位差。手动实现的每个中间量都能打印检查教学和排错更友好代价是多写二十行左右代码还要自己处理参考符号带来的长度差异。常见做法是主程序用 System Object另写一个demo_diff_encoding.m手动实现差分编码两个结果交叉验证。这样既保证仿真效率又能向团队新人讲清楚差分编码机理。如果没有安装 Communications Toolboxawgn、biterr、System Object 全部不可用只能走全手动路线噪声用sqrt(N0/2)*randn叠加到实部虚部误码率用sum(txBits~rxBits)/length(txBits)统计。2.3 误码率仿真的关键参数表与Eb/N0扫描范围误码率仿真的坑集中在参数设置上。下表是 DQPSK 仿真常用的基线参数参数取值说明调制阶数 M4每符号 2 比特每符号采样数 sps1符号级仿真不含脉冲成形每个SNR点比特数 numBits1e6约 50 万符号Eb/N0 扫描范围0:2:14 dB定位曲线后加密到步进 1dBPhaseOffset00标准DQPSKpi/4π/4-DQPSKSymbolMappingGray调制解调两侧必须一致扫描范围的选择与统计可信度绑定。经验规则是每个 SNR 点至少统计 100 个错误比特Eb/N012dB 附近 DQPSK 误码率约 1e-5 量级按 100 个错误反推需要约 1e7 比特全范围扫描会非常慢。常见做法是先粗扫 0:2:14 定位曲线再对感兴趣的点单独把 numBits 调大重跑。Eb/N0 换算在第 3 章展开这里先记住一条结论matlab 的awgn函数输入的是符号信噪比 Es/N0不是比特信噪比 Eb/N0DQPSK 因 log2(M)2需要加上约 3dB。这个 3dB 一出错整条曲线向右平移 3dB属于仿真里最隐蔽、最容易被带进报告的错误。3. 用matlab编写DQPSK误码率仿真主程序3.1 发射端比特生成、差分编码与DQPSK调制代码主程序按「参数区 → 主循环 → 绘图区」三段组织发射端代码如下%% DQPSK调制解调通信链路误码率仿真AWGN信道 % 功能蒙特卡洛仿真DQPSK差分解调误码率输出BER曲线 % 依赖Communications Toolbox clear; clc; close all; rng(2024); % 固定随机种子结果可复现 % ------- 参数区 ------- M 4; % DQPSK阶数每符号log2(M)2比特 numBits 1e6; % 每个Eb/N0点发送的比特总数 EbN0dBList 0:2:14; % 比特信噪比扫描范围(dB) berSim zeros(size(EbN0dBList)); errorCount zeros(size(EbN0dBList)); % DQPSK调制/解调对象输入输出均为比特流 dqpskMod comm.DQPSKModulator( ... BitInput, true, ... SymbolMapping, Gray, ... % 格雷映射相邻相位只差1比特 PhaseOffset, 0); % 0标准DQPSKpi/4π/4-DQPSK dqpskDemod comm.DQPSKDemodulator( ... BitOutput, true, ... SymbolMapping, Gray, ... PhaseOffset, 0);参数说明rng(2024)固定随机种子保证每次运行结果一致这是与「程序操作视频」里输出对照的前提BitInputtrue表示输入是比特向量长度为numBits对象内部转换为numBits/2个符号SymbolMapping两端必须一致否则星座能解出来但误码率差一个格雷映射的增益。参数区独立成块、不用魔法数后续改扫描范围只动这一处。手动差分编码的对照代码可以放成独立脚本demo_diff_encoding.m帮助理解 System Object 内部做了什么% 手动DQPSK差分编码相位累加 复指数调制 phaseMap [0 pi/2 pi 3*pi/2]; % 格雷映射相位表 symIdx bi2de(reshape(txBits, 2, [])., left-msb); % 每2比特→0~3 txPhase zeros(length(symIdx)1, 1); % 首位是参考符号相位为0 for n 1:length(symIdx) txPhase(n1) mod(txPhase(n) phaseMap(symIdx(n)1), 2*pi); end modSigManual exp(1j * txPhase); % 长度符号数1含参考符号这段代码的原理相位增量查表获得累加用mod(..., 2*pi)保证结果落在 [0, 2π)输出信号比数据符号多一个参考符号其作用是与第一个数据符号做差分运算。对照 System Object 的输出长度numBits/2就能明白参考符号的启停逻辑被封装了但物理上它确实存在。3.2 AWGN信道与差分解调接收端的matlab实现信道与接收端在主循环内实现% ------- 主循环遍历Eb/N0 ------- for k 1:length(EbN0dBList) % 发射端 txBits randi([0 1], numBits, 1); % 随机二进制信息比特 modSig dqpskMod(txBits); % DQPSK调制输出复基带信号 % AWGN信道Eb/N0(dB)换算为符号信噪比Es/N0(dB) EsN0dB EbN0dBList(k) 10*log10(log2(M)); rxSig awgn(modSig, EsN0dB, measured); % 接收端 rxBits dqpskDemod(rxSig); assert(length(rxBits) length(txBits), 解调输出长度与发送不一致); % 误码率统计 [~, berSim(k)] biterr(txBits, rxBits); errorCount(k) sum(txBits ~ rxBits); end三个细节值得展开。awgn(..., measured)表示先测量信号功率再叠噪声信号不归一化也不会算错噪声功率如果不用awgn而手动生成噪声复基带信号的实部、虚部各用randn并乘sqrt(N0/2)功率因子极易出错新手建议直接用awgn。Es/N0 与 Eb/N0 的换算关系是 Es/N0 Eb/N0 10*log10(log2(M))M4 时为 3dB这一步错则整条曲线平移。biterr的第一个返回值是错误比特数第二个才是误码率只取后者会漏掉「统计到了多少个错误」这个可信度指标后续验证章节会用到。手动的差分解调算法用一行复数运算完成% 手动差分解调相邻符号共轭相乘提取相位差 phaseDiff mod(angle(rxSig(2:end) .* conj(rxSig(1:end-1))), 2*pi); decSymIdx mod(round(phaseDiff / (pi/2)), 4); % 判决到0~3 grayInv [0 1 3 2]; % 格雷索引→二进制索引 decBits de2bi(grayInv(decSymIdx1), 2, left-msb); % 还原2比特rxSig(2:end) .* conj(rxSig(1:end-1))计算相邻符号的相位差angle取出相位后除以 π/2 再取整完成四象限判决。grayInv是格雷映射反查表索引 0、1、2、3 分别对应二进制 00、01、11、10。手动解调的输出比发送比特少 2 位首符号无前向参考对比时要用txBits(3:end)对齐这段代码放在 System Object 版本旁边逐行对比就能看出差分解调的数学本质。3.3 误码率统计方法与Eb/N0换算细节误码率统计有一个差分独有现象错误传播。DQPSK 一个符号解错差分解码会同时影响当前符号和下一个符号的判决所以同等信道条件下误码率比相干 QPSK 高约 2~3dB。这经常被当成程序 bug 调试实际上是方案本身的特性。Eb/N0 换算再加一个反向验证思路把同一段modSig输入pskdemod(modSig, 4)做相干解调得到相干 QPSK 的仿真误码率再与 DQPSK 仿真曲线对比两条线之间的水平距离约 2~3dB这就是「差分代价」。如果两条线完全重合说明差分解调实现有问题最常见的原因是解调对象误用、符号映射不一致。关于统计精度符号级仿真不需要脉冲成形每个符号一个采样点numBits1e6时单点运行时间通常几秒到十几秒取决于机器性能。仿真时间不可接受时把循环改成parfor随机种子按工作进程分别设置避免多个 worker 生成相同序列。符号差错率与比特差错率的关系也值得记一笔格雷映射下两者近似满足SER ≈ 2 * BER如果统计出来 SER 明显大于这个关系优先怀疑误码统计时的对齐偏移而不是信道模型。4. 误码率曲线、中文注释与程序操作视频的制作规范4.1 理论误码率参考曲线与仿真结果对比画图的同时输出仿真曲线和理论参考曲线。DQPSK 差分解调在 AWGN 下没有像 BPSK 那样简洁的闭式表达式工程上常见做法是用相干 QPSK 理论值做参考线标注差分方案的性能代价% ------- 绘图区 ------- figure(Color, w); semilogy(EbN0dBList, max(berSim, eps), b-o, LineWidth, 1.5); hold on; EbN0Lin 10.^(EbN0dBList/10); berQPSKTheory 0.5 * erfc(sqrt(EbN0Lin)); % 相干QPSK理论误码率 semilogy(EbN0dBList, berQPSKTheory, r--, LineWidth, 1.5); grid on; xlabel(E_b/N_0 (dB)); ylabel(误码率 (BER)); title(AWGN信道下DQPSK调制解调误码率仿真); legend(DQPSK蒙特卡洛仿真, QPSK相干解调理论值, Location, southwest);参数说明max(berSim, eps)防止误码率为 0 时semilogy出现 0 值警告0.5*erfc(sqrt(EbN0Lin))是格雷映射 QPSK 相干解调的理论误码率作为理想下界参考。仿真曲线在 BER1e-3 处应比参考线向右偏移 2~3dB若两线几乎重合多半是差分解调写成了相干解调检查dqpskDemod是否被误替换为pskdemod。绘图区另一个实用细节是曲线标记。Eb/N0 扫描点不多时每个点都要有可见记号b-o中的o就是数据点标记不加标记的话黑白打印时仿真线和理论线难以区分。脚本里建议把errorCount向量同步disp出来曲线只看得到结果看不到统计质量而统计质量是判断曲线末端抖动是否可信的唯一依据。出报告时用exportgraphics(gcf, ber_dqpsk.png, Resolution, 300)导出位图比saveas的默认 dpi 更适合排版。4.2 中文注释的工程规范与matlab乱码防护中文注释在 matlab 里最典型的问题不是写不出来而是文件编码不一致导致的乱码。新版 matlab 默认按 UTF-8 读写.m文件但从老机器、老版本拷来的文件常见是 GBK/GB2312直接打开就会看到中文注释变乱码。这类问题不只出现在 matlabvivado、Dev-C 的中文注释乱码本质完全相同编辑器写入时用的编码和读取时用的编码不一致。恢复与预防分三步统一保存编码在「预设 → 编辑器/调试器 → 语言」中把文件编码设为 UTF-8此后新建脚本都按此写入对已乱码文件用「文件 → 打开」时选择 GB2312 重新打开再另存为 UTF-8。注释按区块组织脚本头部写功能说明块主循环和关键参数处用% ------- xxx -------分隔线行内注释只写「为什么」不写「是什么」。避免中文标点和全角空格混入注释这类字符跨平台拷贝后容易被编辑器自动转换产生乱码之外的隐性格式问题。提示feature(DefaultCharacterSet, UTF-8)可以临时切换当前会话字符集但根治办法还是统一源文件编码并存档到版本管理工具。4.3 程序操作视频的录制要点与配套脚本「程序操作视频」的交付目的是让拿到程序的人知道点哪、等多久、看到什么不是把代码念一遍。录制建议按四段组织并控制时长视频段落建议时长内容环境说明30秒matlab 版本、是否已安装 Communications Toolbox参数区讲解1分钟Eb/N0 范围、numBits 的含义与修改位置主循环运行2分钟左右逐节执行CtrlEnter展示 modSig / rxSig 中间变量曲线核对1分钟仿真线相对理论线的位置、errorCount 输出录制工具方面Windows 可以用 WinG 系统录屏或用 matlab 的getframe配合VideoWriter在脚本里生成演示视频macOS 用 QuickTime 录屏即可。录制前关闭无关窗口、固定窗口大小避免不同分辨率下界面缩放导致按钮位置对不上。更工程化的替代是 Live Script.mlx交付代码块和中文说明交替排列运行一次就是一份带曲线和中间输出的 HTML 报告配合publish还能导出 PDF。拿到程序包的人通常不会反复看视频但会反复翻 Live Script 里的注释和输出交付时两者都保留最稳妥。5. 校验DQPSK误码率仿真结果的三个必查项5.1 错误计数是否达到统计可信度第一个必查项是看每个 SNR 点实际统计到的错误比特数。程序里已经保存了errorCount(k)用循环打印出来% 打印每个SNR点的错误计数 for k 1:length(EbN0dBList) fprintf(Eb/N0 %2d dB, 错误比特数 %d\n, EbN0dBList(k), errorCount(k)); end判断标准很简单最低误码率那个点通常是 Eb/N0 最大点错误数至少 30最好过百。按 95% 置信度估算错误数 N 的相对误差约 2/sqrt(N)N100 时约 ±20%曲线末端抖动可接受N10 时误差超过 60%那一点的数值只能看量级。如果最后一个点错误数不足把 numBits 提高到 1e7 重跑那一个点不要整段重扫。如果某个点errorCount为 0berSim会是 0semilogy里被eps顶到图底这个点在报告里要注明「未观测到错误」不能当真实误码率用。5.2 相位旋转鲁棒性是否成立第二个必查项直接检验 DQPSK 的差分本质把接收信号整体旋转 90° 再解调误码率应基本不变。相干 QPSK 在这种情况下会完全失效DQPSK 因解调只关心相位差而天然免疫。验证代码% 相位旋转鲁棒性测试整体旋转90度后误码率应不变 rxSigRotated rxSig * exp(1j*pi/2); % 接收信号整体旋转90度 rxBitsRotated dqpskDemod(rxSigRotated); berRotated sum(txBits ~ rxBitsRotated) / length(txBits);berRotated与未旋转时的误码率差值应在蒙特卡洛抖动范围内相差一个数量级以上就说明实现有问题。常见失败原因解调端误用绝对相位判决的pskdemod或手动差分解调时相位差区间划分错误例如把 π/2 的倍率取整写成了 π/4。这条检查每次改动解调逻辑后都要重跑是对差分链路最便宜的回归测试。5.3 低信噪比行为与错误传播是否合理第三个必查项看曲线两端。低端Eb/N00dB 时 DQPSK 误码率应在 0.1~0.2 量级过高说明解调对齐有误接近 0.5 说明解调完全失效、等价于随机猜比特。高端曲线应持续下降、没有平台若高信噪比出现错误地板优先排查 PhaseOffset 是否两端一致、星座映射表是否被改动其次检查是否引入了人为的固定误码例如比较时包含了参考符号。最后把仿真曲线与公开资料中的 DQPSK 曲线形状对照同样约 2~3dB 的差分代价、同样斜率的滚降形状对不上就先检查 Es/N0 换算而不是怀疑蒙特卡洛循环写错。三个必查项依次通过DQPSK 误码率仿真基本可以交付。扩展方向按成本排序把awgn换成comm.RicianChannel或comm.RayleighChannel观察衰落信道下的曲线偏移复杂度最低再往后是加根升余弦脉冲成形和定时同步进入波形级仿真每一步改完都回到 5.2 节跑一遍相位旋转测试这条用例能拦住绝大多数解调侧回归错误。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门