ARTICLE DETAIL

资讯详情

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

MATLAB仿真FDM与TDM:从原理到代码的完整实现

MATLAB仿真FDM与TDM:从原理到代码的完整实现 简介一份关于频分复用与时分复用系统仿真的通信原理课程项目报告面向通信原理课程学习者以及需要完成类似课设的高校本科生。报告以上海大学冬季学期通信原理项目为背景完整搭建了在高斯信道中传输的频分复用与时分复用频带传输系统详细说明了系统建模、参数设置与性能测试过程可帮助读者快速理解多路复用技术的工程实现。资源仅包含1个Word文档大小约1.06兆字节内容涵盖频分复用的频谱搬移与相干解调、时分复用的抽样原理与帧同步设计并配有图形用户界面及各阶段波形、频谱截图。文档结构按照项目报告格式组织先介绍频分复用与时分复用的基本原理再给出仿真模型设计、图形界面搭建和结果分析最后还讨论了同步与噪声对系统性能的影响便于学习者按步骤对照练习。目前已有268人学习下载适合作为课程报告撰写或通信原理实验的参考范例。读者可以借鉴其系统框图、参数配置和结果分析方式在此基础上扩展自己的设计方案。 在通信原理这门课上频分复用FDM和时分复用TDM几乎是必考必学的两块内容。但我发现很多同学学完整个学期能把公式推导写得飞起却从来没有在MATLAB里真正看到过频分复用和时分复用的完整收发链路长什么样。等到课程设计或者实验报告需要交仿真的时候只能翻来覆去改网上的半成品代码改又改不明白跑又跑不通。这篇内容就是来解决这个问题的。我会从零开始把FDM和TDM两套系统的完整MATLAB仿真实现拆开揉碎讲清楚——从信号生成、复用、信道传输、解复用到最终恢复出原始信号每一段代码都贴出来每一处关键参数都说明白为什么这么选。无论你是在准备通信原理实验报告还是在复习考研复试的通信基础或者单纯想把教材上的框图变成能跑的代码这篇都能直接给你一条能走通的路。1. 先搞明白一个根本问题FDM和TDM在MATLAB里到底在做什么很多教程一上来就扔代码结果读者连仿真的对象都没搞清楚。所以在我贴第一行代码之前先花点时间把这两件事的逻辑脉络理清楚。1.1 从车道和房间的比喻理解两种复用思路频分复用说白了就是给每路信号划一段专属的频率区间大家同时在线但各占各的频带互不干扰。就像一条高速公路不同车道跑不同的车车道之间用隔离带保护间隔挡开车辆信号在各自的频率车道上并行传输。时分复用则是大家轮流使用同一段频率区间按时间切片轮流发送。就像一间会议室不同小组轮流进去开会每个小组用固定的时间段时间一到就换下一个组会议室信道在同一时刻只有一个人在占用。这两种思路在MATLAB里的建模方式完全不一样FDM仿真核心是频谱操作你需要设计载波频率、安排频带间隔、用滤波器把各路信号在频域上分开。TDM仿真核心是时间操作你需要设计时隙长度、做串并转换、在接收端掐准时间点采样然后用插值或滤波器恢复信号。1.2 为什么用MATLAB做这个仿真最有价值教科书上画FDM系统框图就是几个乘法器加一个加法器再接一堆滤波器看起来简单到不行。但你真去实现的时候就会发现几个棘手的问题一是频率轴到底怎么标。MATLAB的fft结果默认从0到采样率很多人画频谱图直接画对称谱结果载波频率跟频谱图上的位置对不上调半天不知道错在哪。二是数字滤波器根本不是理想滤波器。教科书里说用带通滤波器把各路信号分出来但滤波器的阶数、截止频率、过渡带宽这些参数选不好要么把相邻频带的信号漏进来要么把自己的信号滤没了。三是采样率怎么定。采样率太低高频载波根本表示不出来采样率高了FFT点数不够频率分辨率太差频谱图糊成一团。这三件事恰恰是MATLAB仿真最能暴露问题、也最能帮你加深理解的地方。你在代码里把这些问题一个个解决掉通信原理里那些频带利用率正交性串扰的概念会变得非常具体。2. 仿真前的公共准备信号设计与参数选择的底层逻辑无论FDM还是TDM第一步都是生成需要传输的源信号。我这里用最典型的语音近似信号——正弦波叠加再加一点随机噪声既有周期性又有随机性恢复效果肉眼可辨。2.1 参数基线的确定先定一组公共参数后面两套系统都用这组信号%% 公共参数设置 fs 8000; % 采样率 8kHz电话语音标准采样率 t_total 1; % 仿真时长 1秒 t 0:1/fs:t_total-1/fs; % 时间向量 N length(t); % 总采样点数 8000 % 三路基带信号模拟三路独立的语音/数据 f1 300; % 第一路信号基带频率 f2 600; % 第二路信号基带频率 f3 900; % 第三路信号基带频率 x1 sin(2*pi*f1*t) 0.3*sin(2*pi*2*f1*t); % 第一路300Hz基波600Hz二次谐波 x2 0.8*sin(2*pi*f2*t) 0.2*sin(2*pi*1.5*f2*t); % 第二路600Hz基波900Hz谐波 x3 sin(2*pi*f3*t) 0.25*sin(2*pi*3*f3*t); % 第三路900Hz基波2700Hz谐波这里把采样率定成8000Hz原因有两个一是电话通信的标准采样率就是8kHz语音信号带宽4kHz以内符合奈奎斯特采样定理二是三路基带信号的频率都在300~2700Hz范围直接采样不会混叠后续做频谱分析时频率轴也好看。信号设计上给每路信号都叠加了谐波分量这是故意为之的为的是让信号包含不止一个频率成分这样在FDM系统里才能看出频带偏移的效果——如果每路只是一个单频正弦解调出来波形完美其实是理所当然的没有说服力。2.2 三件容易被忽略的准备工作2.2.1 画频谱图的频率轴要统一MATLAB里fft之后频率轴有两种画法单边谱和双边谱。我强烈建议你写一个通用函数后面所有频谱图统统用它画省得每次都要调function plot_spectrum(x, fs, title_str) N length(x); X fft(x); f (0:N-1) * fs / N; % 频率轴0 ~ fs mag abs(X(1:N)); % 幅值不归一化 plot(f, mag); xlim([0 fs/2]); % 只看0~4kHz单边 xlabel(频率 (Hz)); ylabel(幅度); title(title_str); end这个函数判断标准很简单凡是画频谱x轴必须是真实的物理频率Hz不是FFT点数。很多新手直接plot(abs(fft(x)))出来的横坐标是0到8000的整数点跟真实频率差了8倍这是最大的坑。2.2.2 滤波器的设计思路要先定下来FDM的解复用必然要用带通滤波器TDM恢复信号要用低通滤波器。MATLAB里设计滤波器有两个方向FIR滤波器用fir1线性相位、稳定但同样的过渡带需要更高阶数。IIR滤波器用butter阶数低、计算量小但有非线性相位。在仿真场景中我建议用巴特沃斯IIR滤波器原因很直白阶数4~6阶足够陡峭计算量可以忽略不计而且在仿真里没有硬件实现时的稳定性问题代码写起来更短。如果用FIR想要类似的陡峭程度阶数得上百毫无必要。后面我会给出两种滤波器的用法你对比一下就能感受到差异。2.2.3 放噪声的单位别搞错给信号加噪时MATLAB的awgn函数输入SNR单位是dB但很多人误以为传的是线性信噪比。比如awgn(x, 20)意思是加噪声使信噪比为20dB也就是信号功率是噪声功率的100倍。这在对比不同信噪比下的解调效果时特别关键我做测试时习惯从30dB一路降到0dB看系统什么时候开始崩溃。3. FDM完整仿真从频带分配到滤波器解调的每个细节3.1 频带划分方案与调制实现FDM系统的核心设计问题就是各路信号放到什么频段上。我这里选一组非常干净、非常好解释的参数基带信号最高频率x1约600Hzx2约900Hzx3约2700Hz第一路载波fc1 4000Hz占用频带约3400~4600Hz第二路载波fc2 8000Hz占用频带约7100~8900Hz第三路载波fc3 12000Hz占用频带约9300~14700Hz选择4000Hz作为第一个载波而不是紧贴着信号带宽是为了留出保护间隔——模拟真实系统里为防止相邻信道串扰而预留的频率空隙。载波间隔取4000Hz保证了各路频谱在频域上完全不重叠。%% FDM调制端 fc1 4000; fc2 8000; fc3 12000; % 三路载波频率 % 载波信号同相载波模拟相干解调 c1 cos(2*pi*fc1*t); c2 cos(2*pi*fc2*t); c3 cos(2*pi*fc3*t); % 抑制载波双边带调幅DSB-SC调制 s1 x1 .* c1; s2 x2 .* c2; s3 x3 .* c3; % 频分复用信号 三路直接相加 fdm_signal s1 s2 s3;这里用的是DSB-SC调制抑制载波双边带就是时域相乘。用这个调制方式有三个好处数学最简单、频谱搬移效果最直观、而且它暴露问题也最直接——接收端必须做相干解调本振频率和相位必须严格同步否则恢复出来的信号会带频偏或相位失真。3.2 调制后的频谱验证这一步绝不能省调制完了先别急着加噪声、解调先画一下fdm_signal的频谱确认三路信号确实各就各位了。这一步是整篇仿真里最值回票价的操作因为你亲眼看到了理论上的频谱搬移。figure; plot_spectrum(fdm_signal, fs, FDM复用信号频谱三路已搬移到不同频段);正常你会看到三个清晰的频谱包络一个在4kHz附近一个在8kHz附近一个在12kHz附近。如果这里看不出来三个独立波峰说明载波频率不够高或者基带信号频率太高了叠加产生重叠后面的解调必炸。3.3 信道传输与接收端分路滤波器设计仿真必须过信道我这里主要用awgn加白噪声来模拟信道衰减之外的干扰snr_dB 20; % 先试20dB信噪比适中 rx_fdm awgn(fdm_signal, snr_dB, measured);接收端最关键的一步是用带通滤波器把三路信号分别滤出来。滤波器设计思路对第一路通带覆盖3400~4600Hz过渡带向外扩一点对第二路通带覆盖7100~8900Hz对第三路通带覆盖9300~14700Hz。%% 三路带通滤波器设计巴特沃斯 order 6; % 第一路滤波器通带 3400~4600 Hz Wn1 [3400 4600] / (fs/2); % 归一化截止频率 [b1, a1] butter(order, Wn1, bandpass); % 第二路滤波器通带 7100~8900 Hz Wn2 [7100 8900] / (fs/2); [b2, a2] butter(order, Wn2, bandpass); % 第三路滤波器通带 9300~14700 Hz Wn3 [9300 14700] / (fs/2); [b3, a3] butter(order, Wn3, bandpass); % 滤波分路 y1_band filter(b1, a1, rx_fdm); y2_band filter(b2, a2, rx_fdm); y3_band filter(b3, a3, rx_fdm);注意butter函数传的Wn必须是归一化频率实际频率除以奈奎斯特频率fs/2这个错误出现频率极高。很多人直接写butter(order, [3400 4600], bandpass)运行时MATLAB直接报错或者滤波效果完全不对。滤波器设计完重要的一步是检查滤波器的频率响应确认过渡带没有覆盖到相邻信道。用freqz(b1, a1, 1024, fs)画一下如果通带边缘不够陡把order从6提到8或10但要注意阶数太高会带来较大的相位畸变。仿真阶段我建议6阶起步效果不够再加不要一上来就给高阶。3.4 相干解调与低通滤波恢复滤出来的信号是已调信号在载波频段上要恢复基带信号需要乘以同频同相的本地载波再低通滤波。这就是相干解调的标准流程%% 相干解调 v1 y1_band .* c1; % 乘以本地载波 v2 y2_band .* c2; v3 y3_band .* c3; % 低通滤波器截止频率设为每路基带信号的最高频率余量 lpf_order 6; lpf_cut 1200 / (fs/2); % 第一、二路用1200Hz低通足够基带最高900Hz [bl, al] butter(lpf_order, lpf_cut, low); x1_hat filter(bl, al, v1); x2_hat filter(bl, al, v2); x3_hat filter(bl, al, v3);这里有个细节值得解释解调输出v1里含有基带信号、2倍载波频率的高频分量4kHz×28kHz附近低通滤波器就是要把载波的二倍频成分滤掉。截止频率1200Hz远低于8000Hz所以二倍频分量会被滤得干干净净。3.5 主观与客观双重验证恢复完了别急着收工做两件事一是时域波形对比figure; subplot(3,1,1); plot(t, x1, b); hold on; plot(t, x1_hat, r--); legend(原始信号x1, 恢复信号x1\_hat); title(第一路信号恢复对比); % 第二路、第三路类似二是计算均方误差MSEMSE1 mean((x1 - x1_hat).^2); MSE2 mean((x2 - x2_hat).^2); MSE3 mean((x3 - x3_hat).^2); fprintf(三路恢复信号的MSE: %.4e, %.4e, %.4e\n, MSE1, MSE2, MSE3);在20dB信噪比下MSE应该在10的-2甚至-3量级以内。如果MSE偏大大概率是滤波器过渡带把邻路信号漏进来了或者载波频率被fs整除性不好导致频谱泄漏。3.6 FDM的进阶细节滤波器阶数对比与保护间隔的直观演示如果你想要更多直观感受可以做一个对比把第一路和第二路保护间隔从400Hz改成200Hz甚至0Hz然后用同样的滤波器去解调观察串扰会以多大程度影响恢复信号。这时你会发现保护间隔不够的后果不是信号变差一点而是直接把独立信道变成混叠噪声这个实验能让你切身体会到频带规划的重要性。4. TDM完整仿真从帧结构搭建到信号恢复的全程实战4.1 TDM系统的最简单可行模型时分复用的原理在MATLAB里建模比FDM更需要数据思维。FDM本质是模拟域处理而TDM本质是数字域的时间规划与切换。我做TDM仿真时采用一个经典的三路时隙轮转模型三路基带信号仍然用x1、x2、x3同样的源信号但这里为了更贴近采样后传输的实际情况先对每路信号做采样率变换——严格说TDM传输的是采样点不是连续波形。三个时隙循环轮转时隙1发x1的一个采样点时隙2发x2的一个采样点时隙3发x3的一个采样点然后循环。接收端要做的是按照同步的帧时钟把对应时隙的采样点分别送到三路输出再用插值/滤波把离散点恢复成连续波形。简而言之setp 1串并合并step 2接收分离step 3插值恢复。4.2 为什么TDM仿真不能直接交替发一个点理论上交替发一个点就够了但实际上如果每路只取8000个点然后轮流发送总数据率是原来的3倍单信道上就是一个超长序列接收端一帧一个点地拆。这在MATLAB里能实现但代码写起来绕而且让人抓不住重点。更直观、更好理解的实现思路是分块拼接把每路信号按时间切块块内包含若干个采样点然后轮流发送这些数据块。这样接收端分离后的数据块直接拼起来就是原信号完全不用做插值补偿。%% TDM参数 block_size 16; % 每块包含16个采样点 num_blocks floor(N / block_size); % 块数 % 三路信号截成同样长度 x1_tdm x1(1:num_blocks*block_size); x2_tdm x2(1:num_blocks*block_size); x3_tdm x3(1:num_blocks*block_size); tdm_signal []; for k 1:num_blocks idx (k-1)*block_size 1 : k*block_size; % 轮流插入三路数据块 tdm_signal [tdm_signal, x1_tdm(idx), x2_tdm(idx), x3_tdm(idx)]; end这段做的是发送端的复用合并tdm_signal里的结构是——第1个块是x1的第1~16点第2个块是x2的1~16点第3个块是x3的1~16点第4个块是x1的17~32点以此类推。4.3 接收端的时隙解复用与信号重建接收端拿到tdm_signal经过信道传输后最关键的一步是知道每一块的起始位置。这就是帧同步问题收端必须找到第1个块到底是x1还是x2还是x3。在实际系统里这靠帧头、同步码解决在我们的仿真里由于没有相位偏差直接从第1个点开始按块长顺序切就行。%% 接收端解复用 % 模拟信道噪声叠加 rx_tdm awgn(tdm_signal, 30, measured); % 按发送端相同的块结构切分 r1 zeros(1, num_blocks*block_size); r2 zeros(1, num_blocks*block_size); r3 zeros(1, num_blocks*block_size); for k 1:num_blocks base_idx (k-1)*block_size*3; % 每轮3个块共3*block_size个点 r1((k-1)*block_size1 : k*block_size) rx_tdm(base_idx1 : base_idxblock_size); r2((k-1)*block_size1 : k*block_size) rx_tdm(base_idxblock_size1 : base_idx2*block_size); r3((k-1)*block_size1 : k*block_size) rx_tdm(base_idx2*block_size1 : base_idx3*block_size); end这段是TDM的核心。它做的事就是接收端的时隙分配把收到的长序列每三个块一轮循环分别对应到三路输出。4.4 插值恢复连续信号的两种方案对比如果你采了样、传了帧、分离了数据块最后要输出连续波形最简单的方案当然是直接把分离出来的离散点画出来看起来就是一条折线。但如果你想还原出平滑的连续信号需要做插值。MATLAB里插值三种方式对比方式函数/方法精度用途线性插值interp1(t_discrete, r1, t, linear)中等粗略恢复三次样条插值interp1(..., spline)高平滑恢复理想低通重建频域补零 IFFT理论最高等效采样定理重建实测下来在块长16、原信号频率不超过3kHz的情况下线性插值已经够用三次样条更平滑但两者和原信号的MSE差异极小。真正要选哪种取决于你报告里需要展示的深度。如果想让仿真更通信原理推荐使用理想低通重建——就是傅里叶变换后频域补零再反变换这正是采样定理的逆过程。代码是这样的%% 理想低通重建频域补零 M length(r1); % 分离后每路点数 N_upsample M * 4; % 4倍上采样重建出更密的时间点 R1 fft(r1); R1_up [R1(1:M/2), zeros(1, N_upsample-M), R1(M/21:end)]; r1_recon real(ifft(R1_up)) * (N_upsample/M); t_recon linspace(0, t_total, N_upsample);这里原理是离散时间序列的频谱是周期性的频域补零等效于在周期之间插入零频谱分量把它变成更长周期的频谱IFFT之后就能得到更密的时域采样点也就是一次插值。不过我建议你在报告里用线性插值、样条插值、理想重建三种各恢复一次然后画在同一张图上对比这个对比本身就构成了很有说服力的实验数据。4.5 TDM必须注意的同步代价TDM在MATLAB里看起来很简单——就是分块、合并、再分块。但你要记住这一切的前提是接收端和发送端的时钟完全同步。在实际系统中接收端需要从数据流中提取时钟信号如果收发两端采样时钟有微小偏差即使只有千分之一积累一段时间后接收端就会错位一个块。这也是时分复用系统最核心的代价所在。我在给TDM仿真加过时钟偏差比如收端每个块多取0.01个采样点跑完整个信号长度后后半个信号里的三路已经面目全非了。这个实验强烈建议你亲自做一次做完就明白为什么实际TDM系统里帧同步电路那么复杂了。5. 两套系统的对比结论什么场景选哪个做完整套仿真之后我建议你在报告结尾画一张对比表把两套系统的本质差异说透维度FDMTDM资源划分方式频率维度时间维度实现复杂度需要高选择性滤波器复杂度高需要精确时钟同步同步电路复杂抗噪声能力高信噪比下效果好受滤波器滚降影响受采样率和量化影响时钟抖动影响大典型应用广播电视、光波分复用(WDM)电话系统(E1/T1)、移动通信时隙MATLAB建模难度中等核心在滤波器和频谱较简单核心在数据块处理和插值这两套系统的仿真其实是一对很好的对照组FDM让你练习频谱规划和滤波器设计TDM让你练习数据成帧和时钟同步思维。弄懂了这两套后面学OFDM其实就是多载波FDM思想TDM的数字化实现、CDMA就有了具象的基础。6. 仿真中的常见坑与排错日志我把自己和学生们在这个仿真上踩过的坑集中整理一下每条都是血泪教训。6.1 butter函数归一化频率的坑这是第一大坑。butter需要的频率是归一化的范围0~11对应奈奎斯特频率fs/2。如果你直接把实际频率传进去比如cutoff4000fs8000时归一化应该是1但如果你传了3000得到的滤波器实际截止频率是6000Hz完全不是你想要的效果。排查方法画freqz(b,a,1024,fs)看-3dB点在哪个频率。如果和设计预期不符优先检查归一化。6.2 信号叠加后幅度太大导致awgn表现异常FDM三路信号叠加后峰值幅度可能接近3。这种情况下用awgn(fdm_signal, 20, measured)没问题但如果你用awgn(fdm_signal, 20)不指定measured信噪比计算会假设输入信号功率为1导致实际信噪比受信号幅度影响。建议一律用measured参数它先测量信号功率再加噪声。6.3 FDM解调后波形两头有瞬态失真滤波器对信号的起始段和结束段会产生瞬态响应。如果你恢复出来的信号开头几百个点和原信号偏差很大那多半不是滤波器设计错了而是暂态效应。处理办法丢弃前200个点再做MSE计算这样评价才有意义。% 只统计稳态段 start_idx 500; MSE1 mean((x1(start_idx:end) - x1_hat(start_idx:end)).^2);6.4 TDM解复用索引算错TDM代码里最容易出bug的就是索引计算。我的建议是永远先用小规模测试验证索引逻辑比如block_size改成4、num_blocks改成10运行一次把r1(1:10)和x1(1:10)打出来对比确认完全吻合后再跑全尺寸数据。用这招可以节约大量debug时间。7. 我的一些实操建议这个仿真做完我的一个很深的感受是FDM仿真最锻炼的是滤波器直觉什么时候该加阶数、过渡带留多宽、截止频率选哪这些在课堂上听一百遍也不如自己在频谱图上看一遍来得深刻而TDM仿真最锻炼的是数据流思维收发双方的时序关系一旦用代码表达出来教材里那些帧结构图就瞬间活了起来。如果你打算把这个仿真完善成课程设计或者毕设的一部分可以考虑往这几个方向扩展一是把三路信号的载波频率挨得更近用升余弦滚降滤波器来控制码间串扰观察频谱效率的变化二是给TDM加帧同步码机制在接收端自动搜索帧头三是把FDM和TDM组合成混合多址在时间和频率两个维度都划格子那就是往OFDMA的方向走了。最后分享一个调试小技巧做这类通信仿真不要用随机信号——随机信号恢复出来你根本分不清是恢复对了还是在噪声里勉强找出来的。用带明显结构的正弦信号加谐波那种恢复效果好坏一眼就能看出来。等系统完全跑通再换语音或者随机数据也不迟。这个习惯帮我少走了很多弯路。本文还有配套的精品资源点击获取
返回列表