尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DQPSK-OFDM链路仿真:从QPSK到差分调制的高斯信道MATLAB实现

DQPSK-OFDM链路仿真:从QPSK到差分调制的高斯信道MATLAB实现 简介这份资源面向通信工程、电子信息类专业学生及无线通信入门研究者围绕QPSK、DQPSK与OFDM三种核心调制技术展开重点解决在加性高斯白噪声信道下比较DQPSK与QPSK误码性能的仿真需求。压缩包共12个文件以8个MATLAB源码.m为主体辅以3个自动备份文件.asv和1个图形结果文件.fig整体约13KB体积轻便便于直接运行与二次修改。源码覆盖高斯噪声生成、QPSK与DQPSK调制解调、误码率计算及OFDM系统仿真等模块可帮助读者绘制误码率随信噪比变化的曲线直观理解差分调制相对绝对调制的抗噪优势以及OFDM在多载波传输中的频谱利用特点。目前已有116人学习适合作为通信原理课程的实验参考或课程设计的起步模板。1. 从 QPSK 到 DQPSK-OFDM一条被低估的链路仿真入门路径很多人第一次接触 OFDM 仿真都是从 QPSK 映射直接跳到 IFFT跑出来的星座图干干净净于是觉得「OFDM 不过如此」。可一旦把信道换成高斯白噪声再把调制方式换成 DQPSK眼图和误码率曲线立刻开始翻车——这不是玄学而是差分相位检测在 OFDM 框架下引入的相位累积误差在作祟。QPSK-DQPSK-OFDM 这条链路本质上是在问一个问题当接收端拿不到绝对相位参考时怎么靠前后符号的相位差把数据解出来。它适合已经会写 QPSK 映射、但对差分调制和 OFDM 联合仿真没有完整跑通过的人。高斯信道在这里不是走过场而是验证差分检测是否正确的第一道门槛。把这条链路在 MATLAB 里跑通后面加多径、加频偏心里才有底。2. DQPSK 差分编码与 OFDM 子载波映射的联合设计2.1 为什么 DQPSK 不能直接套用 QPSK 的映射表QPSK 的星座点映射是绝对的00 对应 45°01 对应 135°以此类推。接收端只要知道参考相位就能直接判决。但 DQPSK 的出发点是接收端没有绝对相位参考或者信道引入了慢变相位旋转导致绝对相位不可信。这时候信息不再承载于当前符号的绝对相位而是承载于当前符号与前一个符号的相位差。具体到实现上DQPSK 的差分编码规则是设第 k 个符号的相位为 θ_k信息比特映射为相位增量 Δθ_k则 θ_k θ_{k-1} Δθ_k。接收端检测时计算 Δθ θ_k - θ_{k-1}再反映射回比特。这个「累加」过程在 MATLAB 里就是一个 cumsum 操作但坑在于初始相位 θ_0 的选取——它不影响差分检测结果但会影响星座图的外观很多人在这里调半天以为出了 bug。在 OFDM 框架下DQPSK 的差分是沿频率方向还是时间方向做是一个必须提前想清楚的问题。常见做法是沿时间方向即同一个子载波上相邻 OFDM 符号之间做差分。这样做的原因是频率方向差分对频偏更敏感而时间方向差分在高斯信道下表现更稳。代价是第一个 OFDM 符号必须作为参考符号不承载信息频谱效率会降一点。2.2 子载波映射与 IFFT 前的数据排布OFDM 子载波映射这一步新手最容易犯的错是把差分编码后的复数符号直接往 IFFT 输入里塞忘了预留直流子载波和保护带。标准做法是总子载波数 N实际使用的数据子载波数 N_data两侧各留若干空子载波直流位置置零。DQPSK 差分编码后的符号按顺序填入数据子载波位置。下面是一段可直接跑的 MATLAB 代码完成从比特到 IFFT 输入的完整映射% 参数设置 N_fft 64; % FFT 点数 N_cp 16; % 循环前缀长度 N_data 48; % 数据子载波数 N_sym 100; % OFDM 符号数含参考符号 M 4; % DQPSK 调制阶数 % 生成随机比特 num_bits N_data * (N_sym - 1) * log2(M); bits randi([0 1], num_bits, 1); % 比特分组每组 2 bit 映射为相位增量 bit_reshape reshape(bits, log2(M), []).; phase_inc zeros(size(bit_reshape, 1), 1); for i 1:size(bit_reshape, 1) if isequal(bit_reshape(i,:), [0 0]) phase_inc(i) pi/4; elseif isequal(bit_reshape(i,:), [0 1]) phase_inc(i) 3*pi/4; elseif isequal(bit_reshape(i,:), [1 1]) phase_inc(i) -3*pi/4; else phase_inc(i) -pi/4; end end % 差分编码沿时间方向累加相位 phase_cum cumsum(phase_inc); sym_diff exp(1j * phase_cum); % 重塑为 [N_data, N_sym-1]每列是一个 OFDM 符号的数据 sym_matrix reshape(sym_diff, N_data, N_sym-1); % 插入参考符号第一个 OFDM 符号全 10j sym_matrix [ones(N_data, 1), sym_matrix]; % 子载波映射构建 N_fft x N_sym 的频域矩阵 freq_grid zeros(N_fft, N_sym); data_idx [2:25, 39:62]; % 避开直流和边缘保护带 freq_grid(data_idx, :) sym_matrix; % IFFT 变换到时域 time_signal ifft(freq_grid, N_fft); % 加循环前缀 time_cp [time_signal(end-N_cp1:end, :); time_signal];这段代码的逻辑说明先按 2 bit 一组映射为相位增量再用 cumsum 做差分编码然后按列排布成子载波矩阵。data_idx的选择不是随意的它避开了直流子载波索引 1 和 33 附近和两侧保护带。参数N_cp取 16是 N_fft 的 1/4在高斯信道下足够吸收符号间干扰。如果你把N_data改成 52记得同步改data_idx否则会数组越界。提示差分编码的初始相位不影响误码率但如果你要做星座图对比建议把参考符号设为 10j这样星座图旋转最小肉眼看着舒服。3. 高斯信道下的 DQPSK-OFDM 接收端从去 CP 到差分检测3.1 高斯白噪声信道的建模与信噪比设置高斯信道在 MATLAB 里就是awgn函数但很多人对 SNR 的定义和 OFDM 信号功率的关系搞不清楚导致误码率曲线整体偏移。关键点在于awgn的 SNR 参数是按信号功率归一化后的信噪比而 OFDM 时域信号经过 IFFT 后功率会变化。IFFT 在 MATLAB 里默认除以 sqrt(N)所以时域信号功率和频域符号功率基本一致。但加 CP 之后信号总功率不变能量被拉长了等效每符号能量下降。稳妥的做法是先计算时域信号的平均功率再根据目标 SNR 计算噪声功率手动加噪。这样每一步都可控不会出现「仿真曲线和理论曲线差 3 dB」这种血泪经验。% 计算信号功率 sig_power mean(abs(time_cp(:)).^2); % 目标 SNR 范围 snr_db 0:2:20; ber zeros(size(snr_db)); for idx 1:length(snr_db) snr_lin 10^(snr_db(idx)/10); noise_power sig_power / snr_lin; noise sqrt(noise_power/2) * (randn(size(time_cp)) 1j*randn(size(time_cp))); rx_signal time_cp noise; % 去 CP rx_no_cp rx_signal(N_cp1:end, :); % FFT rx_freq fft(rx_no_cp, N_fft); % 提取数据子载波 rx_data rx_freq(data_idx, :); % 差分检测当前符号乘以前一符号的共轭 rx_diff rx_data(:, 2:end) .* conj(rx_data(:, 1:end-1)); % 判决找最近的相位增量 phase_est angle(rx_diff); % 四象限判决 decision zeros(size(phase_est)); decision(phase_est 0 phase_est pi/2) 0; % 00 - pi/4 decision(phase_est pi/2 phase_est pi) 1; % 01 - 3pi/4 decision(phase_est -pi phase_est -pi/2) 2; % 11 - -3pi/4 decision(phase_est -pi/2 phase_est 0) 3; % 10 - -pi/4 % 反映射为比特并计算误码率 % ...此处省略比特反映射和 BER 统计逻辑与发送端对称 end参数说明snr_db从 0 到 20 dB步长 2 dB覆盖了 DQPSK 在高斯信道下的典型工作区间。noise_power的计算里除以 2 是因为复噪声的实部和虚部各占一半功率。差分检测那一步rx_data(:, 2:end) .* conj(rx_data(:, 1:end-1))是整个接收端的核心它把相位差提取出来同时抵消了信道引入的公共相位旋转——这正是 DQPSK 抗相位模糊的价值所在。3.2 判决门限与星座图观察眼图之外的验证手段DQPSK 的判决门限是四个象限的边界即 0、±π/2、π。在高斯信道下信噪比足够高时rx_diff的相位会聚集在 π/4、3π/4、-3π/4、-π/4 四个点附近。如果你把rx_diff的实部和虚部画成散点图就能看到四个簇。这个图比眼图更直接因为 DQPSK-OFDM 的眼图在时域上被 OFDM 的多载波特性打散了不太容易看出调制质量。实际操作中我一般会在 SNR10 dB 时画一次rx_diff的散点图确认四个簇没有混叠。如果簇之间出现明显的旋转或扩散优先检查两件事一是差分方向是否搞反了时间方向 vs 频率方向二是 CP 长度是否足够。高斯信道下 CP 不够长不会引入 ISI但如果你后面要扩展多径CP 长度就是第一个要调大的参数。注意angle函数返回的是 (-π, π] 范围判决边界在 π 和 -π 处是连续的但代码里用和时要小心边界值归属否则会出现个别比特随机错误误码率曲线在低 SNR 时翘尾。4. 避坑与排查DQPSK-OFDM 仿真里最容易翻车的五个地方4.1 现象误码率曲线在高 SNR 下不降反升原因差分编码的 cumsum 操作在长符号序列上会累积相位误差如果发送端和接收端的初始相位不一致或者参考符号被噪声污染后没有做任何保护误差会沿时间方向传播。解决参考符号不承载信息但接收端做差分检测时第一个数据符号依赖参考符号。可以在接收端对参考符号做一次相位归一化或者把参考符号的功率提高 3 dB牺牲一点总功率换检测稳定性。4.2 现象星座图四个簇整体旋转了一个固定角度原因IFFT 和 FFT 的配对使用中如果子载波映射时数据索引没有对称放置或者直流子载波没有置零会引入固定的相位偏移。解决检查data_idx是否关于 N_fft/2 对称直流位置是否确实为 0。另外MATLAB 的ifft和fft默认不做归一化如果中间手动做了缩放要保证收发两端一致。4.3 现象加噪后误码率始终在 0.25 附近完全不随 SNR 改善原因判决逻辑写错了四个象限的映射关系搞混。DQPSK 的相位增量映射和 QPSK 的绝对相位映射是两套表不能混用。解决把发送端的phase_inc和接收端的decision对照检查一遍确保 00 对应 π/4、01 对应 3π/4、11 对应 -3π/4、10 对应 -π/4。如果映射反了误码率会固定在 0.5 左右如果只是象限顺序错了会固定在 0.25。4.4 现象OFDM 符号数增加后仿真速度急剧下降原因MATLAB 里用 for 循环逐符号处理没有向量化。解决把rx_data(:, 2:end) .* conj(rx_data(:, 1:end-1))这种操作写成矩阵运算避免在符号维度上循环。另外awgn函数在循环里反复调用也会拖慢速度改成手动加噪后可以一次性生成噪声矩阵。4.5 现象换到多径信道后DQPSK 误码率比 QPSK 还差原因时间方向差分在多径信道下相邻 OFDM 符号之间的信道响应变化可能超过差分检测的容忍范围尤其是高速移动场景。解决如果要做多径考虑频率方向差分或者在每个 OFDM 符号内插入导频做信道估计后再做相干检测。DQPSK 的优势场景是慢变信道或对相位参考不可靠的场景不是所有信道都比 QPSK 强。5. 从高斯信道到频偏容忍DQPSK-OFDM 的进阶验证技巧跑通高斯信道只是第一步。DQPSK-OFDM 真正有意思的地方在于它对频偏的容忍度。OFDM 系统对频偏极其敏感子载波间干扰会让 QPSK 的星座点直接糊掉。但 DQPSK 的差分检测在频偏存在时相邻符号的相位差里会多出一个固定的旋转量只要这个旋转量不超过判决边界差分检测依然能工作。验证方法很简单在发送端给时域信号乘一个exp(1j*2*pi*f_offset*t)然后看误码率随频偏的变化。我一般会扫f_offset从 0 到子载波间隔的 10%观察误码率曲线在哪个点开始明显恶化。这个实验能帮你建立对 DQPSK 频偏容忍边界的直觉。另一个进阶技巧是把差分检测从硬判决改成软判决。硬判决只输出最近的相位增量软判决则输出四个相位增量的似然比后面接一个软输入译码器。在高斯信道下软判决能带来 1-2 dB 的增益代价是计算量增加。实现上把angle(rx_diff)换成对四个参考相位的欧氏距离计算再取指数归一化即可。验证项建议参数观察指标频偏容忍f_offset 0 ~ 0.1*子载波间隔BER 恶化 3 dB 时的频偏值CP 长度N_cp 8, 16, 32多径下的 BER 平台差分方向时间方向 vs 频率方向相同 SNR 下的 BER 对比软判决增益硬判决 vs 软判决BER1e-3 时的 SNR 差最后说一个我自己的习惯每次改完参数先跑 SNR10 dB 的单点看rx_diff的散点图。四个簇分得开再跑完整曲线分不开先查映射和差分方向别急着调 SNR 范围。这个习惯帮我省过很多次「曲线跑了一晚上发现是映射表写反了」的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表