
简介这套MATLAB Simulink通信系统建模与仿真源码包面向通信专业学生、研究人员及需要快速上手Simulink仿真的工程技术人员。内容覆盖信号与系统基础、傅里叶变换与反变换、希尔伯特变换、随机过程分析、离散时间系统、卷积运算以及带通/低通变换等核心主题19个可直接运行的.m脚本分主题组织压缩包整体仅9KB轻量易用便于对照源码理解抽象理论、频谱变化与系统时频特性。脚本从离散运算、线性系统分析逐步过渡到随机信号处理结构清楚模块划分明确可配合Simulink模型进行参数调整与二次开发其中既包含基础验证示例也保留了便于扩展的仿真片段适合作为课程设计、期末复习或科研初探的代码起点。目前已有237人学习下载是快速掌握通信系统建模思路、信号分析方法和Simulink编程实践的一份实用参考资料。1. 从文件命名规律看透这套通信信号分析源码翻开源码包里的 m 文件命名规律其实已经把实验主线写在了文件名上lisan_1.m 起头random_process_19.m 收尾中间按离散运算、卷积、傅里叶变换、希尔伯特变换、带通低通、随机过程这条信号处理链路展开恰好覆盖 MATLAB Simulink 通信系统建模与仿真里最常碰到的几类计算。对正在啃通信原理的学生来说每个脚本都是独立可跑的改两个参数就能看到波形、频谱和统计特性的变化对已经在搭 Simulink 模型做系统仿真的工程师来说这些脚本的价值在于当参照物——模块参数填得对不对、算法实现有没有偏差跑一遍对应的 m 函数就知道了。下面按文件编号顺序拆解每个脚本的功能、关键参数和常见误用并把脚本逻辑映射到 Simulink 的模块实现上。2. 离散信号与系统从采样、卷积到 filter 的完整链路2.1 采样定理如何落地lisan_1.m 里的参数选择lisan_1.m 是整个资源包里编号最小的脚本功能是把连续信号离散化这是通信系统建模的第一步。Simulink 里的 Sine Wave 模块也要经过采样和量化才能送进数字信号处理链路所以先把采样参数吃透后面所有频域分析才有基础。% lisan_1.m 风格连续正弦信号采样为离散序列 fs 1000; % 采样率 1000 Hz对应奈奎斯特频率 500 Hz ts 1/fs; % 采样间隔 t 0:ts:0.05; % 时间轴 0~50 ms共 51 个点 f0 50; % 信号频率 50 Hz远低于 fs/2 x sin(2*pi*f0*t); stem(t, x, filled); % 离散序列显示 xlabel(时间/s); ylabel(幅度);采样率 fs 决定奈奎斯特频率 fs/2也就是这段代码能无混叠表示的最高频率。t 用 0:ts:0.05 生成而不是 linspace(0,0.05,51)是因为前者直接体现采样间隔修改 fs 后点数自动变化便于观察采样密度对波形的影响。把 f0 改成 600 Hz 试试恢复出来的序列会变成一个 400 Hz 的假信号这就是混叠现象也是采样定理要求 fs 大于两倍信号最高频率的根本原因。实际做 Simulink 仿真时Sine Wave 模块的 Sample time 参数填的就是这里 ts 的倒数。2.2 线性卷积与圆周卷积lisanyunsuan_2.m 与 lisanConv_3.mlisanyunsuan_2.m 和 lisanConv_3.m 放在一起分别对应离散运算和卷积运算两个主题说明作者在设计实验时把卷积当作离散运算的进阶。卷积在通信系统里是滤波的本质匹配滤波器、相关器、信道均衡全都建立在卷积运算之上。% 线性卷积的两种实现lisanyunsuan_2.m 与 lisanConv_3.m x [1 2 3 4]; % 输入序列长度 Nx 4 h [1 1 1]; % 系统冲激响应长度 Nh 3 y_conv conv(x, h) % 直接调用输出长度 NxNh-1 6 % 手动实现便于理解卷积的移位相乘过程 Nx length(x); Nh length(h); y_manual zeros(1, Nx Nh - 1); for n 1:Nx Nh - 1 for k 1:Nx idx n - k 1; if idx 1 idx Nh y_manual(n) y_manual(n) x(k) * h(idx); end end end直接调用 conv 是最常用做法两层循环的写法纯粹为了看清每个输出点是怎么累加出来的。工程上推荐 conv 或 convmtx但实验里花十分钟手写一遍循环对理解卷积和、线性卷积与圆周卷积的差异非常有帮助。注意结果长度为 NxNh-1这是线性卷积区别于圆周卷积最直观的特征。卷积类型输出长度MATLAB 函数典型通信场景线性卷积NxNh-1convFIR 滤波、时域均衡圆周卷积max(Nx,Nh)手动循环取模OFDM 循环前缀、块处理圆周卷积在 OFDM 系统里特别关键循环前缀的本质就是让线性卷积退化为圆周卷积从而用 FFT 完成频域均衡。如果这两段脚本能跑明白后面理解 Simulink 里的 Convolutional Encoder、FIR Filter 模块时就不容易踩维度不对的坑。2.3 用 filter 求冲激响应lisan_time_system_4.m / lisan_time_system_5.mlisan_time_system_4.m 和 lisan_time_system_5.m 是连续编号的两个脚本分别处理离散时间系统的冲激响应和阶跃响应。两个脚本共用同一套系统系数只是激励不同这是信号与系统课程里最经典的一组对照实验。% lisan_time_system_4.m 风格一阶 IIR 系统的时域响应 b 1; % 输入系数对应 x[n] 的权重 a [1 -0.8]; % 输出系数对应 y[n] - 0.8*y[n-1] x[n] n 0:20; x_imp (n 0); % 单位冲激序列 h filter(b, a, x_imp); % 冲激响应 x_step ones(1, 21); s filter(b, a, x_step); % 阶跃响应 subplot(2,1,1); stem(n, h); subplot(2,1,2); stem(n, s);filter 的约束是 a(1) 必须等于 1否则系统无法写成因果差分方程形式。这里差分方程是 y[n] - 0.8y[n-1] x[n]极点位于 0.8系统稳定且冲激响应按 0.8^n 衰减。把 a 改成 [1 -1.2] 系统就发散冲激响应幅度一路增大这是判断 IIR 系统稳定性的最直接实验。Simulink 里 Discrete Transfer Fcn 模块的 Denominator coefficients 参数直接填 [1 -0.8]Numerator coefficients 填 [1]与这里的 b、a 完全对应脚本跑通了模块参数就不会填错。3. 傅里叶变换脚本族FFT 点、频率分辨率与频谱泄漏3.1 FFT 幅值谱的归一化Fourier_6.m 到 Fourier_10.m资源包里编号 6 到 14 的脚本全部围绕傅里叶变换展开傅里叶级数、离散傅里叶变换、快速傅里叶变换、逆变换各占一个文件。这批脚本的核心考点只有一个FFT 结果怎么归一化才能读出真实幅值。% 频谱分析脚本Fourier_6.m 系列的核心逻辑 fs 1000; % 采样率 1000 Hz t 0:1/fs:1-1/fs; % 时长 1 秒正好 1000 点 x sin(2*pi*50*t) 0.5*sin(2*pi*200*t); N 1024; % FFT 点数可取 512/1024/2048 X fft(x, N); % 补零到 N 点 f (0:N-1) * fs / N; % 频点坐标单位 Hz mag abs(X) / N; % 归一化幅值谱 stem(f(1:N/2), mag(1:N/2)); % 单边谱只看正频率abs(X)/N 是幅值归一化的关键。50 Hz 分量的幅值读出来应接近 1200 Hz 分量接近 0.5因为 200 Hz 处幅度是 0.5。忘记除 N 是最常见的错误读出的幅值会放大 N 倍和原始信号幅度对不上。用 stem 画离散谱线而不是 plot 连线能直观看到频点间隔。FFT 点数 N频率分辨率 Δf fs/N可分辨的最小频率间隔5121.953 Hz两个正弦间隔小于该值时无法区分10240.977 Hz常规频谱分析的起点20480.488 Hz需要分辨 0.5 Hz 级频率时选用频率分辨率由 fs 和 N 共同决定。N 越大谱线越密但补零只能让频谱更平滑不能真正提高分辨率真正的分辨率提升要靠延长采样时长。资源包里 Fourier_6.m 到 Fourier_10.m 的差别主要在信号构造和 N 的选取上把上表三个 N 值各跑一遍频率分辨率对频谱形态的影响会非常直观。3.2 逆傅里叶变换与重构误差iFourier_7.miFourier_7.m 紧跟在傅里叶变换脚本后面承担逆变换验证任务。通信系统里频域滤波、频域均衡都需要经过 IFFT 回到时域重构误差是衡量频域处理是否正确的重要指标。% iFourier_7.m 风格频域处理后重构时域信号 X fft(x, N); Xc X; Xc(abs(f-200) 5) 0; % 把 200 Hz 附近频谱置零 x_recon ifft(Xc, N); % 逆变换回时域 err max(abs(x_recon(1:length(x)) - x)); % 重构最大误差频域置零后重构的 x_recon 与原始 x 的差主要来自两方面一是被滤掉的 200 Hz 分量确实消失了这是预期内的误差二是频谱截断产生的吉布斯效应信号在跳变处出现过冲。err 用 max 取最大绝对值而不是 mean 取平均是为了捕捉最坏情况。OFDM 系统里 IFFT 输出会加循环前缀再发送接收端 FFT 前要去掉前缀这个操作本质就是对重构精度的控制——前缀长度不够重构误差就会落在数据符号上。3.3 频谱泄漏与窗函数频谱泄漏是傅里叶分析里最容易在实际工程中翻车的点。正弦信号频率不落在 FFT 频点整数倍位置时能量会扩散到相邻频点看起来像多了一堆假频率分量。资源包里的 Fourier_8.m 到 Fourier_14.m 里有不少篇幅在处理这个问题。% 频谱泄漏对比整周期截断 vs 非整周期截断 N 128; fs 64; t (0:N-1) / fs; f1 10; % 128 个点里正好 20 个整周期 f2 10.4; % 20.8 个周期非整数必然泄漏 x1 sin(2*pi*f1*t); x2 sin(2*pi*f2*t); win hann(N, periodic); % 周期汉宁窗注意转置对齐维度 subplot(2,1,1); plot(fs/N*(0:N/2-1), abs(fft(x1, N)/N*2)); subplot(2,1,2); plot(fs/N*(0:N/2-1), abs(fft(x2 .* win, N)/N*2));f1 对应 20 个整周期FFT 谱线干净f2 对应 20.8 个周期频谱出现明显裙边。加 hann 窗后主瓣变宽但旁瓣大幅压低泄漏能量被限制在主瓣附近。参数 hann(N, periodic) 里 periodic 选项生成周期窗适合做频谱分析symmetric 选项适合做 FIR 滤波器设计两者不能混用。实际做 Simulink 频谱观测时Spectrum Analyzer 模块内部默认加了窗函数所以模块显示的频谱和直接用 fft 算出来的形状会有差异这是正常的不是 bug。4. 希尔伯特变换与带通/低通设计脚本到 Simulink 模块的映射4.1 解析信号与瞬时包络Hilbert_15.mHilbert_15.m 对应希尔伯特变换这是通信系统里构造解析信号、提取瞬时包络和瞬时频率的标准工具。QAM 解调、调频解调、雷达信号处理都会用到理解这份脚本等于掌握了 IQ 信号数学原理的实践版本。% Hilbert_15.m 风格由实信号构造解析信号并提取包络 fs 1000; t 0:1/fs:0.1; f0 50; x cos(2*pi*f0*t); % 实信号 z hilbert(x); % 解析信号 z x j*xh inst_amp abs(z); % 瞬时包络理想情况下恒为 1 inst_phase unwrap(angle(z)); inst_freq fs/(2*pi) * diff(inst_phase); % 瞬时频率 mean(inst_freq) % 应接近 50 Hzhilbert 函数在 MATLAB 里直接输入实信号返回解析信号 zz 的实部是原信号虚部是原信号的 90 度相移版本。abs(z) 得到瞬时包络cos 信号的理论包络是常数 1unwrap 加 angle 得到连续相位再对相位求差分得到瞬时频率均值应接近 50 Hz。注意 inst_freq 首尾几个点受边界效应影响偏差较大统计时应剔除边缘值。改一个参数就能变成 AM 解调实验令 x (1 0.5cos(2pi5t)) .* cos(2pif0t)abs(z) 会恢复出 1 0.5cos(2pi5*t) 的包络幅度调制解调的核心原理就在这一行代码里。4.2 滤波器系数怎么给daitong_ditong_16.mdaitong_ditong_16.m 的主题从文件名就能看出来带通和低通。通信系统里滤波器无处不在成型滤波、匹配滤波、信道选择都要靠它但 Simulink 里滤波器模块的参数往往把初学者卡住问题出在归一化频率上。% daitong_ditong_16.m 风格fir1 设计低通与带通滤波器 fs 8000; f_low 3400 / (fs/2); % 低通截止频率归一化 f_bp [300 3400] / (fs/2); % 带通通带归一化 b_lp fir1(64, f_low, low); b_bp fir1(64, f_bp, bandpass); freqz(b_lp, 1, 1024, fs); % 滤波器频率响应fir1 的截止频率必须归一化到奈奎斯特频率 fs/2所以 3400 Hz 要写成 3400/(fs/2) 而不是 3400/fs这是滤波器设计里最常见的低级错误。阶数 64 对应滤波器长度为 65这个值决定过渡带宽度阶数越大过渡带越窄但计算量越大同时滤波器延迟也越大。freqz(b, a, N, fs) 的第四个参数传 fs 后横轴直接显示 Hz方便和实际频率对照。Simulink 的 Digital Filter Design 模块支持直接导入这些系数在模块参数里选择 Filter coefficients 来自 workspace把 b_lp 填进 Numerator 即可。4.3 脚本函数与 Simulink 模块的对应关系把脚本吃透之后再搭 Simulink 模型思路会清晰很多。通信系统建模与仿真里的 Simulink 模块本质上是这些数学函数的图形化封装理解底层脚本能避免参数填错的坑。MATLAB 脚本函数Simulink 对应模块参数对应关系fft / ifftSpectrum Analyzer、FFTDSP System ToolboxSpectrum Analyzer 直接输出单边功率谱免去手动归一化filterDiscrete Transfer Fcn、Digital Filter Designb、a 对应 Numerator、Denominator 系数hilbertHilbert TransformCommunications Toolbox输出解析信号的虚部abs / angleComplex to Magnitude-Angle解调端 IQ 分离后的幅相提取randnAWGN Channel噪声功率由 SNR 参数自动计算如果需要在 Simulink 里调用这些脚本的算法逻辑MATLAB Function 块可以做到但要注意代码生成的限制。function Y fft_mag(X) coder.extrinsic(fft); N 1024; F fft(X, N); Y abs(F(1:N/2)); endcoder.extrinsic 声明让 fft 在仿真阶段通过 MATLAB 解释器执行模型能跑通但生成 C 代码时这个调用会被替换成零输出也就是 simulink 模型 c 代码生成流程里 C Function 外部调用不可行的地方。真正要生成嵌入式代码应该用 DSP System Toolbox 的 FFT 模块或者在 MATLAB Function 块里手写基 2 FFT 循环。这点对做嵌入式部署的工程师尤其重要仿真能跑和代码生成能跑是两回事。5. 随机过程脚本与信噪比校准把噪声功率算准再进信道5.1 高斯白噪声的统计检验random_process_17.m 到 random_process_19.mrandom_process_17.m、random_process_18.m、random_process_19.m 三个脚本连续编号主题分别是随机过程的基本统计量、自相关函数和功率谱估计。通信系统性能评估的核心指标 BER 全都建立在噪声模型之上这一组脚本是第 4 章滤波器脚本的进阶也是把噪声从理论公式变成可验证序列的关键。% random_process_17.m 风格噪声序列的统计特性验证 rng(0); % 固定随机种子保证结果可复现 N 10000; x randn(1, N); % 标准高斯白噪声 mu mean(x) % 样本均值接近 0 p mean(x.^2) % 平均功率接近 1 ac xcorr(x, 100, biased); % 自相关函数0 延迟处应最大rng(0) 固定随机种子每次运行得到相同的噪声序列这是仿真可复现的基础。mean(x.^2) 是噪声功率的直接估计标准 randn 序列的功率理论值为 1实测值会在 1 附近波动。xcorr 的 biased 选项输出有偏自相关估计峰值出现在零延迟处数值接近功率值。这三个统计量验证通过说明噪声序列可以放心用于后续的信噪比实验。5.2 按目标 SNR 生成噪声并接入 AWGN Channel把噪声从脚本接进 Simulink 模型前建议先做一步校准这是我在实际调试里养成的习惯直接给 AWGN Channel 模块填 SNR 数值模块会根据输入信号功率实时计算噪声功率但信号经过滤波或其他处理后功率会变化模块内部计算的结果和理论值可能不一致。先标定噪声功率再进信道星座图和眼图才有对比的基准。% 按目标信噪比生成噪声并验证实测值 signal_power 1; % 信号归一化功率 SNRdB 10; % 目标信噪比 10 dB noise_power signal_power / (10^(SNRdB/10)); noise sqrt(noise_power) * randn(1, N); meas_snr 10*log10(signal_power / mean(noise.^2)); % 应接近 10 dB原理是信噪比定义 SNR Ps/Pn已知信号功率和目标信噪比后反推噪声功率再用 sqrt(noise_power) 缩放 randn 序列。最后一行验证代码能立即看出校准是否准确如果 meas_snr 偏离目标值超过 0.2 dB说明序列长度不够增大 N 即可。在 Simulink 模型里用 Signal From Workspace 模块把 noise 变量导入Variable name 填 noiseSample time 填 1/fs输出接到加法器与信号相加这样加噪后的信号送进 AWGN Channel 模块时信道内部会按导入的信号功率重新计算噪声你可以在示波器上直接对比加噪前后的眼图张开度。先用脚本把噪声功率算准再进 Simulink 联调比在模块参数里反复试 SNR 数值要快得多。本文还有配套的精品资源点击获取