简介:本资源为一份面向通信工程、电子信息类专业学生及数字通信入门学习者的MATLAB仿真文档,围绕QPSK调制在加性白高斯噪声(AWGN)信道下的性能展开,适合课程设计、实验报告撰写与通信原理自学参考。压缩包内仅含1个doc文档,体积约404KB,正文系统梳理了QPSK的四相相位映射与复基带数学表达,并完整给出信号生成、调制、噪声注入、匹配滤波、相干解调、误码率统计到BER-SNR曲线绘制的仿真链路,同时列出randi、qpsk、awgn、biterr等关键函数的调用思路与循环扫描不同信噪比的实现框架。读者可据此复现误码率曲线,直观理解QPSK在高斯噪声环境中的抗噪能力,并为实际通信系统设计提供理论依据。目前已有661人学习,便于快速上手并对照修改参数开展拓展实验。
1. 从一条不下降的误码率曲线说起:QPSK 在 AWGN 信道下的 MATLAB 仿真
有人把 QPSK 在 AWGN 信道下的 MATLAB 仿真跑完,Eb/N0 从 0 dB 扫到 12 dB,理论曲线已经掉到 1e-6,实测却卡在 1e-3 附近不再下降;也有人曲线形状完全正确,整条却比教科书右移了 3 dB。这两种现象几乎占掉通信原理课程设计和毕设里 QPSK 仿真的绝大部分返工时间。问题基本不在调制公式,而集中在三处:符号能量有没有归一化、awgn() 里填的到底是 SNR 还是 Eb/N0、比特拆分与合并的配对顺序是否一致。这类资源一般会先给 M-PSK 信号波形的正交展开和相干解调推导,再配一套代码输出误码率曲线、时域波形和星座图、眼图。对做课程设计的人是现成的骨架,对已经工作的人是把链路预算里那几个 dB 对齐的校准工具。下面按建模、加噪、判决、看图排错的顺序拆一遍。
2. QPSK 星座映射与 I/Q 支路建模
2.1 从 M-PSK 通式收敛到四个星座点
M-PSK 的带通表达式是 s_m(t) = g(t)·cos(2πf_c t + 2π(m−1)/M),m = 1,2,…,M,g(t) 为脉冲成形波形。把余弦展开后,每个波形都能写成两个标准正交基的线性组合:f₁(t) = √(2/ε_g)·g(t)cos2πf_c t,f₂(t) = −√(2/ε_g)·g(t)sin2πf_c t。于是信号向量 s_m = [√ε_g·cos(2π(m−1)/M), −√ε_g·sin(2π(m−1)/M)],全部符号能量相同,都等于 ε_g。
M = 4 时相位取 0、π/2、π、3π/2,四个点均匀落在半径为 √ε_g 的圆上,相邻两点相差 90°。文档里还提到 π/4-QPSK 这个变形:在每个符号间隔的载波相位上额外叠加 π/4 相移,让相位跳变不经过原点,包络起伏更小,符号同步也容易做。它的星座仍是正方形,只是整体转了 45°,接收端做相位判决时要注意这个偏移量。
2.2 Gray 映射与 Es = 1 的归一化
映射关系直接决定误比特率和误符号率的换算系数,工程上默认用 Gray 映射,相邻星座点只差一个比特:
| 双比特 b₁b₂ | I 支路电平 | Q 支路电平 | 归一化复符号 | 相位 |
|---|---|---|---|---|
| 0 0 | +1 | +1 | (1 + j)/√2 | 45° |
| 0 1 | +1 | −1 | (1 − j)/√2 | −45° |
| 1 1 | −1 | −1 | (−1 − j)/√2 | −135° |
| 1 0 | −1 | +1 | (−1 + j)/√2 | 135° |
Gray 映射的价值在于:噪声把符号推到最近邻点时,通常只错一个比特,所以误比特率约等于误符号率除以每符号比特数 k。这个近似在后面的理论曲线对照里会直接用到。
归一化必须在建模阶段就定死。若 I/Q 直接取 ±1,符号能量 Es = 2;除以 √2 之后 Es = 1,对应 Eb = Es/log₂4 = 0.5。漏掉这一步,后面算出的噪声方差会跟着错,整条曲线平移 10log₁₀(2) ≈ 3.01 dB。这是"曲线形状对、位置偏 3 dB"最常见的第一个来源。
2.3 手写调制器:不依赖任何工具箱
%% QPSK 调制:比特流 -> 复基带符号(Es = 1,Gray 映射) Nbits = 1e5; % 总比特数 Nbits = Nbits - mod(Nbits, 2); % 向下取偶,奇数比特无法配对 bits = randi([0 1], Nbits, 1); % 生成随机二进制序列 bI = bits(1:2:end); % 奇数位置比特 -> 同相 I 支路 bQ = bits(2:2:end); % 偶数位置比特 -> 正交 Q 支路 % 双极性映射:比特 0 -> +1,比特 1 -> -1;除以 sqrt(2) 做能量归一化 I = (1 - 2*bI) / sqrt(2); Q = (1 - 2*bQ) / sqrt(2); sym = I + 1j*Q; % 复基带 QPSK 符号,Es = |sym|^2 = 1这段代码的逻辑说明:randi生成列向量便于后续向量化运算;1:2:end与2:2:end决定了比特到 I/Q 的分配方式,这个索引在接收端合并时必须以完全相同的顺序还原,否则会出现高信噪比下的误码平台。参数上,Nbits要按目标误码率反推,测 1e-4 量级至少准备 1e6 比特;1 - 2*b完成 0/1 到 +1/−1 的映射,/sqrt(2)把 Es 归到 1。整个调制过程在等效基带上完成,不出现载波,运算量比真带通仿真小一个数量级。
3. AWGN 信道注入与 Eb/N0 换算
3.1 加性白高斯噪声的两条实现路径
AWGN 信道的两个正交噪声分量 n_c、n_s 都是零均值高斯过程,且互不相关,方差均为 N₀/2。对复基带信号加噪,等价于在实部、虚部各加一路独立高斯噪声。手写写法是sigma*(randn + 1j*randn),其中单维标准差 sigma = √(1/(2·Es/N0))(Es 已归一化为 1)。写成这种形式的好处是噪声功率完全确定,结果可复现。
用 MATLAB 的awgn()更方便,但它的snr参数含义是"每样点符号信噪比",在采样率等于符号率时就是 Es/N0。而教科书横轴是 Eb/N0,两者差 10log₁₀(k) = 3.01 dB。直接把 Eb/N0 填进awgn(x, EbN0, 'measured'),等于噪声加多了 3 dB,曲线整体右移——这是第二个偏 3 dB 的来源。
3.2 SNR、Es/N0、Eb/N0 的换算关系
| 参数 | 含义 | 与 Eb/N0 的关系(QPSK) | 常见误用 |
|---|---|---|---|
| Eb/N0 | 每比特能量与噪声功率谱密度之比 | 基准 | 直接填进 awgn 的 snr 参数 |
| Es/N0 | 每符号能量与噪声功率谱密度之比 | Eb/N0 + 3.01 dB | 与 SNR 混用 |
| SNR | 信号功率与噪声功率之比 | 采样率 = 符号率时等于 Es/N0 | 过采样时漏加 10log₁₀(Fs/Rs) |
| sigma | 复噪声每维标准差 | √(1/(2·Es/N0)) | 忘记开方或漏掉因子 2 |
过采样场景要额外注意:若每个符号采 8 个点,噪声带宽随之扩大,awgn的 snr 与符号级 Es/N0 之间还差 10log₁₀(8) ≈ 9 dB。带成型滤波的仿真必须把这一项补回去。
3.3 三种加噪写法的等价验证
%% 同一组符号,三种加噪方式应当得到一致的噪声功率 EbN0dB = 6; % 目标每比特信噪比 k = 2; % QPSK 每符号 2 比特 EsN0dB = EbN0dB + 10*log10(k); % 折算成 Es/N0 = 9.01 dB EsN0 = 10^(EsN0dB/10); % 方式一:手写复高斯噪声,Es = 1 时每维方差为 1/(2*EsN0) n1 = sqrt(1/(2*EsN0)) * (randn(size(sym)) + 1j*randn(size(sym))); r1 = sym + n1; % 方式二:awgn,'measured' 会先估计输入信号功率再按 snr 加噪 r2 = awgn(sym, EsN0dB, 'measured'); % 方式三:显式给定信号功率,避免有限块长带来的功率估计偏差 r3 = awgn(sym, EsN0dB, 0); % 第三个参数 0 dBW 即信号功率 1 W fprintf('实测噪声功率: %.4f / %.4f / %.4f\n', ... var(r1-sym), var(r2-sym), var(r3-sym));参数说明:'measured'会在每次调用时重新估计输入功率,块长较短或高信噪比时估计偏差明显,实测噪声功率会偏离理论值;直接给出信号功率(方式三)则完全确定,适合做可复现的曲线。EsN0dB与EbN0dB的换算写死在代码里,扫点时只改 Eb/N0 一个变量,避免两处不同步。
4. 相干解调、判决门限与误码统计
4.1 相干解调就是取实部虚部的符号
接收信号与两个正交载波做相关后,输出落到 I/Q 平面上的点,判决就是把复符号的实部和虚部各自与门限 0 比较:real(r) < 0判为比特 1,imag(r) < 0同样判为 1。因为星座关于原点对称且 Es 已归一化,0 就是最优门限,不需要额外计算。
还原比特时最容易出错的地方是配对顺序。调制端用1:2:end取 I、2:2:end取 Q,解调端必须原样写回;如果图省事用reshape(bits, 2, []).'再取列,得到的配对顺序会变,高信噪比下误码率会卡在一个平台上不再下降。
4.2 扫 SNR、算误码、叠理论曲线
EbN0dB_list = 0:2:12; % 横轴扫描点 ber = zeros(size(EbN0dB_list)); for ii = 1:numel(EbN0dB_list) EbN0dB = EbN0dB_list(ii); EsN0dB = EbN0dB + 10*log10(2); % QPSK: Es/N0 = Eb/N0 + 3.01 dB sigma = sqrt(1/(2*10^(EsN0dB/10))); r = sym + sigma*(randn(size(sym)) + 1j*randn(size(sym))); bIhat = real(r) < 0; % I 支路硬判决 bQhat = imag(r) < 0; % Q 支路硬判决 bitsHat = zeros(Nbits, 1); bitsHat(1:2:end) = bIhat; % 合并顺序必须与调制端一致 bitsHat(2:2:end) = bQhat; ber(ii) = sum(bits ~= bitsHat) / Nbits; % 等价于 biterr end EbN0_lin = 10.^(EbN0dB_list/10); theory = 0.5*erfc(sqrt(EbN0_lin)); % Q(sqrt(2*Eb/N0)),Gray 编码 QPSK semilogy(EbN0dB_list, ber, 'o-'); hold on; semilogy(EbN0dB_list, theory, 'k--'); grid on; xlabel('E_b/N_0 (dB)'); ylabel('BER'); legend('仿真','理论');逻辑说明:sigma由 Es/N0 直接算出,不调用任何工具箱,省去biterr和qfunc的依赖。理论值用0.5*erfc(sqrt(Eb/N0)),这正是 Q(√(2Eb/N0)) 的等价写法,Gray 编码的 QPSK 与 BPSK 在这一项上完全相同。若两条曲线在高信噪比处分离,优先检查配对顺序和归一化,其次看是否漏了 Es/N0 到 Eb/N0 的 3.01 dB。
4.3 蒙特卡洛仿真到底能测到多低
| 目标 BER | 建议每点比特数 | 预计观测错误数 |
|---|---|---|
| 1e-2 | ≥ 1e4 | 约 100 |
| 1e-3 | ≥ 1e5 | 约 100 |
| 1e-4 | ≥ 1e6 | 约 100 |
| 1e-5 | ≥ 1e7 | 约 100 |
经验规则是让每点至少积累 100 个错误比特,误码率估计的相对标准差才落到 10% 以内。纯蒙特卡洛掉到 1e-5 以下就很吃力,常规做法是曲线只画到 1e-4,更低的部分用理论式或半解析法补。
5. 星座图、眼图与波形图的排错用法
5.1 三张图各自能看出什么
星座图看判决裕量:scatterplot(r)之后应看到四个清晰团簇落在 ±45° 方向,团簇半径就是噪声标准差。团簇糊成一片说明噪声过大或 SNR 单位错;四个点整体转了 45°,说明映射用了 π/4 偏移而判决门限没跟着转。
眼图看定时:eyediagram(real(r), samplesPerSym)需要过采样信号,反映的是 I 支路的码间干扰和采样点位置。眼睛张开度最大处才是最佳采样时刻,用'measured'模式加噪但没做过采样时,眼图会退化成一个点和一条噪声带,看不出任何东西。
时域波形看包络:QPSK 是恒包络调制(不加成型滤波时),若看到幅度明显起伏,多半是 I/Q 两路增益不一致或符号对齐错了位。
5.2 症状到原因的对照表
| 现象 | 最可能的原因 | 检查位置 |
|---|---|---|
| 曲线形状对、整体右移 3 dB | Eb/N0 与 Es/N0 混用,或漏归一化 | sigma 计算式、awgn 的 snr 参数 |
| 高 SNR 处误码率不再下降 | 比特配对顺序与调制端不一致 | 1:2:end与2:2:end的合并 |
| 星座图整体旋转 45° | 用了 π/4-QPSK 映射 | 判决门限是否跟着旋转 |
| 眼图完全闭合 | 没做过采样或没加成型滤波 | 采样率与符号率的比值 |
| 噪声功率估计每次略有不同 | 'measured'在短块上的估计偏差 | 改用固定信号功率 |
5.3 一行代码锁定配对顺序错误
配对顺序的问题不需要靠读代码发现,直接在两个数组上打索引对比就行:
% 假设调制端保存了每比特对应的符号序号和支路标记 idxTx = [(1:2:Nbits).', (2:2:Nbits).']; % 第 n 行是第 n 个符号的 I/Q 比特索引 idxRx = [(1:2:Nbits).', (2:2:Nbits).']; % 解调端若换成 reshape,此处会不一致 assert(isequal(idxTx, idxRx), '比特配对索引不一致,检查 reshape 的维度顺序');把这段断言放在调制和解调之间,任何一次重构导致的配对错位都会在仿真开始前直接报错,而不是等到扫到 10 dB 才看到一个平底的误码率平台。扫点前顺手把idxTx、idxRx和sigma三个量disp出来,一次运行就能覆盖绝大多数返工场景。
本文还有配套的精品资源,点击获取