简介面向广东工业大学信息工程学院电子信息类专业学生的《信号与系统》实验报告适合课程实验、MATLAB仿真入门及期末复习场景使用。报告围绕连续与离散时间信号的表示和运算、卷积运算、连续/离散LTI系统时域分析以及傅里叶级数、傅里叶变换、拉普拉斯变换和Z变换等实验展开逐章给出实验目的、实验内容、MATLAB代码与结果图可帮助读者理解采样、量化对信号的影响掌握卷积与系统响应的求解流程。资源包共1个docx文件约1.68MB正文约92页目录按实验一至实验四及章节模块组织结构完整便于按知识点检索与复盘。已有1257人学习下载适合广工电子信息类学生及需要补强信号处理实验操作的学习者参考也可作为实验报告撰写与MATLAB实现思路的样例。1. 从 92 页实验报告的复现说起实验报告卡壳的时候问题通常不在公式而在把教材里的 f(t) 翻译成 MATLAB 里的一个数组t 取多长、步长给多少、阶跃怎么表示、卷积之后时间轴怎么重建。《信号与系统》实验报告这份资源正好把这条链路完整走了一遍——92 页、四组实验、十四个章节从连续时间信号的波形到傅里叶变换、拉普拉斯变换、Z 变换每个知识点都配了能直接跑的 MATLAB 代码、结果图和分析。它适合三类人正在上信号与系统实验课、要交报告的学生想把 MATLAB 信号处理捡回来的开发者以及想搭一套教学演示模板的人。下面按我拆这份资源的顺序从目录结构讲到核心代码再讲怎么改。2. 目录结构拆解四组实验和十四个章节怎么排2.1 报告骨架四组实验串起连续到离散的主线这份报告不是按教材章节顺序写的而是按实验分组组织。目录编号本身就带着一点历史遗留味道第五章出现在实验二下面第十二、十三章又并进了实验二第十四章单独收尾在 Z 变换。第一次翻的时候容易迷路我把它按知识点重新对齐了一遍下面这张表是拆完之后的结构。实验分组覆盖章节核心知识点关键函数实验一第二、三、四章连续时间信号的 MATLAB 表示、时移反褶尺度变换、卷积运算cos、exp、square、sinc、fliplr、conv实验二第五、十二、十三章连续 LTI 系统时域分析、离散时间信号表示与运算、离散 LTI 时域分析conv、filter、stem、impulse、step实验三第六、七、八章周期信号傅里叶级数、傅里叶变换及其性质、系统频率特性与频域分析fft、abs、angle、freqs、bode实验四第十、十一、十四章拉普拉斯变换、连续系统零极点分析、Z 变换与 Z 域分析laplace、pzmap、zplane、residue这张表最大的用处是定位。比如你想找卷积的代码目录里可能出现在第四章也可能在第十三章的离散卷积里两者的写法完全不同——连续卷积要乘dt近似积分离散卷积直接用conv求和就够了。分不清这两处跑出来的幅值会差一个数量级这是后面避坑章会展开的坑之一。从技术选型看这份报告用的是纯 MATLAB 命令行脚本没有 App Designer没有 Simulink也没有用 Live Script。所有代码都写成开头的交互式命令直接粘进命令窗口就能跑。这种写法在工程上不算优雅但对实验报告场景特别合适一段代码对应一个结论读者可以逐行验证出错时也能立刻定位到是哪一行。2.2 每节的五段式结构目的、内容、代码、结果、分析这份报告最值得借鉴的不是某段代码而是每一节的固定结构。打开任意一章基本都是这个顺序实验目的、实验内容、实验代码、实验结果图、结果分析。看上去像模板但它恰好对应了懂原理、会写码、能验证三步。对于二次开发的人来说这个结构的好处是每一小节天然是一个可独立运行的单元。你完全可以把 2.3.1 里画2cos(3tpi/4)的那段代码单独拎出来放进一个函数里然后批量跑、批量出图。我在拆这类报告时的习惯是先按这个五段式做个映射表把目的对应到验证条件内容对应到输入参数代码对应到函数体结果对应到断言这样整份报告就能被自动检查。提示把五段式搬进代码时最省事的做法是在每个脚本开头用注释写清楚这一段要验证什么公式比如% 验证f(t)2cos(3tpi/4)振幅 2、角频率 3、初相 pi/4。以后改参数时看注释就知道该盯哪几个量。2.3 藏在正文里的函数文件uCT.m 与 functl.m整份报告有两处关键的自定义函数正文里只在代码块中间提了一句很容易被忽略。第一处是uCT(t)用来表示单位阶跃信号第二处是functl.m把一个分段线性信号写成了一个独立函数文件。% uCT.m单位阶跃信号等价于教材里的 u(t) function y uCT(t) y (t 0); % 逻辑数组直接返回参与运算时自动转成 0/1 end这段代码只有两行但它是整份报告里所有门函数的基础。之所以要单独写一个函数是因为在 MATLAB 里u(t)不是内置函数如果每处都写(t0)一是代码长二是做时移时容易漏括号。把它封成函数之后uCT(t-1)就天然带上了时移语义写起来和教材公式一一对应可读性立刻上来了。functl.m的作用类似只是它描述的是一个具体的分段信号。这两个文件必须放在当前工作目录或者用addpath把所在文件夹加入搜索路径否则调用时会报未定义函数。这一点报告里没写但它是新手跑不起来的第一大原因后面避坑章会专门说。2.4 运行环境与目录约定报告没有标注 MATLAB 版本但从用到的函数推断R2014b 之后的版本都能跑。square和sinc这两个函数来自 Signal Processing Toolbox如果装的是精简版 MATLAB运行到 2.3.3 和 3.3.1(2) 就会报未定义。碰到这种情况不用换环境自己补两个替代实现就行square可以用方波符号函数拼sinc用sin(pi*x)./(pi*x)并单独处理零点。这属于典型的环境不对但代码思路没错先把替代实现写进自己的工具函数里后面所有章节都能复用。目录上建议按实验分组建四个文件夹每个文件夹里放脚本和该组用到的函数文件。原因是不同实验组会用到同名的变量比如几乎每节都叫t和y一个文件夹放全部脚本时运行顺序一乱就容易拿着上一节的y去画图跑出来的图看着像对的其实完全错了。3. 连续时间信号的表示从时间向量到复信号四联图3.1 时间向量是一切的底座报告里所有波形都从一个时间向量开始。第一个例子是画2cos(3tpi/4)代码只有五行但每行都有讲究。% 2.3.1(1) 画出 2cos(3tpi/4) 的波形 t -pi/12:0.01:2*pi; % 起点、步长、终点步长决定波形顺滑度 y 2*cos(3*t pi/4); % 逐点计算y 与 t 长度必须一致 plot(t, y); grid on; % 打开网格方便读振幅和周期 axis([-pi/12, 2*pi, -2.2, 2.2]); % 手动锁死坐标范围 title(2.3.1(1));0.01这个步长在这份报告里反复出现它不是随便定的。信号里最高角频率是 3对应周期约 2.09一个周期内大约 209 个采样点画出来的曲线足够平滑如果步长给到 0.5一个周期只剩 4 个点plot会把折线画成锯齿看上去像信号失真其实是采样不够。axis那行是另一个容易被忽略的细节。四个参数依次是 x 轴最小、最大y 轴最小、最大。手动指定范围的好处是同一组实验里的几张图可以直接对比幅值坏处是如果你改了信号参数忘了改axis波形可能被裁掉一截图上什么都看不见。我一般会先plot看一眼自动范围再决定要不要写死。3.2 阶跃与门函数用逻辑数组代替 u(t)第二个例子画(2-e^(-t))u(t)报告里的代码是这样的t -2:0.01:4; y (1 - exp(-t)) .* (t 0); % (t0) 是逻辑数组乘上去等价于乘 u(t) plot(t, y); grid on; axis([-2, 4, -0.2, 1.2]);这里有两个语法点值得单独拎出来。第一是.*它是逐元素乘法左边是数值数组、右边是逻辑数组MATLAB 会自动把true/false转成1/0再逐点相乘。第二是不能写成*矩阵乘法在长度不一致时会直接报错而长度一致时会算出完全错误的结果——这种错误比报错更可怕因为图能画出来只是画的是别的东西。同一个门函数的写法还有另一种报告在画矩形脉冲时用的是相减法(t0) - (t1)。两个阶跃相减在[0, 1)区间上得到 1其他地方是 0正好是一个宽度为 1 的门。这个技巧在functl.m里被用到了极致四个分段全靠它拼出来后面第 4 章会逐行拆。注意t0返回的是 logical 类型如果直接拿去做axis之外的索引运算记得先转 double混在某些老版本工具箱函数里会报类型不匹配。3.3 复信号四联图real、imag、abs、angle复信号是这份报告里视觉信息密度最高的一节。一个复指数信号要看实部、虚部、模、相角四个量报告用subplot(2,2,k)排成田字格。t -5:0.01:10; y 2 exp(1i*(pi/4)*t) exp(1i*(pi/2)*t); % 1i 是虚数单位避免和变量 i 冲突 subplot(2,2,1); plot(t, real(y)); title(实部); grid on; subplot(2,2,2); plot(t, imag(y)); title(虚部); grid on; subplot(2,2,3); plot(t, abs(y)); title(模); grid on; subplot(2,2,4); plot(t, angle(y)); title(相角); grid on;subplot(m,n,k)的含义是把画布分成 m 行 n 列当前在第 k 个格子里画编号从左到右、从上到下。四个函数分别取实部、虚部、模、相角其中angle返回的是弧度范围在[-pi, pi]所以相角图会出现跳变——这是数学上的正常现象不是画错了。如果想让曲线连续可以在angle外面套一层unwrap这一点报告里没提但在做相位分析时几乎是必备操作。1i而不是i是个小习惯。i和j在 MATLAB 里既是虚数单位也是常见循环变量一旦你在前面写过for i 1:10后面的exp(i*t)就会拿循环残留的值去算结果莫名其妙。用1i可以彻底避开这个玄学问题。3.4 矩形脉冲square 的幅度和占空比第三节要产生一个幅度为 1、周期为 1、占空比 0.5 的矩形脉冲报告给的代码是t -0.2:0.01:1.2; y 0.5 * square(2*pi*t, 50); % 第一参数是角频率第二参数是占空比百分比 plot(t, y); axis([-0.2, 1.2, -0.7, 0.7]); grid on; title(2.3.3);square的第一个参数是角频率2*pi*t对应周期为 1第二个参数 50 表示占空比 50%即半个周期高、半个周期低。它的输出是 ±1 的方波乘 0.5 之后变成 ±0.5峰峰值正好是 1。这里有个语义上的分歧值得说清楚报告要求幅度为 1而代码得到的是 ±0.5。如果按单极性脉冲理解幅度应该是 0 到 1如果按双极性理解幅值 0.5、峰峰值 1。两种理解都能自圆其说但如果老师按单极性判这张图就要扣分。我的做法是先看实验要求里的坐标范围如果 y 轴是[-1, 1]就按双极性写是[0, 1]就加 0.5 抬到单极性。这种细节在报告里不会写但它决定了你的图能不能对上参考答案。4. 信号运算与卷积函数体不动只改入参4.1 时移、反褶、尺度变换的四种写法这一节是整份报告里设计得最巧的部分。它先定义了一个基准信号functl.m然后所有的变换都不改函数体只改传进去的自变量。t -3:0.01:3; y1 functl(t - 1); % 右移 1 y2 functl(2 - t); % 反褶后再右移 2 y3 functl(2*t 1); % 时间压缩 2 倍再左移 1 y4 functl(4 - t/2); % 时间展宽 2 倍再反褶、右移这种写法的核心思想是functl只认一个自变量你把什么表达式传进去它就算什么。t-1代入原函数相当于 f(t-1)波形右移一格2-t相当于 f(-(t-2))先反褶再右移两格2*t1相当于 f(2(t0.5))先压缩再左移半格4-t/2相当于 f(-(t-8)/2)先展宽两倍、再反褶、再右移八格。真正容易翻车的是尺度变换之后的显示范围。时间被压缩 2 倍有效区间也跟着缩了一半如果t还是原来那个-3:0.01:3图上会出现大片空白或者信号被挤在中间一小段。报告在每个子图后面都单独写了axis就是在处理这个问题。我一般会把axis和变换一起写改一处参数就顺手改一处范围省得来回找。4.2 functl.m 逐段拆解逻辑数组叠加法基准信号长这样在[-2,-1)上是一条斜率 1 的直线[-1,0)上恒为 1[0,1)上恒为 2[1,2]上是一条斜率 -1 的直线。手工画很简单写成代码就需要一点技巧。function f functl(t) % 分段线性信号用门函数逐段叠加 % 门函数写法 (ta) - (tb) 在 [a,b) 上取 1其余为 0 f (t 1) .* ((t -2) - (t -1)) ... % 第 1 段斜率 1区间 [-2,-1) 1 .* ((t -1) - (t 0)) ... % 第 2 段常数 1区间 [-1,0) 2 .* ((t 0) - (t 1)) ... % 第 3 段常数 2区间 [0,1) (-t 2) .* ((t 1) - (t 2)); % 第 4 段斜率 -1区间 [1,2] end这段代码的精髓在门函数(ta) - (tb)。两个逻辑数组相减在[a, b)上得到 1在区间外得到 0等价于一个矩形窗。把每段的表达式乘上对应的窗再相加就得到了完整的分段函数不需要if-else也不需要循环整段代码向量化执行输入多长的t都能一次性算完。这种写法的好处在二次开发时特别明显。你要加一段只需要在末尾再加一行表达式 .* 门函数要改某段斜率改那个表达式就行其他段完全不受影响。比起用for循环逐点判断向量化写法在点数上万时快得不是一点半点。4.3 奇偶分量分解fliplr 的适用条件奇偶分量这一节报告给的代码是t -3:0.01:3; y (t 0) .* (t 2) .* (1 - t); % 只定义在 [0,2] 上的三角脉冲 y1 fliplr(y); % 时间反褶左右翻转数组 ye (y y1) / 2; % 偶分量 yo (y - y1) / 2; % 奇分量fliplr是左右翻转它把数组第一个元素和最后一个元素交换第二个和倒数第二个交换以此类推。在t关于 0 对称的前提下数组翻转等价于时间反褶 f(-t)。这里有个隐含条件t必须严格关于 0 对称而且采样点数是奇数保证 0 正好落在数组正中间。如果t 0:0.01:3翻转之后得到的是 f(3-t)不是 f(-t)算出来的偶分量根本没有物理意义。报告里恰好用了对称区间所以没暴露这个问题。更稳妥的做法是对任意时间轴做重采样ye (y interp1(t, y, -t, linear, 0)) / 2; % -t 落在原区间外时补 0interp1把y在-t这些点上重新插值超出范围的部分用 0 填充。比fliplr多两行但对时间轴没有要求算是给这个技巧买的一份后悔药。4.4 卷积conv 之后时间轴必须重建连续时间卷积在 MATLAB 里只能用数值近似报告的写法是把两个信号离散化后做求和卷积再乘采样间隔还原量纲。dt 0.01; t1 0:dt:2; x (t1 0) - (t1 1); % 宽度为 1 的门函数 t2 0:dt:3; h exp(-2*t2); % 指数衰减的冲激响应 y conv(x, h) * dt; % 数值卷积乘 dt 近似积分 ty (t1(1) t2(1)) : dt : (t1(1) t2(1)) (length(y) - 1) * dt; plot(ty, y); grid on;conv输出的长度是length(x) length(h) - 1不是原来两个向量中的任何一个。所以ty不能用t1代替必须重新生成起点是两个起点之和步长还是dt点数跟卷积结果一致。这一步漏掉plot会直接报向量长度不一致如果强行截断图能画出来但时间轴是错的波形形状对、位置全歪。乘dt那一步也不是可有可无。离散卷积算的是求和Σ x[k]h[n-k]连续卷积是积分∫x(τ)h(t-τ)dτ两者差一个dt因子。不乘的话幅值会随采样密度变化——你把步长从 0.01 改成 0.001算出来的峰值会大 10 倍这种参数一改结果就变的现象最容易让人怀疑公式写错了。验证卷积结果是否正确除了看图形还有个偷懒办法拿解析解比。比如门函数和指数衰减卷积理论峰值可以手算出来用max(y)和手算值对一下误差在 1% 以内就说明数值实现没问题。这个习惯我保持到现在比盯着图看靠谱得多。5. 避坑与排查跑不出图、结果不对的五处血泪经验5.1 画图和变量类的三个坑现象一运行到plot(t,y)报未定义函数或变量 y。原因是报告里有些代码是分两段写的中间夹着一段用了未定义函数比如 2.3.1(3) 里先写了y t.*(uCT(t)-uCT(t-1))但uCT.m不在路径上这一行执行失败y根本没进工作区后面的plot(t,y)自然找不到它。另一种情况是同一个变量名在前面被算过你以为它还在其实中间某行又把它覆盖成了别的东西。解决办法很简单运行前先在命令窗口敲whos看一眼工作区里到底有什么或者干脆在每段代码开头清空clear一次。我一般会在报告脚本最前面加clear; close all; clc;虽然粗暴但能避免 90% 的变量残留问题。现象二四联图里第二个子图只剩一条曲线。复信号那节的虚部代码里subplot(2,2,2)下面连着写了plot(t, real(y))和plot(t, imag(y))。MATLAB 的plot默认会清除当前坐标区第二次调用把第一次画的线擦掉了所以最后只剩虚部。改法有两种一是中间加hold on二是把两条线写进同一个plot调用subplot(2,2,2); plot(t, real(y), t, imag(y)); % 一次画两条自动分色 legend(实部, 虚部); grid on;第二种写法在报告里更常见因为省了一次hold图例也能一次配齐。现象三坐标范围怎么设都不对波形被裁掉。典型例子是模那个子图先写了axis([-5,10,-2.2,2.2])紧接着又写axis([-5,10,1,3])后一行把前一行覆盖了最终范围是[1,3]如果模的最小值小于 1曲线下半截就被裁掉了。排查办法是数一下每个子图里axis出现的次数。正常应该只有一行写在plot之后、title之前。多行的情况要么是复制粘贴留下的要么是改参数时忘了删旧的。我现在的习惯是把axis和title写在一起改范围的时候两行一起动不容易漏。5.2 函数和数值类的两个坑现象四sinc画出来的过零点位置和教材差一个 pi。MATLAB 的sinc(x)定义是 sin(πx)/(πx)而教材里常写的抽样函数是 Sa(t) sin(t)/t。两者相差一个缩放因子过零点一个在整数处一个在 π 的整数倍处。直接套用会导致波形看起来对、刻度全错。改法是自己写一个function y sa(t) % 教材定义的抽样函数 sin(t)/tt0 处取极限值 1 y sin(t) ./ (t (t 0) * eps); % 分母补一个极小量避开 0/0 y(t 0) 1; endt0时补eps是为了避免除零警告随后再把该点覆盖成 1。这个写法比if判断更向量化输入数组也能直接用。现象五conv之后画图报向量长度不一致。卷积输出长度是NM-1很多人直接拿原来的t去画长度对不上就报错也有人用linspace重建时间轴但起止点算错了图能画出来、波形位置全是歪的。正确的重建方式是起点相加、步长不变、长度跟卷积结果走也就是 4.4 节里那段ty。判断有没有算错看两个特征波形起点应该等于两个输入起点之和波形终点应该等于两个输入终点之和。这两个数对不上说明时间轴重建错了。注意卷积前先确认两个信号的采样间隔是否一致。如果x用 0.01、h用 0.02直接conv得到的结果没有物理意义必须先统一重采样到同一个dt。6. 二次开发把十四节实验改成一个可复用模板库拆完这份报告我做的第一件事是把每个实验小节拆成独立的函数而不是继续用一堆命令行脚本。原因是脚本里的变量全都躺在工作区跑完一节再跑下一节t、y、f互相覆盖想单独复现某张图得从头再跑一遍。改造思路分三层最底层是工具函数uCT、sa、门函数这些放一个文件夹统一addpath中间层是每个实验对应一个demo_*函数只负责算和画不负责保存最上层是一个批量渲染脚本跑一遍把所有图导出成 PNG写报告时直接贴。% render_all.m批量跑实验图并导出写报告时直接取用 figDir fullfile(pwd, figs); if ~exist(figDir, dir), mkdir(figDir); end cases {()demo_cos, ()demo_step, ()demo_complex, ()demo_conv}; names {fig_2_3_1_1, fig_2_3_1_2, fig_2_3_2_1, fig_3_3_conv}; for k 1:numel(cases) f figure(Visible, off); % 不弹窗批量跑的时候窗口不会乱闪 cases{k}(); % 调用对应的绘图函数 print(f, fullfile(figDir, [names{k} .png]), -dpng, -r150); close(f); end这段代码的关键在Visible, off和-r150。前者让图在后台渲染跑二十个实验也不会满屏弹窗后者是导出分辨率150 dpi 足够报告印刷再高文件会大到不好传。函数句柄用()demo_cos这种匿名形式包一层是为了让所有 case 的调用方式统一加新实验时只改数组、不改循环。再进一步可以给每个demo_*加断言。比如卷积那个函数算完之后用解析解的峰值做一次assert误差超过阈值就直接报错而不是等你把图贴进报告之后才发现形状不对。这套东西我一般叫它图形回归测试——图对不对肉眼看不出来但数值对不对一测就知道。改造过程中最容易忽略的是路径问题。工具函数文件夹加进addpath之后换一台机器又要重新加一遍所以我习惯在项目根目录放一个setup.m里面写死相对路径别人拿到文件夹先跑一次setup就能用。这一步多花五分钟能省掉后面无数次在我电脑上明明能跑的扯皮。从那以后我每次接手这类实验报告类的资源都强制先跑一遍清空工作区、只留函数文件、从头执行的流程确认它不是靠工作区里的残留变量才跑通的。这份报告里那几处y未定义、axis被覆盖的问题全都是靠这个流程揪出来的。希望帮到你。本文还有配套的精品资源点击获取