简介:信号与系统课程设计是电子信息技术的重要实践环节,围绕Matlab/Simulink仿真展开,文档面向电子信息类专业学生,帮助掌握信号处理与线性系统分析的仿真建模方法。文中利用Simulink的FFT模块与频谱分析工具对信号进行快速傅里叶变换,搭建FIR滤波器完成数字滤波;随后分别针对离散系统和连续系统,通过传递函数模块、积分模块等建立仿真模型,分析单位脉冲响应、系统响应及稳定性。采样定理部分则演示了信号采样与恢复的完整过程,直观展示采样频率对重建质量的影响。资源为单份doc文档,包含原理说明、模型搭建步骤和结果截图,文件大小约458KB。目前已有114人学习,适合课程设计参考、实验复现或考研复习使用,能帮助读者将理论转化为仿真实践能力。
1. 从课程设计到自主仿真:为什么我推荐用Simulink做信号与线性系统仿真
年初帮几个学弟学妹把“信号与系统课程设计”的Simulink仿真部分从头到尾捋了一遍,发现一个共性现象:教材上的拉普拉斯变换、卷积积分、傅里叶分析,大家都能写出表达式,但一到Matlab里建模就懵了——不会选模块、不会配参数、看不懂Scope波形。
这个课程设计的核心目标,是用Simulink把《信号与系统》里那些抽象的数学运算“跑起来”。它不是一个纯理论文档,而是一个“看得见”的验证过程:比如你设计了一个RC低通滤波器,理论截止频率算出来是1kHz,那就在Simulink里搭一个一阶低通模块,输入阶跃信号,看输出响应速度是不是符合时间常数τ=RC的规律;再比如给你一个系统函数H(s),通过Simulink的Zero-Pole模块观察单位冲激响应,对照手算结果是否一致。
这篇文章不是教你抄一份报告,而是把完整的建模思路、核心模块选型、参数设置逻辑、踩坑记录全部拆开讲一遍。无论你是刚接触Matlab的新手,还是已经会用基本模块但想优化仿真结构的进阶玩家,本文的思路和代码块都能直接抄作业。
这篇博文适合谁?正在做信号与系统课程设计的学生、准备考研复试综合面试的考生、以及工作中需要快速验证线性系统特性的工程师。阅读前提只需要“会画系统框图、知道传递函数长什么样”,Simulink操作层面我从零讲起。
2. 建模之前:一次“信号与系统”课程设计的完整需求拆解
2.1 常见课设要求有哪些隐藏考点
很多课设任务书写得模糊,比如“基于Simulink对LTI系统进行仿真”。但根据我看到的十几份不同学校的任务书,拆开来看几乎都能归纳成以下五类:
- 连续时间信号的产生与运算(正弦、阶跃、冲激、指数衰减、信号的加减乘)
- LTI系统的时域响应分析(零输入响应、零状态响应、单位冲激响应、单位阶跃响应)
- 卷积积分与系统的图形化验证(常见做法是直接把两个信号序列丢进卷积模块)
- 系统函数与频域分析(由微分方程写H(s),用Bode图观察幅频特性、相频特性)
- 采样与恢复(模拟信号经过理想采样、零阶保持器重构,观察频谱混叠)
针对上述每一类需求,Simulink里都有对应的模块,但很多同学的问题就出在“不知道模块叫什么名字”。其实所有模块都藏在Simulink库浏览器里,加上筛选功能,两分钟就能定位。
2.2 Simulink环境准备与基础模块清单
如果你的Matlab版本是R2018b以后,打开方式都一样:命令行输入simulink回车,或者从主页栏直接进入Simulink库浏览器。这里我建议直接进入库浏览器界面,而不是新建空白模型——因为课程设计第一步是拖模块,你需要先看到全部模块在哪。
我个人的操作习惯是:先把以下模块添加到收藏夹,之后的搭建速度会快很多。
| 模块名称 | 模块路径(按版本略有差异) | 适用场景 |
|---|---|---|
| Sine Wave | Simulink/Sources | 正弦信号产生 |
| Step | Simulink/Sources | 阶跃信号输入 |
| Pulse Generator | Simulink/Sources | 脉冲序列(采样恢复常用) |
| Scope | Simulink/Sinks | 波形观察 |
| Transfer Fcn | Simulink/Continuous | 传递函数建模 |
| Zero-Pole | Simulink/Continuous | 零极点建模 |
| Integrator | Simulink/Continuous | 积分器(画系统框图用) |
| Add/Sum | Simulink/Math Operations | 信号加减 |
| Gain | Simulink/Math Operations | 增益系数 |
| Product/Divide | Simulink/Math Operations | 信号乘除 |
| Conv(若存在) | 需额外安装DSP System Toolbox | 卷积计算 |
| State-Space | Simulink/Continuous | 状态空间模型 |
新手最大的一个误区是:拿到一个系统,第一反应是去找“全能的模块”。其实Simulink建模的核心就一句话——“用模块连接的方式,复现系统框图中信号的流动过程”。比如教材里画了RLC电路的系统框图:输入电压→增益/积分→反馈→输出。那么在Simulink里你就直接拖一个Step、一个Sum、几个Gain、一个Integrator连接起来,根本不需要去找“RLC专用模块”——除非你想搭自带的电力电子模型。
2.3 Simulink中“模块封装”与课设报告的关系
课程设计报告一般要求体现建模过程。很多同学截图时只截一个Scope波形,显得很单薄。我的建议是:在Simulink模型中,把同一系统的不同激励输入分别建立Enabled Subsystem或Subsystem封装,这样截图报告时能同时展示“阶跃响应子系统”“冲激响应子系统”“正弦稳态子系统”,结构清晰,评分观感会好很多。
关于封装技术,你只需要掌握三步:选中要封装的一组模块→右键“Create Subsystem from Selection”→双击这个新建子系统→选“Edit Mask”设置参数。如果课设要求传递可变参数(比如说需要修改增益K),那就在Mask里添加一个Edit参数,关联到子系统内部Gain模块的Gain值。这个技巧在答辩演示时特别出彩,因为评审老师常说“那你能改个K值再看效果吗”。
3. 核心环节一:典型信号发生器与LTI系统建模实操
3.1 用Simulink复现“单位冲激信号”的正确姿势
教材上单位冲激信号δ(t)是无穷窄、无穷高的抽象概念,但Simulink里不可能直接造出一个“无穷”。工程做法是:用Step模块或者Pulse Generator产生一个“极窄脉冲”,脉冲宽度远小于系统最小时间常数,就近似为冲激。
实际操作:从Sources库拖入Pulse Generator,双击设置参数:Pulse type选Time based,Period设为100秒,Pulse Width设为0.001(% of Period),即脉宽0.001秒。再接一个Gain模块(增益设1,纯透传),再接Scope。如果你将这个窄脉冲输入到一个一阶低通系统(Transfer Fcn:1/(s+1)),观察到的输出就是从零快速上升后指数衰减的波形,这正是理论上的单位冲激响应h(t)=e^{-t}u(t)。
注意:若Period太短,脉冲会变成周期方波,输出会呈现连续振荡,不是你要的单发冲激响应。建议Period至少是系统时长的100倍。
3.2 传递函数与零极点模型的选择逻辑
“信号与线性系统”仿真中,最核心的就是把系统微分方程变成Simulink能识别的形式。能识别的原因一大堆,但核心是:Simulink的Transfer Fcn模块直接用拉普拉斯域complex frequency s的表达式即可。
比如教材常见二阶系统微分方程: [ y''(t)+2\omega_n \zeta y'(t)+\omega_n^2 y(t)=\omega_n^2 u(t) ] 对应传递函数: [ H(s)=\frac{\omega_n^2}{s^2+2\omega_n \zeta s+\omega_n^2} ]
在Simulink中添加Transfer Fcn模块,双击设置Numerator coefficients为[wn^2],Denominator coefficients为[1 2*zeta*wn wn^2]。但注意这里有一个坑:模块的参数不能直接写符号,必须填数值。因此我一般先用Matlab脚本定义变量,再回到模型参数里填wn^2的数值。
如果你有Control System Toolbox,也可以直接在Matlab命令行创建系统:
wn = 2*pi*10; % 10 Hz固有频率 zeta = 0.5; sys = tf(wn^2, [1 2*zeta*wn wn^2]);然后在Simulink中使用From Workspace模块或者直接把sys变量通过Model Workspace导入,实现参数联动。这个方法适合做参数扫频的进阶需求。
3.3 零输入响应与零状态响应的拆分仿真
有一类课设题非常典型:“已知某LTI系统输入为阶跃信号,初始条件不为零,求零输入响应与零状态响应”。很多同学用一张Transfer Fcn模型直接仿真,结果输出只有全响应,拆分不出来。
我推荐的拆法有两种。
方法一:基于叠加定理。将原因变量(输入信号和初始条件)分开建模。只保留输入信号时,初始条件置零,得到零状态响应;只保留初始条件时,输入信号设为零,得到零输入响应。Simulink中怎么实现初始条件?Continuous库里的Transfer Fcn虽然有初始状态参数,但用起来不直观。我分享一个更顺手的做法:使用State-Space模块,初始条件直接填向量,比如x0 = [1; 0]。
方法二:直接手动搭建系统框图。以RLC二阶电路为例,状态变量选电容电压v_c和电感电流i_L。Simulink中拖Integrator模块,初始条件(Initial condition)分别设置为0和某个初始电流值。这样你就可以任意开关输入信号,实现两种响应的解耦观测。
我强烈建议在报告里把这两种响应画在同一个Scope中,标注“零输入响应”“零状态响应”“全响应=二者之和”,这是信号与系统课程设计的一个高频加分点。
3.4 Simulink一阶滤波模块的快速上手
热搜词里有个“simulink一阶滤波模块”,这里一并讲透。Simulink的Continuous库里有一个模块叫First-Order Filter(有的版本位于Simulink Extras/Additional Linear中,或DSP System Toolbox里)。它内部就是一个一阶低通滤波器,参数有两个:Time constant τ(时间常数)和Initial condition。
举个例子:输入一个包含50Hz和500Hz两个频率分量的信号,用First-Order Filter设置截止频率约100Hz(即τ = 1/(2pi100)),输出就只保留50Hz分量。实操步骤:
- 用Signal Editor或两个Sine Wave叠加生成混合信号;
- 拖入First-Order Filter,设置Time constant = 0.00159(约100Hz);
- 连接Scope观察滤波前后的频谱,可借助Spectrum Analyzer(DSP System Toolbox)查看。
对比最直观的,是你在Scope里接一个Fourier模块或直接再拉一条原始信号线,同图对比。滤波后波形平滑、高频毛刺消失,文字描述和波形图像就能直接搬到报告里。
4. 核心环节二:从卷积到频谱的仿真可视化解构
4.1 卷积积分为什么在Simulink里能干“私家活”
卷积是信号与系统的灵魂操作。但Simulink基础库没有一个叫“卷积”的模块(除非装了DSP System Toolbox)。常规课设做法是:在Matlab命令行生成两个信号序列,用conv函数算卷积,再用plot绘图。这当然可行,但如果你想把卷积过程做进Simulink仿真链路里,有两条路:
- 使用MATLAB Function块,写入
y = conv(u, h),输入两个信号,输出卷积序列。注意:输入信号长度和输出长度会变化,需要适配。 - 使用DSP System Toolbox中的Convolution模块,直接连接两个离散时间序列信号。
我个人更推荐第二条路:拖一个“Discrete Convolution”模块(路径:DSP System Toolbox / Signal Operations),然后给两个信号源设置合理的采样时间。课程设计测试用例建议用矩形脉冲与自身卷积,理论结果是一个三角波,仿真结果若是平滑三角波,说明模型搭建正确。
4.2 拉普拉斯变换的可视化验证:极点与零点的动态响应
热搜词中还有“信号与系统 拉普拉斯变换”,这里也补一个仿真思路。拉普拉斯变换的核心是用复数s = σ + jω描述系统特征,Simulink中不需要直接做拉式变换,而是通过搭建一个反馈系统,观察不同极点位置对暂态响应的影响。
举个例子,设计一个具有极点s = -1 + 2j和s = -1 - 2j的二阶系统: [ H(s)=\frac{1}{(s+1)^2+4} ] 用Zero-Pole模块设置Zeros为空、Poles为[-1+2i, -1-2i]、Gain为1。输入单位阶跃,Scope看到的输出就是衰减振荡曲线,振荡频率接近2rad/s。若将极点往右移,比如s=-0.2±2j,振荡衰减更慢,波形包络下降更缓。
利用这个思路,你可以在课设报告里做“极点位置影响对比”表格:
| 极点实部 | 预期行为 | 仿真观察 |
|---|---|---|
| -1 | 衰减振荡,包络e^{-t} | 2~3个周期后基本消失 |
| -0.2 | 慢衰减振荡,包络e^{-0.2t} | 振荡持续10秒以上 |
| 0 | 等幅振荡(临界稳定) | 输出等幅正弦 |
| +0.2 | 发散振荡 | 波形迅速冲顶 |
4.3 频域分析的“三板斧”:Bode图、频谱分析、滤波器频率响应
信号与线性系统仿真的高频终点是频域。Simulink里可以直接用Linear Analysis工具(在App标签页中),也可以简单地在Scope前加入“Spectrum Analyzer”,实时查看信号频谱。这里我给出一套频域分析的实操路径:
- 搭建被测系统——一个滤波电路或传递函数模块;
- 输入选用Chirp信号(频率随时间线性扫描),模块位于Sources库;
- 在输出接Spectrum Analyzer或Array Plot,观察输出幅值随频率的变化;
- 这个“Chirp测试”的结果就是系统的幅频特性曲线,和理论Bode图对比,误差通常小于5%。
如果你想严谨地截图“Bode图”到课设报告,直接在Matlab命令行输入:
sys = tf([1], [1 0.5 1]); % 示例系统 bode(sys); grid on;这样生成的图分辨率高,格式干净,比用Simulink再调参更省事。课设报告中可以放一张“理论Bode图”和一张“Simulink Scope实测幅频曲线”,对比展示,逻辑闭环。
5. 完整实操:一个“信号与线性系统课设”从建模到成文的全流程
5.1 搭建全过程分步记录
前面理论讲了不少,现在我把一个典型课设的完整操作步骤串起来,你可以照着一步步做。
Step 1:建立模型文件。打开Matlab,新建Simulink空白模型,取名signal_system_design.slx。
Step 2:创建输入信号子系统。拖入一个Sine Wave模块,设置Amplitude=1,Frequency=2pi2(即2Hz),Phase=0。再拖一个Step模块,设置Step time=0,Initial value=0,Final value=1。用一个Mux将它们送入后续系统。
Step 3:构建LTI系统。拖入Transfer Fcn模块,以二阶系统为例:Numerator =[4],Denominator =[1 1 4]。这个系统固有频率为2rad/s,阻尼比0.25,会产生明显振荡。
Step 4:设置Scope显示。拖入两个Scope,一个接输入信号,一个接系统输出,另一个连接输出后再接一个Derivative(求导)模块,用于观察响应速度的变化率。
Step 5:仿真参数。设置Stop Time=10s,Solver选择ode45(变步长,适合连续系统)。勾选“Limit data points to last”以防数据量太大导致Scope卡顿。
Step 6:运行仿真。点击Run,结束后双击Scope查看波形。如果报错“Input port contains NaN”,通常是某个模块增益参数为Inf或除零,回查Gain模块参数。
重复上述过程,把输入分别换为Pulse Generator(窄脉冲)、Chirp信号、混合正弦信号,即可生成冲激响应、扫频响应、叠加信号响应三张核心波形图。
5.2 常用参数计算:别让模块参数乱填
我注意很多同学在Transfer Fcn里填分子分母时,只是照着课本抄,一旦需要自己设计系统就手忙脚乱。这里补充一套从具体RC电路到传递函数参数的笔算法。
假设有电路:输入电压u(t),输出电容电压y(t),R=1kΩ,C=1μF。则传递函数: [ H(s)=\frac{1}{RCs+1} ] 代入数值RC=0.001s,所以Numerator =[1],Denominator =[0.001 1]。
如果课设要求设计一个截止频率200Hz的低通滤波器,那么: [ \tau = \frac{1}{2\pi \times 200} \approx 0.0007958s ] 对应模块参数Denominator填[0.0007958 1]。这个换算过程必须写进报告“参数设计”章节。
5.3 仿真结果与理论值的对照分析
一张漂亮的课设报告图,除了波形,还应该有“理论值 vs 仿真值”的表格。
| 系统参数 | 理论值 | 仿真测量值 | 相对误差 |
|---|---|---|---|
| 峰值时间(多欠阻尼) | 1.57s(按公式π/ω_d) | 1.61s | 2.5% |
| 超调量M_p | 44.4% | 43.8% | 1.4% |
| 稳态误差(阶跃) | 0 | 0.017 | 由数值积分误差造成 |
怎么在Scope上读取峰值时间?优先使用Cursor Measurements,在Scope右上角的“Settings→Measurements”里勾选“Cursor Measurements”,拖动游标到峰值处即可读取。这个方法读取的数据客观,报告截图能直接把数值和波形一并呈现。
6. 常见报错与调试技巧:我在课设现场踩过的坑
6.1 一个最容易混淆的参数:Solver类型与步长
Simulink模型跑出来波形毛刺、锯齿严重,90%是因为Solver设置问题。连续系统应该选变步长(Variable-Step)求解器,如ode45;离散系统选离散求解器(discrete)且步长固定。
有几个“血泪教训”值得拿出来讲:
- 如果只是把Sine Wave和Scope连起来做显示,仿真结果显示波形显示完整的正弦波,步长过大导致严重折线,此时减小“Max step size”(如设为0.001)即可。
- 如果模型中有代数环报警,不要慌,先看是否有直接连接不经过任何动态模块的回路,解决办法是加入一个Memory模块破环。
- 如果Scope没有输出,双击运行后发现一片空白,多半是仿真时间过快已结束,需要将“Stop Time”设大,或者点“Run”后立即停止并查看“Data Inspector”。
6.2 Transfer Fcn参数“1e-5”为什么报错
另一个高频报错是“Denominator coefficients must be a row vector”。这不是你近义词写错,而是分子分母多项式缺项了。比如你要建模H(s)=5/(s^2+3),分母要写成[1 0 3],务必把s项系数0写进去。这个小坑导致很多学生卡了一个小时,我就是其中之一。
6.3 如何让报告截图更“答辩感”
到了写课程设计报告交差阶段,我建议不止截波形图,用“仿真模型截图+Scope波形图+参数设置界面截图”三件套。参数设置界面截图意味着你要为关键模块专门打开一次面板截屏,这样能直观证明你“真的配置过参数”。
还有一个细节:Scope的背景默认是黑色,报告打印时黑底白线废墨。所以在完成仿真截图前,在Scope的“Style”属性里把背景换成白色,线条颜色选蓝色或黑色,打印清晰多了。
6.4 快速排查“仿真结果与手算对不上”的三种思路
如果你仿真结果和手算不一致,别急着怀疑Simulink,先按以下顺序排查:
- 符号变量与单位:数值代入是否正确,例如ω_n=2πf还是f本身,这个错误能造成6倍以上偏差。
- 初始条件:Transfer Fcn里Initial states是否默认为0?有的系统手算零输入响应时假设初始条件不为零,仿真却置零,自然不对。
- 激励时间:Step模块Step time设成1s,系统响应前1s完全为零,与理论从0时刻激励不符。
这三步能解决我见过80%的对不上的问题,剩下20%大多是物理参数换算错误,回去静下心来重新读一遍微分方程即可。
最后再分享一个小体验
我从大学第一次接触Matlab Simulink到现在,最大的体会是:这类“信号与系统课程设计”仿真最大的价值不在于“跑出一个和课本一样的图”,而在于把数学符号转化为“可交互的系统结构”。当你亲手把一个二阶系统的极点拖到虚轴右侧,波形从等幅衰减变成发散振荡时,你对“极点位置决定稳定性”这句话的记忆,会比背一百遍教材都要深刻。
如果你正在为课设头大,照着我上面的模块选型、参数设置和排查思路一步步来,一个下午基本能把核心波形跑齐。后面你还可以继续扩展:把连续系统换成离散系统、加入噪声干扰、用App Designer做一个简化交互界面——每一步扩展都会让这份课设从“合格”走向“优秀”。
本文还有配套的精品资源,点击获取