OFDM与FBMC子载波频谱仿真:从sinc旁瓣到滤波器组设计
2026/9/10 9:11:28 网站建设 项目流程

简介:针对多载波调制技术中的频谱性能对比需求,这份基于MATLAB 2022A的仿真资料面向通信方向学生与工程师,围绕OFDM与FBMC两种调制方式完成子载波频谱性能仿真,帮助读者理解二者频谱特性差异。压缩包共4个文件,主程序Runme.m内含详细注释,两张jpg为仿真结果图,avi录像展示完整操作过程,整体仅459KB,下载与使用均很轻量。目前已有263人学习下载。通过运行代码可获得OFDM与FBMC子载波频谱对比图,配合操作录像可快速掌握参数设置与运行流程;资料还提示了MATLAB当前文件夹路径需切换至程序所在目录,能有效避免新手常见报错。适合课程设计、毕业设计或相关课题入门参考。

1. OFDM与FBMC子载波频谱仿真:从矩形窗到滤波器组

OFDM在4G/5G里几乎是物理层的代名词,子载波间隔15kHz、循环前缀、sinc形状的频谱,这些概念做过无线通信的人都能说出来。但真到了看子载波频谱这一步,很多人会忽略一个事实:OFDM的矩形窗在频域上导致13dB量级的第一旁瓣,遇到频偏和窄带干扰时,这些旁瓣会直接砸进邻带。FBMC用一组精心设计的原型滤波器替代矩形窗,把旁瓣压到-60dB以下,代价是重叠因子和实现复杂度。这套基于matlab 2022A的仿真工程,用Runme.m一键出OFDM与FBMC两种调制下的子载波频谱图,还带了操作录像,特别适合刚接触物理层算法、准备做滤波器组设计的工程师快速理解两种体制的频谱本质。

2. 子载波频谱成型的理论基础:矩形脉冲与滤波器组

2.1 OFDM中矩形脉冲对应的sinc频谱

OFDM的每个子载波在时域上可以看作一个复指数乘以矩形窗函数。矩形窗在时域长度为T,对应的频域就是sinc函数。sinc函数的零点在1/T的整数倍处,主瓣宽度为2/T,第一旁瓣峰值比主瓣低约13.3dB,旁瓣衰减速度约为6dB/倍频程。多子载波叠加后,由于每个子载波频谱互相重叠,但正交性保证在整数倍子载波间隔处采样时不会互相干扰。

在matlab里验证这个过程很简单。取一个子载波,补零后做FFT,就能看到完整的sinc包络。补零相当于时域上延长观察窗口,频域上相当于内插,并不会改变频谱的物理形状,只是让包络曲线更平滑。

2.2 FBMC滤波器组的设计与频谱聚焦

FBMC的核心是把OFDM的矩形窗替换成原型滤波器。原型滤波器的长度通常等于重叠因子K乘以符号周期T,常见K取4。PHYDYAS滤波器就是被广泛使用的一种,它的系数由频域采样点直接计算。经过该滤波后,每个子载波的频谱只在相邻少数子载波内保持非零,旁瓣大幅衰减,带外泄漏可以做到很低的水平。但FBMC失去了标准OFDM那种矩形窗带来的简单正交性,改成了实部正交,需要配合偏移QAM(OQAM)来保证传输性能。

2.3 两种体制的子载波频谱参数对比

对比项OFDMFBMC(以PHYDYAS为例)
时域基函数矩形窗原型滤波器加频域搬移
频域形状sinc近似带限,旁瓣级联衰减
第一旁瓣峰值约-13.3dB可低于-80dB
子载波间隔Δf = 1/TΔf = 1/T,但重叠因子K影响延迟
正交方式复正交实正交(OQAM)
对同步的要求要求较严格,受频偏影响大因旁瓣低,对频偏相对宽容

这张表对于选型很重要。如果做的是高移动性场景,多普勒频偏较大,OFDM的sinc旁瓣在频偏后会严重破坏子载波间正交性;而FBMC由于旁瓣低,能在一定程度上承受这种破坏,代价是系统延迟和实现复杂度。

3. Matlab实现:OFDM与FBMC频谱生成代码拆解

3.1 全局参数配置

仿真工程里通常有一个参数区,我习惯把所有可调量放在Runme.m开头,方便批量跑。核心参数包括子载波数Ncarrier、符号周期T、采样率fs、FBMC的重叠因子K以及滤波器长度。

% 全局参数设置 Ncarrier = 64; % 子载波数量 T = 1e-3; % 符号周期 1ms fs = 10e3; % 仿真采样率10kHz,确保包络曲线平滑 K = 4; % FBMC重叠因子 Lfilter = K * T * fs; % 滤波器长度,对应40个采样点 oversamp = 8; % 频谱绘制时的过采样倍数

参数说明:子载波数量直接影响频谱的稀疏程度,想看清单个子载波形状时,用64个子载波足够。fs设成10000Hz,是因为符号周期1ms时子载波间隔为1000Hz,过采样8倍后FFT分辨率为10000/(1000*8)=1.25Hz,可以清晰画出旁瓣结构。Lfilter必须等于K乘以T再乘以采样率,否则滤波器的时域长度会和符号周期不匹配,旁瓣抑制会退化。

3.2 OFDM子载波频谱生成

OFDM单个子载波的频谱就是矩形窗做傅里叶变换。实际仿真中一般先生成长度为T的矩形脉冲,再补零,最后FFT观察包络。

% OFDM子载波频谱生成 Nfft = oversamp * Lfilter; % 注意这里用Lfilter的长度来统一比较 t = (0:Lfilter-1) / fs; rect = ones(1, round(T*fs)); % 矩形窗,长度对应符号周期 rect = [rect, zeros(1, Lfilter - length(rect))]; % 补零到滤波器长度 spectrum_ofdm = abs(fft(rect, Nfft)); spectrum_ofdm = spectrum_ofdm / max(spectrum_ofdm); % 归一化 f = (0:Nfft-1) * fs / Nfft; f_shift = f - fs/2; % 搬移到零中心 spec_shift = fftshift(spectrum_ofdm);

逻辑说明:这里为了更好地与FBMC对比,将矩形窗补零到与FBMC滤波器相同的长度Lfilter。FFT点数取oversamp * Lfilter,等效于在频域做精细内插,让sinc的旁瓣曲线更圆滑。归一化后便于比较主瓣峰值。fftshift把零频搬移中间,便于观察负频率到正频率的完整旁瓣。

3.3 FBMC原型滤波器及子载波频谱生成

FBMC原型滤波器可以用PHYDYAS方式生成。PHYDYAS滤波器频域系数有闭式表达式,matlab里实现很简单,我常用的方式是直接在频域定义系数,再通过逆FFT转到时域。

% 生成PHYDYAS原型滤波器 Ncoef = Lfilter / K; % 每个符号周期内的频域采样点数,即10 H0 = 1; H1 = sqrt(2)/2; H2 = 1 - sqrt(2)/2; % PHYDYAS系数 pFreq = [H0, H1, H2, H1, H0]; % 频域抽头,长度必须是2K-1=7,这里简化为5,实际可调整 % 重新插值到Ncoef长度,以便进行ifft pFreq_interp = interp1(linspace(-1,1,length(pFreq)), pFreq, linspace(-1,1,Ncoef), 'spline'); pTime = ifft(ifftshift(pFreq_interp), Lfilter); % 原型滤波器时域脉冲 pTime = pTime / sqrt(sum(abs(pTime).^2)); % 能量归一化 % 生成中心子载波频谱 carrier_freq = 0; % 看零频处子载波 n = (0:Lfilter-1) / fs; subcarrier_fbmc = pTime .* exp(1j * 2 * pi * carrier_freq * n); spectrum_fbmc = abs(fft(subcarrier_fbmc, Nfft)); spectrum_fbmc = spectrum_fbmc / max(spectrum_fbmc);

逻辑说明:PHYDYAS的原型滤波器频域响应在归一化频率轴上是一个近似升余弦的形状。我这里给出的是常用的H0、H1、H2系数,实际工程中需要根据重叠因子K精确计算。ifft之后得到的pTime就是原型滤波器的时域冲激响应,能量归一化是为了让发送功率一致,便于和OFDM对比。将原型滤波器与复指数相乘实现频域搬移,得到某个子载波的基带波形,再做FFT得到它的频谱包络。

参数说明:pFreq_interp这一步容易踩坑。如果直接构造长度Ncoef的频域序列,需要注意频率轴必须关于零频对称,否则ifft得到的时域脉冲会有相位畸变。我习惯用interp1从5抽头插值到Ncoef个点,插值方式用spline可以得到平滑的频域响应,旁瓣特性更稳定。

3.4 两个频谱叠加对比与坐标刻度

生成频谱后,把OFDM和FBMC的包络画在同一张图上,横轴换成归一千载波间隔。这里要注意单位的统一。

% 画图,横轴以子载波间隔归一化 subplot(2,1,1); plot(f_shift/1e3, spec_shift, 'b', 'LineWidth', 1.2); grid on; xlim([-5 5]); title('OFDM子载波频谱'); xlabel('频率 (kHz)'); ylabel('归一化幅度'); subplot(2,1,2); f_fbmc = f - fs/2; spec_fbmc_shift = fftshift(spectrum_fbmc); plot(f_fbmc/1e3, spec_fbmc_shift, 'r', 'LineWidth', 1.2); grid on; xlim([-5 5]); title('FBMC子载波频谱'); xlabel('频率 (kHz)'); ylabel('归一化幅度');

逻辑说明:两个子图共用相同的频率范围,便于肉眼直接对比旁瓣衰减速度。OFDM的频谱在±1kHz处有零点,第一旁瓣出现在±1.5kHz附近,而FBMC的频谱会在很窄的范围内快速跌落。如果只关心旁瓣抑制dB值,可以把幅度轴改成dB,但看包络时线性轴更能直观感受主瓣宽度差异。

4. 运行Runme.m与结果判读:频谱图背后的参数影响

4.1 打开工程的正确姿势

压缩包里包含Runme.m、OFDM_FBMC子载波仿真文件夹、仿真操作录像0019.avi以及两张已生成的频谱图。注意MATLAB左侧当前文件夹路径,必须切到程序所在文件夹。很多人在这一步卡住,在命令窗口看到“未定义函数或变量”就以为是代码问题,实际上是没有设置路径。操作录像里用Windows Media Player播放,画质不高,但能看清每一步点选。

% 在命令窗口设置路径也可以 cd('你的解压路径\OFDM_FBMC子载波仿真'); Runme

如果不想每次改路径,可以把整个文件夹加入MATLAB路径。右键文件夹,选择“添加到路径”,再执行Runme即可。注意不要直接双击Runme.m然后点“运行”,因为双击打开时当前路径通常是MATLAB的默认路径,脚本里如果用了相对路径读取数据就会失败。

4.2 录像中的关键操作流程

录像总共几十秒,流程是:启动MATLAB 2022A,左侧定位文件夹,打开Runme.m,点击运行,弹出两个频谱图窗口。图上有OFDM和FBMC各自的子载波频谱曲线。录像的结尾还展示了如何通过缩放工具查看旁瓣细节。

我建议自己运行时多做一个动作:在Runme.m里设置断点,逐段执行,观察工作区里pTime和spectrum_ofdm的尺寸。这样能理解每条语句产生的是什么。比如spectrum_ofdm是Nfft长度的向量,如果没有fftshift,图形会左右对称但零点不在中间,容易误判主瓣位置。

4.3 频谱图怎么读

拿到频谱图后,第一看主瓣宽度。OFDM主瓣零点点间距是2/T,对应2000Hz,FBMC主瓣虽然也有一定宽度,但能量更集中。第二看第一旁瓣高度。用数据游标点一下第一旁瓣的峰值,读取相对于主瓣的dB值。OFDM大约-13.3dB,FBMC按照原型滤波器设计,可以做到-40甚至-60dB。第三看旁瓣跌落趋势。OFDM的旁瓣呈sinc式衰减,比较缓慢;FBMC旁瓣在几个间隔以外迅速淹没在数值噪声里,如果噪声底在-300dB,说明滤波器强制清零了旁瓣。

仿真时要注意,频谱的归一化方式会影响dB读数。如果直接用线性幅度归一化到最大值,那么第一旁瓣-13.3dB在图上就是0.22左右,需要手动换算。更专业的做法是先取20*log10(幅度),再用最大值归零,这样读出的dB值就是实际旁瓣抑制。

% dB显示示例 spec_db_ofdm = 20 * log10(spec_shift + eps); spec_db_ofdm = spec_db_ofdm - max(spec_db_ofdm);

提示:matlab的log10在0处会出现-inf,所以加一个eps避免图形断裂。这在画频谱时是个常见的细节。

5. 进阶:子载波间隔、重叠因子与旁瓣抑制的边界验证

5.1 修改子载波数量看频谱密度变化

把Ncarrier从64改成128或256,重新运行,你会发现OFDM的子载波频谱图整体形状不变,因为单个子载波频谱只和符号周期T有关。但在多子载波叠加图中,相邻子载波间距依然是1/T,而总带宽变宽。真正需要留意的是FFT点数Nfft是否足够。我一般取oversamp*Lfilter=320,在128个子载波时依然足够,但如果子载波数超过1024,建议把oversamp提高到16,否则绘制的包络线会有锯齿。

5.2 重叠因子K对FBMC频谱的影响

这是FBMC仿真里最容易出效果也最容易出问题的参数。K=2时滤波器长度短,旁瓣抑制只有-20dB量级;K=4时能达到-60dB;K=6时理论上能到-90dB,但时延显著增加。修改K后,PHYDYAS的频域系数需要重新计算,不能简单沿用H0、H1、H2。一个经验公式是频域抽头系数满足相位条件,但更快的做法是通过迭代算法设计原型滤波器。在工程仿真里,我通常固定K=4,因为它是性能与复杂度的平衡点。

% 验证不同K的旁瓣抑制 Ks = [2, 4, 6]; for ki = 1:length(Ks) Lfil = Ks(ki) * T * fs; % 这里需要重新设计原型滤波器,伪代码略 % 计算频谱后记录第一旁瓣峰值 end

5.3 正交性验证:计算子载波间干扰

FBMC的旁瓣低不代表正交性一定好,工程上更关心在两个子载波之间的干扰。可以用一个简单方法验证:让第m个子载波发送单位脉冲,在第n个子载波的匹配滤波器输出处采样,观察残留值。如果残留值在-80dB以下,说明该组滤波器参数可用。

% 子载波间干扰计算示例 delta_f = 1 / T; % 子载波间隔1000Hz m = 2; n = 3; % 第2和第3个子载波 freq_shift = (n - m) * delta_f; rx = pTime .* exp(1j * 2 * pi * freq_shift * n); interference = abs(sum(rx .* conj(pTime)))^2; % 内积模平方

逻辑说明:这个内积计算模拟了接收端用第m个子载波的匹配滤波器去收第n个子载波信号的场景。理想情况下两者正交,内积为0。由于PHYDYAS滤波器是实数正交,直接复内积不一定为零,需要把实部和虚部分开判断。所以如果刚才那个值不为零,先别急着改参数,改成real(sum(rx .* conj(pTime)))^2再验证,这才是FBMC的正交条件。

提示:当K=4时,间隔1个子载波的干扰通常已经低于-60dB,间隔3个子载波以上直接跌到-100dB以下。如果调试时发现干扰降不下去,优先检查原型滤波器的频域系数是否对称、时域脉冲长度是否为KTfs的整数倍。这两个位置最容易出错。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询