十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OFDM仿真:AWGN与瑞利衰落信道下的Matlab实现与BER分析

OFDM仿真:AWGN与瑞利衰落信道下的Matlab实现与BER分析 简介面向通信工程与无线传输方向学习者的OFDM基带仿真资源覆盖AWGN信道与瑞利衰落两种典型场景适合正在搭建OFDM收发链路、研究循环前缀/零填充保护间隔及误码率性能的初学者或进阶者。压缩包共25个文件以8个MATLAB脚本、8个.fig仿真图、8个.dat误码率数据文件为主并含1张整体效果图包体约252KB。脚本涵盖OFDM基本收发、保护间隔设置、QAM调制映射、BER统计与正交性验证等核心环节对应fig与dat文件可辅助复现不同信道条件和保护间隔长度下的性能对比。已有200人学习下载资料体量精简、脚本与绘图数据配套便于按模块阅读和修改适合作为OFDM课程设计或通信原理实验的参考实现。1. 为什么OFDM仿真要同时面对AWGN和瑞利衰落OFDM仿真的价值在于可以用一套收发链路同时验证两种截然不同的信道假设AWGN只改变信噪比不引入符号间干扰瑞利衰落则会让子载波增益随机起伏甚至因多径时延产生频率选择性衰落。很多人在Matlab里已经跑通了QPSK在AWGN下的误码率但换成瑞利信道后误码率曲线掉不下去问题往往不在信道代码本身而是接收端少做了信道估计和均衡。下面的内容把两种信道分别接到同一套OFDM链路上给出可复现的发送、加噪、信道、接收和误码统计方法并把参数设置依据和常见误用一起讲清楚适合正在做毕业设计仿真或物理层算法验证的工程师直接对照修改。2. OFDM链路模型与两种信道的作用位置2.1 信道作用在OFDM链路的哪个环节OFDM发送端的一般流程是数据比特经过调制映射成QAM符号按子载波数量N切成块每块做一次IFFT变换到时域然后在符号前插入循环前缀CP最后形成基带复数信号txSig。接收端先做帧同步和去CP再按块做FFT从频域符号恢复比特。信道作用的位置明确位于txSig和rxSig之间。AWGN信道是在时域信号上叠加高斯白噪声。因为IFFT是正交变换白噪声在频域的统计特性不变每个子载波的噪声分量独立且等功率所以AWGN对OFDM的影响就是每个子载波的信噪比同时降低子载波间的正交性不受破坏。瑞利衰落信道则复杂一些如果只有一条径并且没有多普勒频移信道退化为乘一个固定复增益所有子载波经历同样的衰减和旋转接收机可以用一个复数系数补偿如果有多个时延不同的径信号是各径副本的叠加频域各子载波增益不再平坦均衡器必须在每个子载波上单独估计增益。判断信道仿真代码是否写对就是看有没有反映上述差异。AWGN代码如果对频域符号每个子载波乘不同增益那就不合理瑞利代码如果只加噪声而信号幅度完全不变说明衰落并没有真正生效。2.2 AWGN与瑞利信道下误码率差异的直觉AWGN下16QAM的理论误码率随Eb/N0增加快速下降大约在17.5dB左右达到10^-4。瑞利平坦衰落信道下瞬时信噪比的概率密度函数是指数分布平均信噪比20dB时仍然有约1%的概率瞬时信噪比低于0dB这些深衰落符号即使相位估计正确也难以解对所以整体误码率远高于AWGN。OFDM系统需要交织、信道编码和自适应调制来对抗深衰落物理层仿真的目的之一就是量化这些技术在瑞利信道下的增益。仿真层面有个典型现象如果瑞利的BER曲线与AWGN几乎重合基本可以断定衰落路径没有打通常见原因包括信道对象没有作用于信号或者均衡放大了噪声却没有补偿增益。这类问题在BER曲线上表现为高SNR段斜率与AWGN相同而不是变缓排查时先看星座图而不是先调噪声功率。2.3 仿真前确定OFDM参数与信道参数仿真参数先定下来再写代码才有意义。以子载波数64、CP长度16为例如果多径时延扩展设定为12个采样点那么CP远大于时延扩展系统处于循环前缀保护有效的状态频域均衡效果会比较理想。如果时延扩展超过CP长度就算做了频域均衡也会因为ICI产生误码平层这个平层不是噪声造成的而是OFDM本身对时延扩展的敏感度上限。参数推荐取值说明子载波数 N64IFFT/FFT的点数CP长度16必须大于最大多径时延调制方式16QAM每个符号4比特采样率 fs1e6 Hz决定子载波间隔和时延量化多径时延[0 5e-6 12e-6] s对应0、5、12个采样点最大多普勒频移50 Hz对应低速移动场景这组参数确定后子载波间隔等于fs/N约为15.625kHz符号长度为64微秒加CP后80微秒。多径时延12微秒小于CP的16微秒循环前缀保护有效。同时要注意信道相干带宽约等于1/(5×时延扩展)按12微秒时延估算约为16.7kHz和子载波间隔接近意味着相邻子载波经历相近的衰落这为导频子载波按组插入提供了依据。为了方便遍历时延配置建议在代码里加一个保护检查% 检查时延扩展是否在CP保护范围内 fs 1e6; pathDelays [0 5e-6 12e-6]; cpDuration cpLen / fs; maxDelay max(pathDelays); if maxDelay cpDuration error(多径时延超过CP需要增大CP长度或减小时延扩展); end fprintf(CP时长: %.3f us\n最大时延: %.3f us\n, ... cpDuration*1e6, maxDelay*1e6);这个检查在参数化仿真里很有用遍历多径时延时可以自动跳过无效配置避免后面均衡结果失真。提示CP长度覆盖多径时延只是OFDM成立的必要条件实际系统还要考虑定时误差和信道时变带来的残余ICI仿真收益有限时不必追求理论极限。3. Matlab里先搭OFDM基带链路再叠加AWGN3.1 最小可运行的OFDM发送端代码先把发送端写出来所有符号都按矩阵方式组织便于后面插入导频和扩展信道编码。% ofdm_tx.m 基础发送端 N 64; % 子载波总数 cpLen 16; % 循环前缀长度 M 16; % 16QAM numFrames 500; % OFDM符号帧数 dataBits randi([0 1], N*log2(M)*numFrames, 1); dataSym qammod(dataBits, M, InputType, bit, UnitAveragePower, true); symMat reshape(dataSym, N, numFrames); ifftOut ifft(symMat, N, 1); txSig [ifftOut(end-cpLen1:end, :); ifftOut]; txSig txSig(:);UnitAveragePower设为true时16QAM符号平均功率为1后面按SNR加噪声时可以直接把信号功率当1来计算。如果不写这个参数Matlab会按符号最小距离为2的方式归一化16QAM平均功率约为10同样的噪声功率下信噪比会偏差约10dB。reshape按列填充正好把一个OFDM帧放在一列里IFFT也按列计算避免自己在两层循环里处理子载波索引。循环前缀的插入用了矩阵切片先取ifftOut最后cpLen行接到顶部再整体纵向拼接。这样每列是一个带CP的完整OFDM符号最后txSig(:)按列排成串行发射波形。这里有个被忽略的点IFFT默认不缩放FFT也不缩放Matlab这种约定让频域信道响应可以直接表示为rxSym和txSym的比值保留这个默认行为对后面均衡实现最省事。3.2 用awgn加噪声的两种写法和参数差异AWGN的叠加可以调用awgn函数也可以手动构造噪声。两种写法在代码里都要熟悉因为后面瑞利衰落场景里两种写法会带来不同的统计含义。% 写法1: awgn函数SNR固定 snrDb 15; rxSig awgn(txSig, snrDb, measured); % 写法2: 手动生成复噪声噪声功率固定 sigPower mean(abs(txSig).^2); noisePower sigPower / (10^(snrDb/10)); noise sqrt(noisePower/2) * (randn(size(txSig)) 1j*randn(size(txSig))); rxSig txSig noise;awgn第三个参数measured表示先测量输入信号功率再计算噪声功率。这个方法在信号功率恒定时很方便但OFDM信号虽然有归一化平均功率每一帧的瞬时功率仍有波动实测功率会和理论值有几dB的差别。手动写法把噪声功率固定下来信噪比跟随信号功率浮动更贴近真实接收机看到的场景信道噪声是由接收机带宽和温度决定的信号功率和信道衰落才是变量。复噪声的方差分配是常见出错点。噪声功率noisePower是复信号的总功率实部和虚部各分一半所以每个分量要乘sqrt(noisePower/2)。只给实部加噪声等效信噪比会比设定低3dBBER曲线整体右移而且在低信噪比段特别明显。另一个细节是awgn函数默认假设输入为实数传入复数信号时它会自动构造复噪声但手动写法里很多人会忘记虚部噪声分量导致噪声功率减半。3.3 接收端解调与AWGN下的误码统计接收端按逆过程展开去CP、FFT、解映射最后统计误码率。rxMat reshape(rxSig, NcpLen, numFrames); rxData rxMat(cpLen1:end, :); rxSym fft(rxData, N, 1); rxSymFlat rxSym(:); rxBits qamdemod(rxSymFlat, M, OutputType, bit, UnitAveragePower, true); bitErrRate sum(rxBits ~ dataBits) / length(dataBits);这里reshape(rxSig, NcpLen, numFrames)要求rxSig长度严格等于帧数乘以(NcpLen)如果发送端在CP插入前修改过帧数这一行会直接报维度不匹配。更稳妥的做法是先reshape成矩阵再去CP而不是按长度切割成一个向量再重建矩阵。加AWGN前后没有引入符号定时偏移所以去CP时从cpLen1开始取即可如果后面接入多径信道接收端还要先估计定时位置。AWGN链路跑通后需要确认SNR与Eb/N0的换算。awgn函数接收的是SNR而理论BER曲线通常以Eb/N0为横轴两者差一个10*log10(log2(M))对应关系如下调制阶数每符号比特数SNR相对Eb/N0的偏移QPSK23.01 dB16QAM46.02 dB64QAM67.78 dB如果把awgn的SNR值直接当成Eb/N0去对理论曲线仿真点会比理论值右移约6dB。很多初写OFDM仿真的人卡在这一步不是因为收发链路有错而是横轴定义没对齐。做完一次AWGN校验后可以顺手用scatterplot(rxSymFlat)看一眼解调前的星座图噪声环境下星座点云团如果呈圆形对称说明加噪方式没问题。4. 瑞利衰落模拟从平坦衰落到多径时延4.1 用comm.RayleighChannel实现平坦衰落Matlab里生成瑞利衰落信道的推荐接口是comm.RayleighChannel老代码里常见的rayleighchan在高版本中虽然还能用但新工程最好直接用comm对象参数语义更清晰也方便配置多径和多普勒。fs 1e6; channelFlat comm.RayleighChannel(... SampleRate, fs, ... PathDelays, 0, ... AveragePathGains, 0, ... MaximumDopplerShift, 0); fadedTx channelFlat(txSig);PathDelays0代表单一径AveragePathGains0代表该径平均功率0dBMaximumDopplerShift0代表信道在一个仿真批次的全部帧内不随时间变化。这个配置适合先验证接收链路的均衡和解调逻辑是否正确因为信道是静止的任何误码率异常都可以归因到收发链路本身。MaximumDopplerShift设为50Hz时信道在每个采样点之间连续变化连续OFDM帧之间的衰落相关统计误码率需要跑到几千帧以上曲线才平滑。需要留意comm.RayleighChannel内部用多径滤波器实现卷积输出波形的起始段有瞬态效应。严格做符号定时同步时要先用训练序列估计出信道冲激响应的起始位置再决定去CP窗口偏移。教学性质的仿真可以忽略这个延迟但在和实际硬件联调时不能忽略否则整段CP窗口整体偏移误码率会无规律波动。4.2 多径时延和多普勒频移的参数设置频率选择性衰落的参数配置如下channelMulti comm.RayleighChannel(... SampleRate, fs, ... PathDelays, [0 5e-6 12e-6], ... AveragePathGains, [0 -3 -8], ... MaximumDopplerShift, 50); fadedMulti channelMulti(txSig);参数值含义PathDelays[0 5e-6 12e-6] s三条路径的时延AveragePathGains[0 -3 -8] dB三条路径的平均功率MaximumDopplerShift50 Hz移动带来的多普勒扩展SampleRate1e6 Hz决定时延的采样点数量5微秒时延对应5个采样点12微秒对应12个采样点都在CP长度16以内。时延最好用非整数倍采样周期的值来模拟真实场景例如[0 4.7e-6 11.3e-6]但调试时先设整数倍可以逐点核对卷积输出。AveragePathGains的衰减值是平均意义上的瞬时功率仍然服从指数分布因此第二径在某几个符号上可能比直射径还强这正是瑞利衰落环境下的典型情况。如果想把时延扩展到超过CP长度比如25微秒系统就会出现符号间泄漏。运行同样的均衡代码BER会在高信噪比段出现平台无论怎么增加SNR都降不下去。这是OFDM对时延扩展敏感性的直接体现也是调参时可以主动验证的一个边界条件。另外注意路径时延值在comm.RayleighChannel内部会按采样周期量化如果时延不是采样间隔的整数倍能量会泄漏到相邻抽头上所以对比解析结果和仿真结果时要先用info(channelMulti)查看实际生成的信道冲激响应。4.3 导频估计与频域均衡的完整实现瑞利信道下接收端必须在数据解调之前估计每个子载波的频域信道响应。下面是一套带导频的收发流程发送端预留导频子载波接收端做LS估计和插值。N 64; cpLen 16; M 16; numFrames 500; pilotSub [8 20 32 44 56]; % 导频子载波 dataSub setdiff(1:N, pilotSub); % 数据子载波 pilotSym ones(length(pilotSub), 1); % BPSK导频功率为1 dataBits randi([0 1], length(dataSub)*log2(M)*numFrames, 1); dataSym qammod(dataBits, M, InputType, bit, UnitAveragePower, true); dataSymMat reshape(dataSym, length(dataSub), numFrames); txFrame zeros(N, numFrames); txFrame(dataSub, :) dataSymMat; txFrame(pilotSub, :) repmat(pilotSym, 1, numFrames); ifftOut ifft(txFrame, N, 1); txSig [ifftOut(end-cpLen1:end, :); ifftOut]; txSig txSig(:); % 经过多径瑞利信道后加噪声 fadedSig channelMulti(txSig); snrDb 22; rxSig awgn(fadedSig, snrDb, measured); % 接收端去CP、FFT rxMat reshape(rxSig, NcpLen, numFrames); rxFrame rxMat(cpLen1:end, :); rxSym fft(rxFrame, N, 1); % 导频位置的LS信道估计 rxPilot rxSym(pilotSub, :); chanEstPilot rxPilot ./ pilotSym; % 线性插值到全部子载波 chanEstAll interp1(pilotSub, chanEstPilot, 1:N, linear, extrap); % 频域均衡 eqSym rxSym ./ chanEstAll; rxDataSym eqSym(dataSub, :); rxBits qamdemod(rxDataSym(:), M, OutputType, bit, UnitAveragePower, true);LS估计的除法需要在每个OFDM帧上独立执行因为信道状态随帧变化。pilotSym为1时除法简化为直接取导频处的接收符号这里保留显式除法是为了后续改成CAZAC序列或幅度非1的导频时逻辑不变。插值使用interp1的linear模式对复值会分别插实部和虚部导频间距较小时表现足够。导频间隔要和相干带宽匹配子载波间隔15.625kHz时5个子载波一组对应的频域跨度约78kHz在典型室内环境下小于相干带宽插值误差可控。导频子载波如果太少线性插值会漏掉频域响应的深谷均衡后残余误差变大BER会出现平层。导频比例一般取总子载波数的5%到15%在这个范围内增加导频的收益需要配合信道编码的增益一起评估。如果要做更高阶的64QAM信道估计误差对误码率的影响会更大导频间距要相应缩短。5. 用BER曲线校验OFDM信道模拟是否正确5.1 理论BER和仿真BER的对比方法AWGN下的校验用berawgn直接生成理论曲线把仿真点和理论曲线画在同一张半对数图上。ebN0Db 0:2:20; snrDb ebN0Db 10*log10(log2(M)); % 16QAM偏移6.02dB berTheory berawgn(ebN0Db, qam, M); % 对每个snrDb跑一遍3.3的收发统计得到 berSim semilogy(ebN0Db, berTheory, k-, ebN0Db, berSim, ro); grid on; xlabel(Eb/N0 (dB)); ylabel(BER); legend(理论曲线, 仿真结果);横轴一定要统一到Eb/N0。16QAM是每符号4比特所以SNR比Eb/N0高约6dB。如果不做换算仿真曲线整体右移看起来像实现有3dB损失实际上只是横轴定义没对齐。仿真的误码率统计点数要足够BER到10^-4时至少需要统计100个错误比特也就是至少传输10^6比特否则曲线末段会剧烈抖动。按500帧、64个子载波、16QAM计算总共只传输约128000比特只能支撑到10^-3量级的统计想看到更低的BER必须加大帧数。5.2 误码率曲线异常的排查方向异常现象常见原因排查动作BER整体右移数dBEb/N0与SNR换算漏了log2(M)对比snrDb和ebN0Db的换算高SNR段出现平层导频过稀或时延超CP增加导频密度或减小时延瑞利BER和AWGN重合信道对象未作用或未均衡打印fadedSig功率并与txSig比较曲线抖动剧烈帧数不足或信道未重置帧数提升到5000以上其中瑞利BER和AWGN重合最常出现因为很多人把瑞利信道放在发射端与噪声之间却忘了接收端要做均衡结果就是把衰落当成了固定的幅度缩放解调星座图仍然聚在理想点附近。用scatterplot(eqSym(:))看一眼均衡后的星座图能快速判断是信道估计错误还是均衡方向错误。如果星座图有明显旋转但整体聚拢优先检查导频符号相位如果星座图发散成环状优先检查插值算法线性插值在导频间距过大时会产生明显的幅度误差。5.3 边界退化测试和导频密度检查仿真代码调通后再用两个边界测试确认信道模拟的鲁棒性。第一个测试是把多径时延全部设为0、多普勒频移设为0此时comm.RayleighChannel退化为一条时不变的复数增益路径BER曲线应和手动构造的瑞利平坦衰落一致第二个测试是导频密度减半看BER是否变差如果变差说明原导频配置是系统瓶颈如果不变说明还有冗余。% 退化测试1: 多径时延清零等效平坦衰落 channelFlat comm.RayleighChannel(SampleRate, fs, ... PathDelays, 0, AveragePathGains, 0, MaximumDopplerShift, 0);退化测试的价值在于把复杂信道对象和手写衰落模型对照一次能排除Matlab版本升级导致的默认参数变化也让后续使用这个信道对象时更有把握。命令行直接对比两种信道下同一SNR的星座图散点分布如果形状一致说明信道对象配置语义理解正确。之后再单独把最大多普勒频移从0调到50Hz观察BER曲线是否略微抬升这是验证时间选择性衰落有没有生效的最快方式。做完这组测试整套OFDM信道模拟才算真正具备了复用条件后续加信道编码、加同步算法才能有可靠的基线参照。本文还有配套的精品资源点击获取
返回列表