
简介这份课程设计文档围绕MATLAB/Simulink环境下的通信系统建模与仿真展开以AWGN信道为背景系统比较BPSK与QPSK两种数字调制方式的误码率性能。正文先从BPSK与QPSK的调制解调原理出发介绍了相位键控的基本思想、相干解调结构及相位模糊问题随后给出需求分析、设计思路和Simulink模型搭建方法。仿真部分记录了不同信噪比下的误码率曲线并对比分析两种方案的抗噪声能力结论显示QPSK在相同条件下误码率低于BPSK。资源包含1个docx文档大小约551KB结构涵盖引言、正文、总结与课程感言既包含理论公式推导也包含完整的仿真流程、结果记录和问题解决方案。目前已有4900人浏览学习特别适合通信工程、电子信息类学生完成课程设计或实验报告时参考也可帮助初学者快速掌握使用Simulink进行通信系统仿真的基本方法。1. AWGN信道下BPSK与QPSK调制比较这堂课设到底在考什么很多同学拿到“基于MATLAB/Simulink的通信系统建模与仿真课程设计AWGN信道下BPSK与QPSK调制比较”这个题目第一反应是打开Simulink拖模块拖完了发现误码率曲线乱跳或者两条曲线叠在一起根本看不出差别。其实这个题目的核心不是教你拖模块而是逼你把数字通信里最基础的一组关系理清楚在同样的大噪声环境下BPSK和QPSK谁的抗噪声能力更强强多少为什么QPSK带宽效率翻倍却几乎不损失误码性能。这篇文章按课程设计的完整流程展开从理论推导、Simulink建模、脚本仿真到排错验证讲清每一步该怎么做、参数怎么设、坑在哪。适合正在做这个题目的本科生也适合想用MATLAB/Simulink把调制解调链路彻底弄明白的从业者。2. 拿到题目先别急着建模误码率理论和大纲选型思路2.1 BPSK与QPSK的误码率边界为什么两条理论曲线几乎重合这个题目最容易被忽略的地方是理论部分但理论恰恰决定了你后面怎么判断仿真结果对不对。BPSK是二进制相移键控一个符号携带1比特两个星座点分别在0度和180度QPSK是四进制相移键控一个符号携带2比特四个星座点均匀分布在圆周上。在高斯白噪声AWGN信道下BPSK的误比特率理论公式是[ P_b Q\left(\sqrt{\frac{2E_b}{N_0}}\right) ]QPSK每个符号携带2比特误比特率的理论公式是[ P_b Q\left(\sqrt{\frac{2E_b}{N_0}}\right) ]两者在误比特率意义上完全一样。很多同学第一次看到这个结论会愣住QPSK的星座点更密为什么误码率不更高原因是QPSK虽然符号间欧氏距离比BPSK小但每个符号携带2比特在相同的比特能量 (E_b) 下比较时这种“密度代价”恰好被比特数抵消了。误符号率则不同QPSK的误符号率近似是误比特率的两倍因为一个符号错了可能只错1个比特也可能错2个比特平均下来每个出错符号大约错1比特。这个结论是整个课程设计的第一块基石。如果后面你的仿真曲线和理论曲线对不上先回来检查你画的是误比特率还是误符号率以及横轴到底用的 (E_b/N_0) 还是 (SNR)。2.2 用Simulink还是纯脚本两种路线的适用边界课程设计大纲一般允许两种实现方式一种是纯MATLAB脚本自己写调制解调另一种是Simulink搭模块。我的建议是如果只是要求出误码率曲线对比脚本更快更可控如果课程要求演示系统结构、模块参数、动态仿真过程Simulink更直观而且答辩时好讲。两件事并不冲突常见做法是Simulink搭出完整链路再用脚本跑蒙特卡洛统计最后用BERTool做交叉验证。Simulink路线的优势在于模块封装清晰从信源、调制器、信道到解调器、误码统计每一级都能单独看波形和星座图适合把课程设计报告写得有层次。缺点是跑蒙特卡洛仿真时Simulink的仿真时间受步长和采样率影响很大低误码率区域比如 (10^{-5})需要跑很久。脚本路线的优势是循环控制灵活可以一次跑完所有信噪比点缺点是代码写起来要自己处理滤波、采样、定时这些细节调试难度高一些。我一般建议课程设计采用“脚本验证理论 Simulink画系统框图”的组合打法。先说清楚理论曲线长什么样再用Simulink搭链路验证几个关键信噪比点最后用脚本把完整曲线跑出来。这个思路既避开了Simulink跑大量数据点的耗时问题又满足了课程设计对系统建模的考核要求。2.3 先算清楚 (E_b/N_0) 和 (SNR) 的换算关系做这个题目最容易翻车的地方就是混用 (E_b/N_0) 和 (SNR)。两个仿真工具里写的是不一样的。MATLAB的AWGN函数和Simulink的AWGN信道模块都支持两种模式一种是直接指定 (SNR)单位dB另一种是指定 (E_b/N_0) 配合符号速率和每符号比特数。为什么需要换算因为 (E_b/N_0) 是归一化到每比特的信号噪声功率比和带宽、采样率无关适合比较不同调制方式而 (SNR) 是实际的信号功率和噪声功率之比和系统带宽强相关。在仿真里如果你用的是基带等效模型信号经过采样后噪声功率和采样率有关所以 (SNR) 不能直接用。正确的做法是先确定每比特能量 (E_b)再由符号速率 (R_s) 和每符号比特数 (k) 计算比特速率 (R_b k \times R_s)然后用 (SNR E_b/N_0 \times R_b / B) 换算其中 (B) 是接收机等效噪声带宽。在MATLAB的脚本仿真中我习惯的做法是直接使用awgn函数的measured选项先测信号功率再按目标 (E_b/N_0) 反推噪声功率。具体换算公式后面代码里会给出。3. 用Simulink搭出双调制链路从模块选型到参数落地3.1 模型整体架构与模块选型Simulink搭这个题目我推荐用 Communications Toolbox 里的模块不要自己画正弦波和乘法器做模拟调制。常见做法是搭三套链路BPSK链路、QPSK链路再加一个理论误码率曲线作为参照。每条链路的核心模块是相同的只是调制器参数不同。整体架构从信源开始Random Integer Generator产生二进制数据进入BPSK Modulator Baseband或QPSK Modulator Baseband调制后经过AWGN Channel送入对应的解调器解调输出和原始比特一起进入Error Rate Calculation模块统计误码率。为了看星座图和波形可以在信道输出处接一个Constellation Diagram模块和一个Time Scope。模块版本和名字在不同MATLAB版本里略有差异我用的是R2020a之后的模块名称。如果找不到模块可以在库浏览器里搜索Modulator Baseband或者把Communications Toolbox更新到与MATLAB主版本匹配的版本。搭建时注意采样时间的设置这是整个模型跑不跑得起来的关键。3.2 各模块参数设置从信源到误码统计先看信源。Random Integer Generator的Set size设为2输出0和1的随机整数对应BPSK的二进制输入。采样时间Sample time设为1秒Samples per frame设为100或者1000这个值决定了每个仿真步处理多少比特太大会让误码统计的更新变慢太小则星座图上点太少看不清。如果后面要接到QPSK调制器输入也需要是二进制只不过QPSK调制器内部会把比特两两分组映射成四进制符号。调制器参数是核心。BPSK Modulator Baseband只需要设相位偏移默认是0即星座点在0度和180度。QPSK Modulator Baseband要设相位偏移为pi/4或0这影响星座图的观感但误码率结果一样。这里有一个很多人忽略的参数调制器的输出是复数基带信号采样率等于符号速率所以AWGN信道模块里的参数必须和符号速率对齐否则等效噪声功率算错。AWGN信道模块选择Eb/N0 (dB)模式输入Eb/N0值然后填符号速率等于信源采样率的倒数和每符号比特数。BPSK每符号1比特QPSK每符号2比特。这里填错一个数字整条误码率曲线就会平移3dB。解调器直接选对应的BPSK Demodulator Baseband和QPSK Demodulator Baseband解调方式选Hard decision课程设计一般不需要软解调。最后是Error Rate Calculation模块。Receive delay参数要特别注意因为调制解调链路有延迟接收端比特和发送端比特不是逐位对齐的。常见做法是把延迟设为0然后在解调器输出端加一个Buffer或Delay模块手动对齐或者在Error Rate Calculation里设置一个合适的延迟值比如1让输出端的误码率统计自动对齐。如果这里不设置误码率会显示得很奇怪甚至大于1。3.3 跑透一个完整的Simulink模型仿真时间与数据采集模型搭好之后仿真时间设置是关键。不要用默认的10秒因为误码率统计需要足够多的比特才能稳定。以符号速率1Hz、每帧100比特为例仿真100秒才1万个比特误码率在 (10^{-3}) 时只能统计到大约10个错误比特抖动非常大。我一般设置仿真时间为1000秒以上或者在误码率模块里设置Stop simulation条件当错误比特数达到一定数量比如100个时自动停止仿真这样能在高信噪比时节省大量时间。仿真运行时Error Rate Calculation模块输出三个值误码率、错误比特数、总比特数。低信噪比时这三个值更新很快高信噪比时更新很慢当误码率低于 (10^{-4}) 时仿真时间会急剧增加。这时候不要干等把Simulink的仿真模式从Normal改成Accelerator可以提高运行速度。星座图模块默认只在仿真结束时显示最终结果如果想看动态过程双击星座图标本打开了示波器窗口。但要注意Constellation Diagram显示的是接收端符号序列经过匹配滤波和采样后的点如果AWGN信道模块前没有加匹配滤波器星座图会显示出发射符号加噪声的原始分布看起来点比较散这是正常的。课程设计的重点是误码率曲线星座图只作为辅助观察手段。4. 用脚本把误码率曲线跑出来手动调制解调与Monte-Carlo统计4.1 完整可复现的脚本BPSK与QPSK误码率对比纯MATLAB脚本是验证理论最直接的手段。下面这段代码我拆得很细可以直接复制运行做了关键注释。它做的事情是生成随机比特按BPSK和QPSK分别调制加AWGN噪声硬判决解调统计误码率最后画图对比理论值。% 参数设置 EbN0_dB 0:1:12; % Eb/N0 范围单位 dB numBits 1e6; % 每个信噪比点仿真的比特数 ber_bpsk zeros(size(EbN0_dB)); % 存储 BPSK 误码率 ber_qpsk zeros(size(EbN0_dB)); % 存储 QPSK 误码率 for idx 1:length(EbN0_dB) % 当前 Eb/N0 值线性 EbN0_lin 10^(EbN0_dB(idx)/10); % ---------- BPSK ---------- bits_bpsk randi([0 1], numBits, 1); % 随机二进制比特 sym_bpsk 2*bits_bpsk - 1; % 映射0 - -1, 1 - 1 noiseVar_bpsk 1 / (2*EbN0_lin); % BPSK 噪声方差推导见下方说明 noise_bpsk sqrt(noiseVar_bpsk) * randn(numBits, 1); rx_bpsk sym_bpsk noise_bpsk; rxBits_bpsk rx_bpsk 0; % 硬判决大于 0 判为 1 ber_bpsk(idx) sum(rxBits_bpsk ~ bits_bpsk) / numBits; % ---------- QPSK ---------- bits_qpsk randi([0 1], numBits, 1); % 将比特两两映射为 QPSK 符号每 2 比特 - 一个符号 bits_matrix reshape(bits_qpsk, 2, numBits/2).; symReal 2*bits_matrix(:,1) - 1; % 实部0 - -1, 1 - 1 symImag 2*bits_matrix(:,2) - 1; % 虚部0 - -1, 1 - 1 sym_qpsk (symReal 1i*symImag) / sqrt(2); % 归一化到单位能量 noiseVar_qpsk 1 / (2*EbN0_lin); % QPSK 比特能量归一化后噪声方差相同 noise_qpsk sqrt(noiseVar_qpsk/2) * (randn(numBits/2,1) 1i*randn(numBits/2,1)); rx_qpsk sym_qpsk noise_qpsk; % 硬判决按象限判决 rxBitsReal real(rx_qpsk) 0; rxBitsImag imag(rx_qpsk) 0; rxBits_qpsk reshape([rxBitsReal, rxBitsImag]., [], 1); ber_qpsk(idx) sum(rxBits_qpsk ~ bits_qpsk) / numBits; end % 理论误码率 EbN0_lin 10.^(EbN0_dB/10); berTheory_bpsk qfunc(sqrt(2*EbN0_lin)); berTheory_qpsk qfunc(sqrt(2*EbN0_lin)); % 误比特率理论值相同 % 画图 figure; semilogy(EbN0_dB, ber_bpsk, bo-, LineWidth, 1.5); hold on; semilogy(EbN0_dB, ber_qpsk, rs-, LineWidth, 1.5); semilogy(EbN0_dB, berTheory_bpsk, b--, LineWidth, 1); semilogy(EbN0_dB, berTheory_qpsk, r--, LineWidth, 1); grid on; legend(BPSK仿真, QPSK仿真, BPSK理论, QPSK理论); xlabel(E_b/N_0 (dB)); ylabel(误比特率 (BER)); title(AWGN信道下BPSK与QPSK误码率对比);4.2 代码逻辑说明与关键参数含义这段代码里最需要理解的是噪声方差的推导。BPSK符号能量是1因为符号是1和-1平均能量是1每符号1个比特所以符号能量等于比特能量 (E_b1)。AWGN信道的噪声方差 (N_0/2)因此 (E_b/N_0 1 / N_0 1 / (2\sigma^2))反推噪声方差 (\sigma^2 1 / (2E_b/N_0))。这就是代码里noiseVar_bpsk 1 / (2*EbN0_lin)的来源。QPSK部分为什么噪声方差公式一样关键在于我把星座点做了归一化。四个星座点位于 ((\pm1/\sqrt{2}, \pm1/\sqrt{2}))每个符号的能量是 (1/2 1/2 1)。每符号2比特所以比特能量是 (E_b 1/2)。根据 (E_b/N_0) 的定义得到 (N_0 E_b / (E_b/N_0) 0.5 / (E_b/N_0))而实部和虚部各占一半噪声功率所以每一路噪声方差是 (N_0/2 0.25 / (E_b/N_0) 1/(4 \cdot E_b/N_0))。因为符号能量为单位1所以你也可以理解成直接把总噪声方差设为 (1/(2E_b/N_0))然后实部虚部分摊。代码里noiseVar_qpsk 1/(2*EbN0_lin)是总噪声方差再除以2就是每路方差和上面的推导完全一致。一个常见错误是忘记对QPSK星座点归一化。如果直接用sym_qpsk symReal 1i*symImag星座点能量是2而不是1那么相同 (E_b/N_0) 下误码率曲线会右移3dB看起来比理论值差很多。这个坑几乎每个做这个题目的同学都会踩一次。4.3 从脚本结果读出的三个结论跑完这段代码曲线图会给出三个直观结论。第一BPSK和QPSK的误比特率仿真曲线几乎重合和理论曲线一致这正是2.1节里推导的结论。第二在 (E_b/N_0 10dB) 附近两者误码率都已经降到 (10^{-6}) 以下在这个数值后面仿真抖动会非常明显因为1e6个比特里错误比特数只有个位数统计误差很大。第三如果比较误符号率QPSK会比BPSK差大约2倍但题目要求的是误码率或误比特率所以这两条线重合是正确结果不是模型搭错了。仿真统计还有一个参数值得调整numBits。每个信噪比点跑1e6比特12个点大约要几秒钟在可接受范围内。如果要画到 (10^{-6}) 以下numBits需要增加到1e7以上运行时间会明显变长。我一般会在高信噪比点单独跑长仿真低信噪比点只需要1e5比特就足够稳定这是一种省时间的技巧。5. 防翻车指南理论曲线对不上、BER平台期、Simulink仿真卡死5.1 仿真曲线和理论曲线整体偏移多半是噪声方差算错现象是仿真误码率曲线和理论曲线形状一致但整体向右平移了几dB或者向左平移。常见的是向右偏3dB。这个现象十有八九是星座点能量没归一化。QPSK直接映射成1/-1实部加上1/-1虚部星座点能量就是2比特能量比理论推导大一倍等效于信噪比虚高3dB所以仿真曲线看起来比理论好3dB。更隐蔽的情况是BPSK的符号映射用了0/1而不是-1/1这时候平均符号能量变成0.5曲线会左移3dB看起来比理论差。解决方法是严格按照单位平均符号能量设计映射表并在加噪声前用mean(abs(sym).^2)打印一遍能量确认是1再继续跑。5.2 高信噪比时BER曲线出现平台期比特数不够或是延迟没对齐在高信噪比区域误码率曲线开始变平甚至抖动不再随 (E_b/N_0) 增加而下降。第一种原因最直接numBits不够。在 (10^{-5}) 的误码率下1e6个比特平均只有10个错误比特统计波动接近100%。这时候增加比特数到1e7或1e8曲线会继续下降。第二种原因是Simulink链路里的延迟没对齐Error Rate Calculation模块比较的发送比特和接收比特错位误码率停在某个恒定值不再下降。排查方法是在低信噪比下先确认误码率合理然后逐步增加信噪比看误码率是否单调下降如果平台期出现在高信噪比且延迟没有做对齐基本可以判定是延迟问题。在Simulink中给解调器输出加一个Delay模块并微调延迟拍数让误码率降到最低就是对齐成功。5.3 Simulink仿真时间过慢检查采样时间设置和仿真模式Simulink模型跑1000秒仿真要等很久这是课程设计里最常见的抱怨。原因一般是信源的Sample time设置得太小比如设成了0.001秒那么1000秒仿真就要处理100万个采样点加上误码统计模块每步都要更新速度自然慢。解决思路是只要不影响误码率结果尽量把符号速率设为1HzSample time设为1Samples per frame设大一些比如1000。然后把仿真模式从Normal切换到Accelerator并使用Stop simulation条件在错误数达到预设值时自动停止。这个条件可以在Error Rate Calculation模块里设置当累计错误比特数达到100时停止仿真能显著减少高信噪比点的运行时间。5.4 QPSK结果怎么调都和BPSK不相同你比较的可能是误符号率这是最后一个容易踩的坑。很多同学在Simulink里看Error Rate Calculation模块的输出发现QPSK的误码率是BPSK的两倍左右怎么调都对不齐。这时候要看清楚模块输出的是“符号误码率”还是“比特误码率”。Simulink的Error Rate Calculation默认逐比特比较如果输入QPSK解调器输出的是符号索引而不是比特序列那么统计出来的就是符号错误率。QPSK误符号率确实约等于误比特率的2倍这不是bug。解决方法是让QPSK解调器输出比特Output type选Bit并且信源和参考输入都保持二进制序列。另外部分同学在手动写QPSK判决时会用星座图的象限边界即大于0来判决这在AWGN信道下是最优的误码率不会因此变差可以放心用。6. 用BERTool验一遍你的仿真结果一个值得养成的验证习惯课程设计做完Simulink模型和脚本仿真后很多同学就直接截图写报告了。我建议你用MATLAB自带的BERTool再做一次交叉验证这个工具能省下你反复检查理论公式的时间还能让报告的置信度上一个台阶。BERTool的打开方式是在MATLAB命令行输入bertool界面里选择Monte Carlo标签页设定调制方式为BPSK或QPSKEb/N0范围保持一致仿真比特数设为1e5到1e6然后点击运行。BERTool用相同参数跑出来的误码率点应该和你脚本里的仿真结果重合。这个交叉验证的意义在于BERTool是官方工具它的噪声计算和你手写代码里的方差公式有可能不一样如果结果不一致那是你的推导或实现出错了如果一致说明你的代码是可靠的。从BERTool结果里还能提取一个重要习惯不要只盯着曲线看要看置信区间。在低误码率区域仿真点的统计波动很大比如Eb/N0 10dB时1e6个比特只可能统计到个位数的错误事件点与点之间的抖动是正常的。如果你的报告需要高精度数据就在低误码率点单独增加仿真比特数到1e8而不要对所有点都用相同比特数浪费运行时间。我以前做这个题的时候卡在QPSK曲线比BPSK差3dB这个问题上整整一下午最后发现是星座点没归一化。后来每次做仿真我都先打印符号能量再用BERTool验证一遍。这两步养成了习惯之后几乎没再被误码率对不上的问题折磨过。这个题目本身不难难的是把理论、实现和验证三个环节连起来每一步都有据可查。希望这些思路和踩坑记录能帮到你。本文还有配套的精品资源点击获取