
简介面向QPSK数字通信系统链路仿真的MATLAB资源适合通信工程专业学生、科研人员及需要验证数字基带传输原理的开发者。仿真完整覆盖根升余弦脉冲成型上采样8倍、滚降系数0.2、AWGN信道传输、匹配滤波、相关解调与判决并输出接收眼图与星座图可直观观察不同信噪比下的信号质量同时计算仿真误码率并与理论值对比帮助理解成型滤波与匹配滤波在抗噪声性能中的作用。资源包仅含3个文件以MATLAB脚本为主附带眼图与星座图结果图片压缩包大小约54KB轻量易用适合快速运行与二次修改。已有2832人学习下载说明这套仿真在QPSK入门与课程设计场景中具有较高参考价值。 做通信仿真这些年我一直觉得QPSK在AWGN信道下的误码率仿真是个“最小完整系统”——麻雀虽小五脏俱全。调制映射、加性白噪声建模、信噪比换算、判决检测、误码率统计数字通信链路里最核心的那些环节它全给你串起来了。正因如此不管是《通信原理》课程设计还是刚入职做基带算法验证的新人上手题基本都是这个配置。这篇文章我就用MATLAB把QPSK信号在AWGN信道下的误码率仿真正儿八经跑一遍从原理到代码到结果对照再到踩坑一路说透。1. 为什么几乎所有通信教材都用QPSK当入门仿真先说一个我自己的观察QPSK在蜂窝通信、WiFi、卫星通信里几乎都是“低速率兜底”的调制方式信号质量差的时候系统会自动切到它。这个现实地位决定了它不只是一个教学玩具而是你以后读协议、调链路预算时一定会碰到的真家伙。从算法验证角度看QPSK的价值在于它是“复杂度低、信息量足”的完美交叉点。BPSK只有一个比特流程图和星座图都太简单体现不出I/Q两路并行处理的精髓16QAM或者64QAM虽然更能体现高阶调制的星座设计但对于刚接触仿真的人来说判决边界、幅度归一化、误码率公式推导一次性铺开容易直接劝退。QPSK处于中间它有完整的象限概念有实部虚部两路信息有Gray映射带来的“相邻符号只错1比特”优势但判决逻辑又足够简单。还有一个经常被忽略的点Gray编码下的QPSK理论误码率恰好和BPSK完全相同符号差错率也有一套精确的闭式表达式。这意味着你做完蒙特卡洛仿真之后可以用理论曲线做严格的交叉验证而不是“大概趋势对就行”。这是我带新人时特别看重的一点——仿真结果如果不能和理论值严丝合缝代码里八成有坑而QPSK是练习这种“对照验证”习惯成本最低的场景。最后说一句大实话很多人觉得写仿真是为了交差但真正到了面试或者实际项目里面试官问你“QPSK在AWGN下的误码率公式是什么、仿真曲线长什么样、为什么高信噪比时曲线掉得特别快”答不上来就很尴尬。这篇跑完这些底层直觉你自然就有了。2. QPSK调制解调与AWGN信道的数学建模2.1 星座点设置与Gray映射QPSK的星座点有四种标准画法常见的是把四个点放在单位圆上相位分别为45度、135度、225度、315度。每个符号对应2个比特所以第一步是把输入的比特流两两分组。我在代码里习惯用一组直接映射到复平面的向量% 四个星座点按Gray码顺序排列 % 00 - 11j, 01 - -11j, 11 - -1-1j, 10 - 1-1j constellation [11j, -11j, -1-1j, 1-1j] / sqrt(2);这里除以sqrt(2)是做什么如果不除四个点的幅度是sqrt(2)平均符号能量Es2除以sqrt(2)之后每个符号都落在单位圆上Es1后面算噪声功率的时候就不用考虑信号能量额外缩放公式会清爽很多。Gray映射的顺序我上面已经写出来了相邻星座点之间只有1个比特翻转。为什么在意这个细节因为AWGN信道里噪声把符号推到相邻星座点的概率最大Gray映射能保证“大概率误差只影响1个比特”这样比特误码率和符号误码率之间有个简单关系理论值的推导也符合这个前提。2.2 AWGN信道与Eb/N0的正确换算AWGN信道在基带等效模型里就一句话rx tx_symbols noise;但这里的noise怎么加是新手翻车重灾区。noise必须是复高斯噪声实部和虚部各自独立都服从均值为0、方差为sigma^2的正态分布而且这个sigma^2和信噪比必须严格对应。先理清几个定义Es是每符号能量QPSK是2比特/符号所以Es 2 * EbEb是每比特能量Eb/N0就是我们常说的“每比特信噪比”单位dBN0是噪声功率谱密度在基带复信号模型里总噪声功率等于N0所以当信号能量Es1时符号信噪比SNR Es/N0 1/N0而Eb/N0还要再折算一次SNR_dB EbN0_dB 10*log10(2); % Es 2*Eb SNR_lin 10^(SNR_dB/10); N0 1 / SNR_lin; % 因为Es 1 sigma sqrt(N0/2); % 实部、虚部各占一半噪声功率这个N0/2就是最容易出错的点。很多人在生成噪声时直接写成sqrt(N0)*randn结果等效于把噪声功率翻了一倍仿真曲线会比理论值右移约3dB——这个现象后面我会专门讲。2.3 解调判决的思路AWGN信道对接收端来说没有记忆没有干扰最优判决就是“最小欧氏距离”看接收符号离四个理想星座点哪个最近就判成哪个点。QPSK因为星座点刚好按象限划分判决规则可以简化为看实部和虚部的符号实部 0 判为比特1 0 判为比特0按我上面定义的映射虚部同理这本质上是把二维判决拆成了两个一维判决正好对应I/Q两路。理解这一点也就理解了为什么QPSK在AWGN下的误码率曲线和BPSK一致——它可以看成两个正交的BPSK叠加。3. 完整仿真代码从参数设置到误码率统计3.1 仿真参数与总体架构我写仿真脚本的习惯是先定参数区再写核心处理最后是结果展示。这样改Eb/N0范围或者数据量时不需要动逻辑部分。%% 参数设置 clear; clc; close all; rng(42); % 固定随机种子保证结果可复现 EbN0_dB 0:2:10; % 扫信噪比单位dB numBits 1e6; % 每个信噪比点仿真的总比特数 M 4; % QPSK k log2(M); % 每符号2比特 % 星座映射表Gray编码功率归一化 constellation [11j, -11j, -1-1j, 1-1j] / sqrt(2); ber_sim zeros(size(EbN0_dB)); % 存放仿真误比特率 for idx 1:length(EbN0_dB) % 每一步都在循环内部实现见下文 end这里把rng(42)写在开头是我踩过坑之后养成的习惯。仿真最怕“这次跑和上次跑结果不一样”固定种子至少能排除随机性带来的干扰。你复制别人的代码跑不出同样的曲线种子往往就是原因之一。3.2 调制、加噪与判决的向量化实现这段是核心我尽量写成不需要Communications Toolbox也能跑的形式只有理论对比那行用了通信工具箱自带函数。% 1. 生成随机比特并两两分组 bits randi([0 1], numBits, 1); bitPairs reshape(bits, k, []); % 每行是 [b1, b2] symbolIdx 2 * bitPairs(:,1) bitPairs(:,2) 1; txSymbols constellation(symbolIdx).; % 2. 加AWGN噪声 SNR_dB EbN0_dB(idx) 10*log10(k); % 符号信噪比 SNR_lin 10^(SNR_dB/10); N0 1 / SNR_lin; % Es1所以N01/SNR noise sqrt(N0/2) * (randn(numBits/k, 1) 1j*randn(numBits/k, 1)); rxSymbols txSymbols noise; % 3. 判决实部虚部分别判符号 rxBits zeros(numBits, 1); rxBits(1:2:end) real(rxSymbols) 0; % 实部对应第1个比特 rxBits(2:2:end) imag(rxSymbols) 0; % 虚部对应第2个比特 % 4. 统计误比特率 ber_sim(idx) sum(rxBits ~ bits) / numBits;整个循环里没有用任何一个“逐符号”的for循环全部是矩阵运算。在MATLAB里这种向量化写法比写for n 1:N逐个符号循环快几十倍1e6比特在2GHz的老笔记本上跑完全部信噪比点也就几秒钟。一个细节说明判决之后我直接对比的是比特不是符号所以统计出来的是误比特率BER。如果你关心的是误符号率SER需要把判决后的符号索引和原始符号索引对比那就要换一套统计方式两者不要混用。3.3 理论误码率曲线与绘图理论曲线直接用通信工具箱是最省事的% 理论误比特率Gray编码QPSK等价于BPSK ber_theory berawgn(EbN0_dB, psk, M, nondiff);如果是在没有通信工具箱的环境里也可以手动实现Q函数ber_theory_manual 0.5 * erfc(sqrt(10.^(EbN0_dB/10)));这两个公式在数值上是等价的Q(x) 0.5*erfc(x/sqrt(2))。我建议你在自己的脚本里把两种都算出来对比一下能加深对理论表达式的理解。绘图部分用semilogyfigure; semilogy(EbN0_dB, ber_sim, ro-, LineWidth, 1.5, MarkerSize, 6); hold on; semilogy(EbN0_dB, ber_theory, b*-, LineWidth, 1.2); grid on; xlabel(Eb/N0 (dB)); ylabel(Bit Error Rate); legend(仿真值, 理论值, Location, southwest); title(QPSK在AWGN信道下的误码率性能);为什么用semilogy而不是plotBER在Eb/N010dB时已经到10^-6量级线性坐标下低误码率部分会被压成一条贴在零轴上的直线整个曲线后半段的意义就完全看不出来了。对数坐标才能直观体现“每增加3dB误码率下降一个数量级”这种瀑布特性。4. 仿真曲线与理论误码率的对照验证跑完上面的代码你应该会看到两条曲线几乎重合实线是理论值圆圈是仿真值。这在预期之内因为AWGN信道是最干净的模型没有衰落没有频偏没有相位噪声仿真和理论如果对不上那一定是代码有bug。对照验证时有几个点值得注意。第一低信噪比区间的仿真点和理论值通常贴得很紧。Eb/N00dB时理论误码率大约在0.078左右这个量级下1e6个比特里大约有7.8万个错误比特统计涨落很小曲线自然平滑。第二高信噪比区间才是考验。Eb/N010dB时理论误码率大约在3.9e-6量级也就是说1e6个比特里平均只出4个错。这时候如果运气好一个错都没出仿真值算出来就是0在semilogy图上直接掉出坐标范围显示成“消失的点”。这就是样本量不够的典型症状。碰到这种掉出图外的点我的处理办法很简单要么增加每个信噪比点的仿真比特数比如从1e6加到1e7要么接受这个点不存在并只画有值的点。工程上做链路预算时通常更关心误码率在10^-3到10^-6这个区间低于10^-6基本可以认为通信质量足够好了。第三注意曲线整体的斜率趋势。AWGN下QPSK的误码率曲线是单调下降的而且下降速度会越来越快。原因是误码率公式里存在指数项Eb/N0每增加3dB指数里的参数按sqrt(2)倍增大误码率就成量级下降。如果你看到曲线在某个区间突然平坦或者高信噪比时反而上翘不用怀疑代码里肯定有噪声功率或判决逻辑的问题。下面这张表给出几个典型信噪比点上的理论误码率方便你快速核对仿真结果数量级是否正确Eb/N0 (dB)理论BER约1e6比特下期望错误数07.86e-27860023.75e-23750041.25e-21250062.39e-3239081.91e-4191103.87e-63.9从表里可以明显看出10dB时1e6个比特只够统计平均不到4个错仿真值在单个随机种子下的波动会非常大。这也是为什么严谨一点的项目里每个信噪比点都会跑多次蒙特卡洛实验取平均或者直接加大数据量。5. 仿真结果对不上理论值这份排查清单请收好这部分是我最想写的内容。带新人的时候我见过的QPSK仿真“翻车”现场90%都能归到下面几类原因。每一次都是同样的症状但根因完全不同。5.1 症状与根因对照表症状最可能的原因严重程度仿真曲线整体右移约3dB噪声功率没除2多乘了一倍最常见曲线在低信噪比就对不上比特到符号的映射表顺序错了比较常见高信噪比时曲线出现平台固定种子导致错误数太少样本不足常见曲线趋势一致但数值几乎高一倍统计的是符号误码率却拿来和比特误码率比概念混淆曲线左右抖动但大致趋势对每信噪比点比特数太少正常现象5.2 逐条展开说原因第一类“噪声功率翻倍”的问题根源在于复噪声的实部和虚部。我见过不少写法是noise sqrt(N0) * randn(1,N)但这只生成了一路实噪声或者放弃了虚部信息。正确的做法是实部虚部各用sqrt(N0/2)总噪声功率才等于N0。如果只把噪声当实信号生成等于噪声少了一半表现在结果上就是仿真曲线比理论曲线好3dB到处传的“仿真比理论好”的错觉多半就是这么来的。第二类映射表错乱典型表现是低信噪比时BER明显高于理论值。原因是Gray编码要求相邻星座点只有1比特不同如果映射顺序写错比如把01和10放成了相邻点那一次符号错误就会导致2比特错BER大约翻倍。判决逻辑和映射顺序是配套的改映射表的时候一定要同时检查解调端的bit到符号的转换公式。第三类样本量不足我在上一节已经说过。1e7个比特跑一个信噪比点在高误码率区间只要零点几秒但在10dB左右也就是几个毫秒的事真正耗时间的是数据生成和判决那一大串内存操作。如果不急着出图可以用10^7甚至10^8——这个量级也只是几秒钟的事。第四类概念混淆最隐蔽。很多课程设计的报告里学生统计的是误符号率却把结果画到“误码率”图上。QPSK一个符号两个比特没采用Gray编码时一次符号错误平均会造成1个比特错误两个指标粗略看接近但严格分析时误码率约等于误符号率的一半Gray编码下高信噪比时。所以写论文或报告时一定要明确你这根曲线到底统计的是什么两者都有理论公式但混用会让结果差0.5到1倍。第五类抖动属于统计学范畴。AWGN本身就是随机过程蒙特卡洛仿真的本质是统计实验样本量小了波动大是天经地义的事。应对方法除了增加样本量还可以把这几个信噪比点多跑几次平均或者换一个随机种子看看结果是否显著变化。5.3 一个额外的实用技巧最后分享一个我调试时常用的技巧不要直接跳到高信噪比跑全量仿真。我会先把EbN0_dB设成0:2:10每个点先用1e5比特快速跑通一遍确认曲线形状没问题再加大到最终数据量。这样调试周期能压缩到十几秒。如果一开始就上1e8一旦代码有bug等结果出来已经是半个小时后了。另外如果你将来要做的是带信道编码或衰落信道的仿真这套基带仿真框架依然适用——AWGN只是信道模型里最基础的一环把信道模型替换掉、把判决和统计模块保留就能平滑过渡到瑞利衰落、莱斯衰落甚至OFDM子载波上的仿真。QPSK这块地基打牢后面学什么通信模块都顺。本文还有配套的精品资源点击获取