尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

QPSK+LDPC+FFT频偏估计:Matlab完整链路仿真与调试指南

QPSK+LDPC+FFT频偏估计:Matlab完整链路仿真与调试指南 简介本资源是一套面向通信工程专业本科生与研究生的MATLAB仿真实践包聚焦无线通信系统中QPSK调制解调、LDPC信道编译码及基于FFT的载波频偏估计与补偿等核心同步技术解决实际链路中频偏导致解调性能恶化的问题。压缩包共14个文件9个.m主程序脚本、4个.mat预置矩阵数据、1个.txt操作指引总大小162KB涵盖LDPC校验矩阵生成、编码/译码、QPSK调制解调、AWGN信道建模、FFT频偏估计算法实现及误码率统计全流程所有代码均含详细中文注释。配套操作视频清晰演示运行环境配置需MATLAB 2024b、路径设置要点与结果可视化过程显著降低初学者调试门槛。目前已有78人学习下载适合开展课程设计、毕设仿真或深入理解现代数字通信系统联合优化机制。 要是你正在做通信系统相关的仿真——不管是毕业设计、课程项目还是工作里需要验证一个链路方案的可行性——你大概率绕不开这一套组合QPSK调制解调、LDPC编译码、FFT频偏估计。这三个东西单独拿出来每一个都有大量现成代码和教材但真要把它们拼成一个完整的、能跑出误码率曲线的同步通信系统麻烦事就来了。模块接口怎么对、LLR怎么传、频偏估计放在哪一级、仿真要跑多少帧才能让曲线平滑这些才是真正卡人的地方。这篇文章就围绕这套QPSKLDPCFFT频偏估计误码率仿真的Matlab实现把整个链路的设计思路、关键代码、调试过程、容易踩的坑全部拆开讲。适合正在做移动通信、卫星通信、深空通信类课题的同学也适合刚接触LDPC译码和载波同步、想通过完整仿真理解系统级联的工程师。我不打算只贴一堆代码而是把为什么要这么设计讲明白这样你拿到程序之后改参数、换场景、扩展成别的调制方式都不会抓瞎。1. 这套仿真系统到底在解决什么问题先别急着看代码。搞清楚三个模块各自扮演的角色、它们之间怎么配合比记住任何一行代码都重要。1.1 三个技术点为什么偏偏凑在一起从基带处理的角度看一个数字通信系统的接收机核心任务就是把收到的、带着噪声和畸变的信号尽可能准确地还原成发送端那串比特。QPSK、LDPC、FFT频偏估计分别对应这个任务里的三个层面。QPSK解决的是调制效率的问题。它把2个比特映射成一个复数符号频谱利用率比BPSK翻了一倍也就是说同样的带宽能传两倍的数据。代价是符号点之间的距离变近了对抗噪声的能力比BPSK差一些所以后面需要更强的纠错码来兜底。LDPC解决的是传输可靠性的问题。它是目前信道编码家族里性能最接近香农极限的一类码在同样的信噪比下能比卷积码、RS码低好几个数量级的误码率。5G、WiFi 6、DVB-S2这些标准里都有它的身影。在仿真里加入LDPC最直观的收益就是误码率曲线会出现明显的悬崖式下降——信噪比超过某个门限后误码率会急剧降低这个门限离香农限往往只有零点几个dB。FFT频偏估计解决的是收发同步的问题。实际通信时发射机载波和接收机本地振荡器之间不可能严格同频多普勒频移也会让信号频率发生偏移。对QPSK这种相位调制方式来说一点点频偏就会让星座图不停地旋转解调出来的数据全乱。FFT频偏估计的目的就是测出这个频偏值然后在解调之前把它补偿掉。这三个模块拼在一起就是一个很典型的有编码、有调制、有同步的完整数字收发机模型跟实际工程里的链路结构基本一致。1.2 链路整体框架与数据流向整个系统的数据流是这样一个顺序发送端随机产生二进制信息比特LDPC编码得到码字比特QPSK符号映射格雷映射加入载波频偏或直接在基带加等效频偏接收端下变频/去载波得到带频偏的基带信号FFT频偏粗估计并补偿QPSK软解调输出LLR对数似然比LDPC译码输出信息比特估计与原始比特比较统计误码率有一个关键点LDPC译码器用的是软信息所以QPSK解调不能做硬判决必须输出软比特LLR。很多第一次做级联的人在这里翻车把QPSK解调成硬比特再丢给LDPC译码性能会差很多。原因是LDPC的置信传播算法本质上是在概率域上迭代更新你喂给它的如果是0或1这种硬判决结果它就失去了利用置信度信息的能力。所以项目里面QPSK解调模块直接输出LLR这一步是整个链路能够正确工作的基础。1.3 这套系统适合什么人、怎么用它进阶如果你是还没接触过LDPC的学生建议先跑通无编码QPSK的误码率曲线确认QPSK部分没问题再打开LDPC编码和译码模块对比两条曲线的差距。如果已经有基础可以直接拿这套程序当母版把QPSK换成16QAM、64QAM把LDPC的码率换成3/4、5/6或者把AWGN信道换成多径信道扩展性都很好。2. QPSK调制解调从星座图映射到软解调LLRQPSK看着简单但里面有几个细节直接决定后面LDPC译码的性能。2.1 为什么选QPSK而不是BPSK或更高阶调制选QPSK是因为它处于频谱效率和抗噪声能力的平衡点。BPSK虽然抗噪最好但传同样的数据需要两倍带宽16QAM频谱效率高但对SNR的要求高很多在低信噪比下跟LDPC配合时LLR的置信度会普遍偏低对译码不友好。QPSK把2个比特放在一个符号上误码性能和实现复杂度都合适是LDPC这类强纠错码最常见的搭配方式。5G的PBCH、PDSCH在低阶调制时也大量使用QPSK就是这个原因。2.2 发射端符号映射的格雷编码细节QPSK发射端做的事情是把每2个比特编码成1个复数符号。映射方式要采用格雷映射也就是相邻星座点之间只差1个比特。这么做的好处是当噪声把符号误判到相邻星座点时只错1个比特而不是2个误码率直接减半。一个常用的格雷映射规则% 输入bit_pair是 [b1 b2]输出为复数符号 % 00 - -1-1j, 01 - -11j, 11 - 11j, 10 - 1-1j % 归一化因子让平均符号能量为1 s ((2*b1-1) 1j*(2*b2-1)) / sqrt(2);这里/sqrt(2)的作用是能量归一化。QPSK四个星座点到原点的距离都是sqrt(2)除以sqrt(2)后模长变成1这样符号平均能量就是1后面加噪的时候EsN0、EbN0的换算才不会出错。既然用到了EbN0就多说一句EbN0和EsN0的换算公式在仿真里极其容易被搞错EsN0 EbN0 10log10(每符号比特数)QPSK时是 10log10(2)实际加噪时Matlab的awgn函数用的是SNR信号功率/噪声功率如果信号平均功率已经是1SNR EsN0dB可以直接换算如果你要做的是带LDPC编码的链路那就更要注意信息比特经过编码后每个符号承载的信息比特不再是2个而是2 * R个R是LDPC码率。所以加噪时的EbN0到SNR换算要乘上码率。很多人在这一步栽跟头最后画出来的曲线横轴漂了好几个dB。2.3 接收端软解调与LLR计算接收端拿到带噪声的符号后如果直接做硬判决出来的比特只有0或1这对LDPC是灾难。正确做法是计算每个比特的LLRLLR的定义是LLR_k ln( P(b_k1 | r) / P(b_k0 | r) )计算QPSK两个比特的LLR时因为复数符号的实部和虚部分别承载了一个比特而且格雷映射让实部虚部互相独立所以可以分开算。在AWGN信道下每个比特的LLR可以化简为LLR_b1 2 * real(r) / (noise_var / 2) LLR_b2 2 * imag(r) / (noise_var / 2)这里的noise_var是复噪声的方差。写代码时要注意如果按实部虚部分开考虑每个维度的噪声功率是总噪声功率的一半不要忘了。我自己调试时最常犯的错是LLR符号搞反把1的对数似然比算成0的结果LDPC译码出来的误码率几乎接近1。验证方法很简单先关掉LDPC用LLR硬判决取正负号对比原始比特如果误码率在无频偏时接近理论值说明LLR符号是正确的。这一步检查一定要先做不然接上LDPC后出了问题根本分不清是编码的问题还是前端LLR的问题。2.4 基带等效模型仿真里不需要真正上变频很多初学者会纠结是不是要真的在Matlab里生成一个几十MHz的载波信号做乘法器上变频然后接收端再下变频不需要。在基带仿真里我们直接用复数基带信号表示QPSK符号载波频偏也可以通过乘一个复指数exp(1j*2*pi*f_off*t)来等效。这是通信仿真里非常成熟的做法数学上跟实际射频链路等价但计算量少好几个数量级。频偏的等效公式r(n) s(n) * exp(1j*2*pi*f_off*T_s*n) noise(n)s(n)是发送符号序列f_off是频偏HzT_s是符号周期秒n是符号序号。注意这里f_off*T_s这个乘积很多时候用归一化频偏delta_f表示单位是相对于符号速率的比例。比如符号速率1kHz频偏50Hz那么delta_f 0.05意味着每20个符号星座图就转一圈。3. LDPC编译码误码率曲线掉下来的真正功臣LDPC是整个系统里算法最复杂的模块。我把它单独拿出来讲因为这里面的参数选择和代码实现决定了你最终能看到多好的性能。3.1 LDPC比卷积码、Turbo码好在哪LDPC的全称是低密度奇偶校验码。它的核心思想是用一个非常稀疏的校验矩阵H来定义一组约束关系编码后的码字必须满足H * c^T 0。因为H矩阵大部分是0只有少量1迭代译码时每次只需要处理很少几个变量节点和校验节点之间的信息传递复杂度很低。相比卷积码LDPC的优势在于可以通过增大码长逼近香农限而且便于并行译码这在硬件实现上很重要。相比Turbo码LDPC的错误平层更低而且没有交织器的延迟问题。所以在仿真中选择LDPC既是为了性能也是为了贴近实际系统5G NR的LDPC码就是基于QC-LDPC结构的。3.2 校验矩阵的构造不要用随机矩阵直接上LDPC的性能很大程度上由校验矩阵H的结构决定。最忌讳的是用完全随机的稀疏矩阵因为随机矩阵里很容易出现长度为4的环而小环会严重劣化迭代译码的性能。实际仿真建议用两类矩阵QC-LDPC准循环LDPCH矩阵由循环移位子矩阵构成5G、DVB等标准都用了这种结构好实现、性能有保证用PEG算法构造的随机LDPCPEG能保证大围长比如至少6性能也不错适合自定义码长码率如果你只是做误码率仿真验证最省事的办法是用Matlab通信工具箱里的ldpcQuasiCyclicMatrix或者Comm Toolbox自带的标准矩阵。但如果你的Matlab没有这个工具箱自己写一个QC-LDPC矩阵生成器也不难核心就是构造基矩阵然后把每个非零元素替换成单位阵的循环移位。一个小建议刚开始调试的时候别用太大的码长。用N648、R1/2的码跑一次仿真快出了问题也好排查。等整个链路验证通了再换成5G标准的N1944或者更长的码。3.3 编码实现生成矩阵还是校验矩阵直接编码LDPC编码本身比译码简单。经典做法是用高斯消元把校验矩阵H化成系统形式得到生成矩阵G然后c mod(u * G, 2)完成编码。这里有一个坑直接对H做高斯消元得到的G往往非常稠密存储和计算量都很大。所以工程上会用RU算法也叫近似下三角编码利用H的稀疏性把编码复杂度控制在O(N)量级。但如果你的N只有一两千码率也不高直接用高斯消元求G的方式完全能接受仿真程序没必要搞复杂。Matlab里如果用二元域高斯消元常见的写法是% H是稀疏校验矩阵size(H) [M, N]码率 1 - M/N % 把H化成 [I | H2]再求G [H2 | I] % 编码c mod(u * G, 2)我经验是编码部分先求一个系统G保存下来后面每一帧编码直接用这个G就行不用每帧重新计算。G的计算只跟H有关跟数据无关属于一次性开销。3.4 BP译码与最小和简化LLR的迭代游戏LDPC译码通常用和积算法Belief PropagationBP也叫置信传播。它把校验矩阵H看作一张二分图左边是变量节点对应码字的每个比特右边是校验节点对应每个校验方程。信息在两类节点之间来回传递反复迭代直到所有校验方程都满足或者达到最大迭代次数。BP译码的核心步骤初始化每个变量节点拿到信道LLR就是QPSK软解调输出的LLR水平更新校验节点到变量节点每个校验节点根据它连接的其他变量节点的信息计算我建议你是什么垂直更新变量节点到校验节点每个变量节点综合信道信息和所有校验节点的建议更新自己的置信度硬判决与停止条件每个变量节点计算总LLR并硬判决如果满足所有校验方程提前退出和积算法里最难写的是水平更新的双曲正切运算L(r_ji) 2 * atanh( prod_{k in N(j)\i} tanh(L(q_kj)/2) )这行公式看起来简单但涉及大量tanh和atanh运算数值稳定性不太好。工程上常用**最小和算法Min-Sum**近似L(r_ji) prod( sign(L(q_kj)) ) * min( |L(q_kj)| )最小和算法虽然理论性能比标准BP差一点点大约0.1~0.2dB但实现简单、数值稳定做仿真足够了。如果你想让仿真逼近理论性能可以在最小和结果上乘一个约0.8的修正因子这个叫归一化最小和性能几乎不输BP。3.5 迭代次数与早停机制迭代次数是LDPC译码的另一个关键参数。迭代太少纠错能力发挥不出来迭代太多增加仿真时间。我常用的设置在10~50之间。低信噪比时大部分帧需要接近最大迭代次数才能收敛或宣告失败高信噪比时通常3~5次迭代就能满足所有校验方程。所以一定要写早停机制——每次迭代后检查H * c_hat是否全零如果是就立刻跳出循环。这个机制能把高信噪比区间的仿真时间缩短一个数量级。还需要注意的一点设置一个最大迭代次数上限同时保存最后一次迭代的硬判决结果。因为当信噪比太低时译码可能永远不收敛这时还是要硬着头皮输出一个结果不能卡死循环。4. FFT频偏估计与同步让星座图从旋转到静止频偏同步是整个系统里最容易被低估的部分。很多人觉得QPSK理论误码率曲线跑得很好就完事了但实际系统里的频偏会让误码率直接崩掉。这部分的原理和实现值得认真看。4.1 载波频偏为什么对QPSK是致命的QPSK的信息承载在载波的相位上。理想情况下接收星座点应该固定在四个位置。但只要有频偏符号点的相位就会随着时间线性增加星座图变成一个旋转的圆环。频偏越大转得越快符号间隔越大转过的角度越大。具体量化来看如果归一化频偏delta_f 0.01符号速率的1%那么每100个符号星座图转一圈。对一帧1000个符号的数据来说帧尾的符号相对于帧头的符号已经转了10圈解调必然完全失效。所以频偏估计必须在解调之前完成把残余频偏压到足够小的范围。4.2 FFT频偏估计的原理M次方谱QPSK信号的M次方谱频偏估计是一个经典做法。原理不复杂但值得说透。QPSK符号的相位集合是 {±π/4, ±3π/4}。如果对接收信号做4次方运算这些相位的4倍分别是 {±π, ±3π}其实都等价于π模2π意义上也就是说4次方之后调制信息带来的相位全部被消除剩下的就是一个单频信号r(n)^4 s(n)^4 * exp(1j*2*pi*4*f_off*T_s*n) 噪声项s(n)^4在QPSK下是一个常数所有星座点4次方后相同所以r(n)^4的频谱会在频率4*f_off处出现一个尖峰。对这个信号做FFT找到幅度最大的谱线对应的频率除以4就得到频偏估计值。这个思路可以推广到MPSKM次方后谱峰出现在M*f_off处。BPSK用2次方QPSK用4次方8PSK用8次方。原理一模一样。4.3 MATLAB实现核心代码与参数选择FFT频偏估计在Matlab里的实现大概就是这几个步骤function f_est fft_freq_est(rx, fs, M, Nfft) % rx: 接收基带信号 % fs: 符号速率 (Hz) % M: 调制阶数QPSK时M4 % Nfft: FFT点数 % 1. M次方消除调制信息 rM rx .^ M; % 2. 可选去直流和低通滤波提高信噪比 % rM rM - mean(rM); % 3. 做FFT并找谱峰 spec fftshift(fft(rM, Nfft)); freq_axis (-Nfft/2 : Nfft/2-1) / Nfft * fs; [~, idx] max(abs(spec)); % 4. 频偏估计结果注意除以M f_est freq_axis(idx) / M; end这段代码有两个细节特别重要第一FFT点数Nfft的选择。频偏估计的分辨率受限于fs / Nfft也就是说FFT点数越多频率分辨越细估计越准。但点数太多参与FFT的符号数量也要多否则做FFT的那段信号里包含不了那么多周期。经验值是让参与估计的符号数至少覆盖几个频偏周期。比如归一化频偏0.01至少需要几百个符号才能看到明显的谱峰。第二M次方后噪声不是高斯了。4次方运算会把噪声放大尤其低信噪比时r^4里的噪声项会变得很大谱峰可能被噪声淹没。这是M次方谱估计的固有局限。如果你的系统信噪比很低可以考虑用导频序列辅助估计发送一段已知序列接收端用本地序列做相关运算然后对相关结果做FFT找峰这样噪声抑制效果好得多。4.4 估计精度与残余频偏的容忍范围FFT频偏估计存在栅栏效应即真实频偏落在两条谱线之间时估计结果会偏向最近的那条谱线。这意味着FFT估计本身就有量化误差最大误差是半个频率分辨率。如果频率分辨率是fs/Nfft那么残余频偏最大有fs/(2*Nfft)。这个残余频偏对QPSK的影响是相邻符号间的相位增量不再是0而是随时间积累。比如归一化频偏0.001一帧1000个符号相位累积到2π还是会出问题。所以实际工程里FFT频偏估计通常是粗估计之后还要接一个判决引导或者锁相环做细估计把残余频偏压到更低。但在纯基带仿真里如果每帧的符号数不多比如几百到几千个符号且频偏是固定的FFT估计完直接补偿效果已经足够好因为残余频偏在单帧内累积的相位很小。5. 误码率仿真框架与结果分析当你把调制、编解码、频偏估计各模块都跑通之后接下来的问题是怎么把这些模块放进一个循环里得到一条可信的误码率曲线。5.1 蒙特卡洛仿真需要统计多少比特才算数误码率仿真本质上是一个蒙特卡洛实验在给定的EbN0下发送很多帧数据统计错误比特数除以总比特数得到误码率估计值。这个统计要跑多少数据取决于你想看到多低的误码率。一个常用的经验法则是如果想可靠地测到BER1e-4至少要统计大约100个错误比特也就是总比特数要超过1e6。如果总比特数只有1e5那统计出来的1e-4其实只有10个错误比特置信度很低曲线会抖动得很厉害。这就带来一个仿真时间的问题。LDPC译码本身有开销N648的帧一帧只有648个比特要跑到1e6比特需要1543帧每一帧都要做编码、调制、加噪、频偏估计、解调、译码在低信噪比下可能会比较慢。所以实际仿真时可以根据误码率目标动态调整仿真停止条件——比如累计错误比特达到50~100个就换下一个SNR点而不是每个SNR都固定跑5万帧。5.2 仿真循环框架模块之间的参数传递整个仿真框架可以用一个清晰的循环来组织EbN0_dB 0:0.5:6; for k 1:length(EbN0_dB) EbN0 10^(EbN0_dB(k)/10); SNR_dB EbN0_dB(k) 10*log10(code_rate * bits_per_symbol); total_bit_errors 0; total_bits 0; while total_bit_errors 100 total_bits max_bits % 1. 随机生成信息比特 info_bits randi([0 1], K, 1); % 2. LDPC编码 codeword ldpc_encode(info_bits, G); % 3. QPSK调制注意每个符号2个比特 symbols qpsk_mod(codeword); % 4. 加噪声 received awgn(symbols, SNR_dB, measured); % 5. 加频偏 received received .* exp(1j*2*pi*f_off*(0:N-1)); % 6. FFT频偏估计与补偿 f_est fft_freq_est(received, fs, 4, Nfft); received_comp received .* exp(-1j*2*pi*f_est*(0:N-1)); % 7. QPSK软解调得到LLR llr qpsk_soft_demod(received_comp, noise_var); % 8. LDPC译码 decoded ldpc_decode(llr, H, max_iter); % 9. 统计错误比特 bit_errors sum(decoded ~ info_bits); total_bit_errors total_bit_errors bit_errors; total_bits total_bits length(info_bits); end ber(k) total_bit_errors / total_bits; end这个框架里有几个值得注意的地方。第一加噪和加频偏的顺序。我的习惯是先加噪声再加频偏或者在加噪的同时加频偏因为实际接收机的A/D之后信号就是带频偏的含噪信号频偏估计器看到的是加完噪声的信号。这样能把频偏估计器的性能也反映到仿真结果里更真实。第二频偏估计器是在每一帧独立估计的。也就是说每一帧的频偏估计结果可能不一样这会带来估计方差的影响。如果你的系统里频偏是恒定不变的也可以先发送一帧估计一次后面所有帧都用这个估计值补偿这样性能会更好一点。但为了更接近实际场景每一帧独立估计更合理。第三LLR计算里的噪声方差。软解调时使用的是AWGN信道的噪声方差但注意如果你在接收端对信号做了频偏补偿补偿操作本身不会改变噪声功率所以噪声方差还是按照原来的EsN0计算即可。但如果你在链路中加入了滤波器或者别的处理噪声方差就要重新估计了。5.3 三组对照仿真的设计思路为了把每个模块的作用都体现出来我建议仿真时至少跑三组曲线曲线1无编码QPSK理论误码率对比用于验证QPSK解调模块正确性曲线2QPSK LDPC无频偏用于衡量LDPC的编码增益曲线3QPSK LDPC 频偏估计与补偿用于验证整个系统的同步能力和端到端性能这三组曲线的对比关系是曲线2比曲线1低很多编码增益曲线3应该跟曲线2基本重合如果有偏差说明频偏估计和补偿还不够理想。曲线3如果明显差于曲线2常见原因有三个频偏估计误差太大增加FFT点数可以改善残余频偏在帧内累积过大减少每帧符号数或做二次细估计频偏估计器在低SNR下失效改用导频辅助估计。这个对照设计的价值在于当某条曲线不对时你能快速定位问题出在哪个模块。比如曲线1不对肯定是QPSK解调或加噪有问题曲线2不对肯定是LDPC编码或译码有问题曲线3不对那就专门排查频偏估计模块。分段定位比面对一个黑盒系统抓瞎强太多了。5.4 结果图的绘制与解读误码率曲线一般用semilogy画纵轴是BER对数坐标横轴是EbN0。figure; semilogy(EbN0_dB, ber_no_code, o-, LineWidth, 1.5); hold on; semilogy(EbN0_dB, ber_ldpc, s-, LineWidth, 1.5); semilogy(EbN0_dB, ber_ldpc_freq, ^-, LineWidth, 1.5); grid on; xlabel(Eb/N0 (dB)); ylabel(BER); legend(QPSK理论,QPSKLDPC (无频偏),QPSKLDPCFFT频偏估计);从曲线上你能直观看到几个结论LDPC带来的编码增益大概有多少dB频偏补偿后性能是否回到无频偏的状态低信噪比区域的错误平层在哪里。这些结论不仅对仿真本身有意义对理解实际系统设计也有帮助——比如如果你的系统要求BER1e-5从曲线上立刻能读出需要的最小EbN0进而推算出发射功率、天线增益等链路预算参数。6. 调试过程中那些容易让人崩溃的问题这一节专门写我在调试这套系统时踩过的坑每一条都是实际调试中遇到的真问题希望对你有帮助。6.1 先分模块验证再级联联调我见过太多人把编码、调制、信道、频偏、译码一次性写完然后运行发现误码率一条线完全不知道问题出在哪。这是最要命的调试方式。我的习惯是严格分阶段验证第一步只跑QPSK无编码对比理论误码率。QPSK在AWGN信道下的理论误码率公式是BER Q(sqrt(2*EbN0))Matlab里berawgn(EbN0_dB, psk, 4, nondiff)可以直接给参考值。如果你的仿真曲线和理论曲线差超过0.2dB说明调制解调或加噪有bug。第二步加入LDPC但去掉频偏。此时如果你用N648的码性能较好的情况下在BER1e-4附近大约需要3.5~4dB的EbN0码率1/2时这个经验值可以当作参考。如果差太远检查LLR符号、归一化、迭代次数。第三步加入频偏。先用较小的频偏比如归一化0.01验证频偏估计模块的单帧性能。可以在某个高SNR下打印估计值和真实值的误差看看是否在预期分辨率范围内。6.2 排查链路问题的通用方法用探针检查信号质量在级联链路中信号从一个模块传到另一个模块中间每一级都可以加探针观察。我最常用的探针是星座图。加噪之后、频偏补偿之后、软解调之前分别画出接收星座图看形状是否合理。在没有频偏时QPSK星座图应该是四个清晰的点团有频偏但没有补偿时星座图是一个圆环补偿之后又回到四个点团。如果频偏补偿后还是圆环形状说明频偏估计或补偿的符号方向搞反了。方向搞反是你自己意识不到的因为幅值都没问题但星座图会越转越厉害。类似的LDPC译码之前可以打印LLR的分布。如果LLR的均值接近0说明解调得到的信息太弱可能是噪声方差给大了如果LLR的符号分布明显不对称可能是LLR计算有偏。6.3 几个典型的性能瓶颈与解决思路实际调试中我发现这几个问题出现频率最高瓶颈1频偏估计器在低SNR下失效。M次方谱估计对噪声敏感当SNR低于某个门限时r^4的谱峰被噪声峰淹没估计结果完全错误导致误码率曲线在低SNR处反而崩溃。解决思路是用导频辅助在一帧里插入已知导频符号接收端对导频位置做相位差分或相关运算估计频偏。导频数量不需要很多每隔几十个符号插一个即可。瓶颈2LDPC码长太短导致性能不理想。N648的码和N1944的码性能差不少。如果你的曲线比预期差很多试试把码长加倍看曲线是否明显改善。如果改善明显说明是码长限制不是代码bug。瓶颈3归一化因子不一致导致SNR换算错误。这个坑比较隐蔽因为链路里所有模块的功率都能对上只有误码率曲线整体偏移。排查方法是用无编码QPSK的曲线作为标尺如果无编码曲线和理论曲线重合说明调制、加噪正确。如果无编码偏移但LDPC曲线看起来正常更要检查LDPC那条曲线的横轴是EbN0还是EsN0。瓶颈4频偏补偿后性能没有恢复。检查补偿方向。如果估计出f_est补偿应该是乘以exp(-1j*2*pi*f_est*t)。有人写成正的结果越补越偏。用连续两帧的星座图对比可以快速看出补偿后是否还旋转。6.4 如何优化仿真速度LDPC译码是整个仿真里最耗时的地方特别是在低信噪比下需要跑很多次迭代。几个提高仿真速度的小技巧用归一化最小和算法代替标准BP减少tanh运算设置合理的最大迭代次数不要盲目设到100启用早停机制收敛后立即退出在高SNR区域可以适当减少每个SNR点的最少运行帧数因为高SNR下误码率本身很低统计到足够的错误比特需要的数据量过大会拖慢整体进度如果机器有多核可以对不同SNR点做parfor并行各SNR之间完全独立并行起来没有通信开销6.5 中文注释和操作视频如何让程序真正可复用最后说一句关于程序配套内容的事。这套程序我特意配了详细的中文注释和一份操作视频。原因很简单通信系统仿真的代码最大的问题不是跑不起来而是别人看的时候不知道每段代码在干什么、为什么这么写。中文注释可以降低这部分成本让你不仅会运行还能根据注释修改参数、调换模块。而操作视频的价值在于它能展示完整的操作流程——从打开Matlab、加载代码、运行仿真到解读每一张图。特别是误码率曲线画出来之后怎么从曲线判断系统性能、怎么调整参数让曲线更平滑这些看文字可能不是一目了然看操作演示就直观多了。我的建议是拿到这套程序后先看一遍操作视频了解整体框架然后自己动手改几个参数比如换码率、换频偏大小观察曲线变化。这样比单纯跑通一遍有用得多。当你把这三个模块的联调都做顺了再回头去看5G、DVB这类实际系统的收发机设计文档思路会清晰很多。所谓同步、编码、调制说到底就是在频谱效率、抗噪能力和实现复杂度之间做权衡而这些东西只有自己亲手仿真过才能真正建立起直觉。本文还有配套的精品资源点击获取
返回列表