ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MATLAB信号与系统实验报告:卷积、频谱与零极点分析

MATLAB信号与系统实验报告:卷积、频谱与零极点分析

简介:面向广东工业大学信息工程学院电子信息类学生及备考信号与系统实验的学习者,这份实验报告以MATLAB为工具,系统梳理连续与离散时间信号表示、卷积运算、LTI系统时域与频域分析等实验内容,可用于课程实验对照、报告撰写参考与考前复盘。包内共1个docx文件,约1.68MB,正文按实验模块组织,含实验目的、实验内容、代码与结果图,目录覆盖阶跃与冲激信号生成、连续时间卷积、离散信号运算、采样量化、傅里叶级数与变换、拉普拉斯变换等知识点,便于按章节检索。已有1257人学习,适合需要完善实验流程、核对波形结果或理解MATLAB实现细节的读者参考。

1. 一份实验报告真正难的地方,不在公式

电子信息类专业的学生打开 MATLAB,第一反应往往是照着指导书把命令一条条敲进去,再截图贴进文档。交上去被追问一句「这个 0.01 的步长怎么定的」「卷积之后时间轴为什么从这里开始」,就答不上来了。《信号与系统》实验报告要交的从来不是几张好看的波形图,而是一条能复现的链路:连续时间信号在 MATLAB 里怎么表示,离散时间 LTI 系统怎么用卷积和差分方程验证,傅里叶变换、拉普拉斯变换、Z 变换的结论怎么跟频谱和零极点对上号。这套报告覆盖十四个章节、四个实验包,从 2cos(3t+π/4) 这类基础波形一路走到零极点分析和 Z 域求解。适合两类人:一是要交课程实验报告、需要一套完整结构照着写的电子信息类学生;二是毕设前期要用 MATLAB 做信号仿真验证、想找一份能直接改参数复用的模板的开发者。

2. 实验体系拆解:四个实验包、十四个章节的主线与工具链配置

2.1 十四个章节其实只有三条主线

把目录摊开看,章节编号跳来跳去,容易让人以为内容很散。按知识依赖重新排一遍,其实是三条主线串起来的:第一条是信号的表示与运算,包含连续时间信号的 MATLAB 表示、时移反褶尺度变换、微分积分、加减相乘;第二条是时域分析,核心是卷积和 LTI 系统的响应求解,连续和离散各来一遍;第三条是变换域分析,傅里叶级数、傅里叶变换、频率特性、拉普拉斯变换、零极点、Z 变换依次展开。前一条是后一条的工具,卷积没写对,后面的频域验证基本没法做。

主线对应章节核心函数与写法交付物
信号表示与运算第二、三、十二章plot、subplot、real/imag/abs/angle、自建阶跃函数波形图、复信号四视图、奇偶分量分解
时域分析第四、五、十三章conv、filter、lsim、impulse、step卷积波形、系统响应曲线
变换域分析第六、七、八、十、十一、十四章sinc、fft、freqs、laplace、ztrans、roots、zplane频谱图、幅频相频曲线、零极点图

这张表的价值在于排期。做实验的时候按主线走,不要在第二章纠结复信号的相角画法,也不要一上来就啃 Z 变换——先把阶跃函数和分段信号写顺,后面所有卷积、积分、能量计算的被积函数都靠它。

2.2 一个实验单元的标准三段式:代码、波形、结果分析

报告里每个小题都是同一套骨架:先给实验代码,再贴结果图,最后写结果分析。前两段大多数人都会写,拉开差距的是第三段。有效的分析必须落到具体参数上,而不是「由图可知该信号是衰减的」这种万能句。比如 2cos(3t+π/4),分析要明确写出振幅 2、角频率 3 rad/s、初相位 π/4、周期 2π/3;比如 e^(-t)sin(10πt) 这类调幅信号,要指出包络由 e^(-t) 决定、振荡频率由 10π 决定、两者相乘形成衰减振荡。写完参数,再补一句「如果把 10π 改成 20π,波形会变密但包络不变」,这段分析就有了可验证性。

代码段也有讲究。截图命令行窗口是最容易被扣分的写法,因为别人没法复现。正确做法是把每个小题写成独立脚本,脚本开头清空环境、定义时间轴、定义信号,结尾统一grid on、xlabel、ylabel、title。同一个实验里多个小题共用一个时间轴定义时,放在脚本最前面,改一次全局生效,比在每个小题里各写一遍要稳。

2.3 工具链:几个容易被忽略的函数依赖

基础绘图不需要额外工具箱,但报告里用到的square、sinc属于 Signal Processing Toolbox,laplace、ztrans、ilaplace、iztrans属于 Symbolic Math Toolbox。机房版本装没装这两个工具箱,动手前先确认一遍,否则跑到一半报未定义函数,时间全耗在找环境上。快捷验证方式是命令行敲ver看已安装工具箱列表,或者直接which square看有没有返回路径。

还有两个习惯要在一开始就养成。文件命名不要用数字开头,也不要和内置函数同名——曾经有人把分段信号函数存成sinc.m,之后所有调用sinc的地方全部串到他自己的函数上,波形画出来完全不对,排查了大半天。工作目录统一放在一个实验文件夹下,函数文件和脚本文件同级,避免Undefined function这类问题。脚本开头加一句clear; close all; clc;,把上一次运行的残留变量和图窗清掉,这个动作后面会救很多次命。

3. 连续时间信号的表示与运算:从 0.01 步长到奇偶分量分解

3.1 时间轴离散化:步长决定了波形可信度

MATLAB 画连续信号,本质是用密集的点连成线,所以时间轴的步长直接决定图形是否可信。步长取 0.01 在大多数题目里够用,但要看信号最高频率成分:画 sin(10πt) 时,一个周期是 0.2 s,0.01 的步长只能采到 20 个点,波形勉强能看;如果频率再翻一倍,就会出现明显的折线感甚至混叠,看起来像另一个频率的信号,这就成了玄学问题。判断标准很朴素——把步长减半再画一次,波形形状明显变了,说明原来的步长不够。

clear; close all; clc; dt = 0.001; % 时间步长,高频信号建议 0.001 及以下 t = -2:dt:2; % 时间范围要覆盖信号的有效区间 f = exp(-t).*sin(10*pi*t); % 衰减振荡信号 plot(t, f, 'LineWidth', 1.2); grid on; xlabel('t / s'); ylabel('f(t)'); title('e^{-t}sin(10\pi t) 波形');

这段代码的关键是三个参数。dt控制采样密度,t的上下界控制有效区间,LineWidth只是让图在文档里不糊。时间范围要覆盖信号变化最剧烈的部分,衰减信号取到 -2 到 2 就够,如果取 -10 到 10,两端全是平的,有效波形被压成一小段,图上什么也看不清,调axis也救不回来。

3.2 阶跃信号自建函数与分段信号封装

报告里大量题目带 u(t),而 MATLAB 没有内置的连续阶跃函数,必须自己写一个。写成独立函数文件,全篇复用:

function y = uCT(t) % 连续时间单位阶跃:t >= 0 输出 1,否则输出 0 % 支持向量输入,(t>=0) 返回逻辑数组,参与算术运算时自动转 0/1 y = double(t >= 0); end

有了它,(2-e^(-t))u(t)、t[u(t)-u(t-1)]、[1+cos(πt)][u(t)-u(t-2)] 这类题就能一行写完:

t = -2:0.001:4; y = (1 + cos(pi*t)) .* (uCT(t) - uCT(t-2)); % 加窗后只在 [0,2) 有值

注意必须是点乘.*,不是矩阵乘。向量和向量做逐元素运算时写成*会直接报维度错误,这是新手最常撞的一堵墙。同理,(t>=0)-(t>=1)这种两个逻辑数组相减的写法,等价于一个宽度为 1 的矩形窗,比分段 if-else 简洁得多,也更快。

分段折线信号建议封装成函数文件,比如报告里那个四段拼接的 f(t):

function f = functl(t) % 四段折线信号,用逻辑量相减实现区间开关,避免 if 判断 f = (t+1) .* ((t>=-2) - (t>=-1)) ... % [-2,-1):斜率 1 + 1 .* ((t>=-1) - (t>=0)) ... % [-1, 0):常值 1 + 2 .* ((t>=0) - (t>=1)) ... % [ 0, 1):常值 2 + (-t+2) .* ((t>=1) - (t>=2)); % [ 1, 2]:斜率 -1 end

封装成函数的好处是,后面所有「f(t-1)、f(2-t)、f(2t+1)、f(4-t/2)」的题都不用重写表达式,只改传进去的自变量,这是整份报告里性价比最高的一个动作。

3.3 复信号四视图:实部、虚部、模、相角

复信号题要求同时画出实部、虚部、模、相角,四个子图排成 2×2。写法上有一个细节必须注意:虚数单位用1j,不要用i——i在 for 循环里是默认循环变量,一旦被覆盖,后面的exp(i*...)就全错了,而且不报错,图看上去还挺像那么回事,属于典型的黑匣子故障。

t = -5:0.01:10; y = 2 + exp(1j*(pi/4)*t) + exp(1j*(pi/2)*t); % 用 1j 表示虚数单位 subplot(2,2,1); plot(t, real(y)); grid on; title('实部'); subplot(2,2,2); plot(t, imag(y)); grid on; title('虚部'); subplot(2,2,3); plot(t, abs(y)); grid on; title('模'); subplot(2,2,4); plot(t, angle(y)); grid on; title('相角 / rad');

四个子图的axis范围要分别设,不要图省事四个都写同一组数。模的取值范围和相角的取值范围差着量级,共用一组参数的结果就是相角曲线被压成一条直线。相角用angle返回的是 (-π, π] 的主值,遇到跨越 ±π 的时刻会出现跳变,看起来像断线——这不是错,是主值折叠,分析里写清楚就行。

3.4 时移、反褶、尺度变换:只改函数入参

这一组题考的是对 f(at+b) 的理解。原函数封装好之后,四道题只需要四次调用:

题目表达式变换类型期望结果
f(t-1)functl(t-1)右移 1波形整体右移
f(2-t)functl(2-t)反褶 + 右移左右翻转后平移到 [0,3]
f(2t+1)functl(2*t+1)压缩 2 倍 + 左移 0.5波形变窄到原宽度一半
f(4-t/2)functl(4-t/2)展宽 2 倍 + 反褶 + 平移宽度翻倍且左右翻转

看结果的时候按「先反褶、再尺度、最后平移」的顺序对照,比死记公式靠谱。反褶看波形是否左右颠倒,尺度看有效区间宽度变成原来的几分之一,平移看起点落在哪。三个动作分开验证,出错时能立刻定位是哪一步理解错了,不用整段重算。

3.5 奇偶分量分解与 fliplr 的边界

偶分量和奇分量的定义是 f_e(t) = [f(t)+f(-t)]/2,f_o(t) = [f(t)-f(-t)]/2。数值实现最省事的写法是用fliplr把数组反过来:

t = -3:0.01:3; % 关于原点对称,601 个点,包含 t=0 y = (t>=0).*(t<=2).*(1-t); % 待分解信号 ye = (y + fliplr(y)) / 2; % 偶分量 yo = (y - fliplr(y)) / 2; % 奇分量

fliplr成立有两个前提,缺一不可:时间轴必须关于原点严格对称,采样点数必须是奇数(保证 t=0 落在正中间)。t = -3:0.01:3生成 601 个点,正好满足。一旦写成-3:0.01:3.005,点数变成 602,反过来的数组整体错位半个采样点,奇分量在 t=0 附近会莫名其妙翘起来,波形看着像对了又像不对,排查起来非常费劲。血泪经验是:分解前先numel(t)确认点数是奇数,再用max(abs(t+t(end:-1:1)))验证时间轴对称,两行代码省半小时。

4. 从卷积到变换域:LTI 系统分析与频谱、零极点的落地写法

4.1 连续卷积的数值实现与时间轴对齐

卷积是整份报告的分水岭。conv算的是离散序列的卷积和,要近似连续卷积,必须乘采样间隔,而且输出的时间轴要重新构造,长度是 N+M-1。

dt = 0.01; t = -2:dt:4; f = (t>=0).*exp(-t); % 输入信号:单边指数 h = (t>=0).*(t<=2); % 系统冲激响应:宽度 2 的矩形窗 y = conv(f, h) * dt; % 连续卷积要乘步长 dt ty = (0:length(y)-1)*dt + (t(1)+t(1)); % 起点为两信号起始时刻之和 plot(ty, y); grid on; xlabel('t / s'); ylabel('y(t)');

三个参数必须对上。乘dt是因为离散求和近似积分,漏掉它结果会整体大 100 倍,波形形状对但纵轴离谱;ty的起点是t(1)+t(1),不是t(1),起点写错整条曲线会往左平移;长度用length(y)-1而不是原信号长度,写死成原长度会截断尾部。检查方法很直接:卷积结果的面积应该约等于两个信号面积的乘积,用sum(y)*dt和理论值比一下,数量级对不上就说明哪里漏了。

4.2 离散卷积与差分方程:conv 和 filter 的分工

离散部分容易混的地方是搞不清什么时候用conv、什么时候用filter。conv求的是两个有限长序列的卷积和,对应 y[n] = x[n]*h[n],不需要乘步长,因为离散序列本身没有时间间隔的概念。filter解的是差分方程,输入系数向量 a、b 和激励 x,直接得到零状态响应,适合递推形式的系统。

n = 0:30; x = (n>=0); % 单位阶跃激励 h = (0.5).^n; % 系统单位脉冲响应 y1 = conv(x, h); % 方式一:卷积和,长度 61 y2 = filter(1, [1 -0.5], x); % 方式二:差分方程 y[n]-0.5y[n-1]=x[n] stem(n, y2, 'filled'); grid on; % 递推结果只到 n=30,与 y1(1:31) 一致

两种方式的结果在前 31 个点上完全重合,这个对照本身就是很好的实验分析素材:写清楚「卷积和与差分方程描述同一系统,前者给出全响应长度,后者按递推逐步计算」,比单纯贴两张图有说服力。

4.3 周期信号傅里叶级数与频谱柱状图

矩形脉冲串的复傅里叶系数有解析式 D_n = (Aτ/T)·sinc(nτ/T),MATLAB 的sinc定义正好是 sin(πx)/(πx),可以直接对上,不用自己再凑。

A = 1; tau = 0.5; T = 1; % 幅度、脉宽、周期 N = 15; % 谐波次数上限 n = -N:N; Dn = (A*tau/T) * sinc(n*tau/T); % 复傅里叶系数 stem(n, abs(Dn), 'filled'); grid on; xlabel('谐波次数 n'); ylabel('|D_n|'); title('周期矩形脉冲幅度谱');

频谱用stem不用plot,因为离散谱线之间没有定义,连成线是错的。参数怎么改也有讲究:tau/T是占空比,占空比越小,包络的零点越往外推,谱线衰减越慢;N控制画多少根谱线,取太小看不出包络形状,取太大图挤成一团,15 到 30 之间比较合适。分析里把这两条写进去,说明白参数对频谱的影响,这一小题就算做透了。

4.4 傅里叶变换性质验证:用一组对照实验说话

验证时移、频移、尺度变换这些性质,最有效的做法是做对照实验而不是单张图。以时移为例:同一信号画两条曲线,一条原信号,一条延迟 τ 后的幅度谱,两条幅度谱应该完全重合,相位谱相差 -ωτ。尺度变换则是时域压缩、频域展宽,把 a=2 和 a=0.5 两种情况并排画出来,展宽压缩的关系一眼可见。这种对照写法比孤零零一张频谱图更像实验,答辩时也更容易讲清楚「我怎么知道它对了」。

4.5 系统频率特性与零极点图

连续系统的频率特性用freqs求,给的是 s = jω 处的情况;零极点用roots或zplane求,前者不依赖工具箱。

b = [1 0]; a = [1 3 2]; % H(s) = s / (s^2+3s+2) w = linspace(0, 20, 800); H = freqs(b, a, w); subplot(2,1,1); plot(w, abs(H)); grid on; title('幅频特性'); subplot(2,1,2); plot(w, angle(H)); grid on; title('相频特性'); p = roots(a); % 极点:-1 和 -2,均在左半平面 z = roots(b); % 零点:0 disp(p); disp(z);

分析要落到「极点位置决定稳定性」这条线上:两个极点都是负实数,系统稳定;极点离虚轴越近,对应模态衰减越慢。零极点图在离散域用zplane(b,a)画,同一个函数能同时显示单位圆,判断稳定性看极点是否都在圆内。这套写法在拉普拉斯变换和 Z 变换两章之间是通用的,换个变量名就能复用。

5. 避坑与常见问题排查:五个最容易翻车的点

5.1 波形类问题:图不对,但代码不报错

现象一:波形是折线,或者频率看起来不对。原因基本锁定在采样步长上——步长相对信号最高频率成分太大,一个周期只采到几个点,连出来的线已经不能代表原信号。解决方式是减半步长重画一次做对比,形状明显变化就说明原步长不够;同时把t的范围收窄到有效区间,别用大范围加小步长硬堆,向量长度上百万时绘图会明显卡顿。

现象二:图上什么都看不见,只有一条水平线。常见原因是axis的范围写死了,而且写错了位置。比如先axis([-0.5,2.5,-1.2,4.2])再plot,后画的图会重置坐标轴;或者信号实际峰值在 5 附近,axis上限却卡在 1.2,曲线被整体裁掉。解决顺序是先plot加grid on看看自动范围,确认波形正确之后再补axis微调,别一上来就硬编码。

现象三:相角曲线出现垂直跳变,像断线。这是angle返回主值 (-π, π] 造成的折叠,不是错误。想要连续曲线可以用unwrap展开,但报告里更推荐保留原样并补一句解释,因为主值折叠恰好说明相位确实绕过了 ±π,是个可以写进分析的观察点。

5.2 运算类问题:形状对不上,答案全错

现象四:Undefined function 'uCT'或者阶跃画成一条直线。报告里阶跃函数是自定义的,如果只建了脚本没建函数文件,调用时必然报未定义;也有人把uCT写成(t>0)而不是double(t>=0),逻辑数组直接参与plot时看不出问题,但一旦进入积分或卷积就会被当成布尔量处理,结果全错。解决办法是把阶跃函数固化成独立.m文件放在当前工作目录,所有脚本共用同一份,绝不各写各的。

现象五:卷积波形形状对、位置错,或者整体偏大。三个参数至少错了一个:漏乘步长dt(纵轴大两个数量级)、时间轴起点写成t(1)而不是两信号起点的和(曲线整体左移)、结果长度按原信号长度截断(尾部丢失)。排查顺序固定下来——先看纵轴量级是否符合面积乘积,再看起点是否等于两起点之和,最后看总长度是否为 N+M-1,三步走完基本能定位。

现象六:奇偶分量分解后,t=0 附近翘起来。fliplr要求时间轴关于原点严格对称且点数为奇数。-3:0.01:3是 601 点,没问题;改成-3:0.01:3.01就是 602 点,翻转后整体错位半个采样点,奇分量在原点附近就会出现异常值。动手前用numel(t)和mod(numel(t),2)各查一次,奇数且包含 0 才用这套写法,否则改用插值重采样到对称网格再做分解。

6. 验收与答辩:把报告过一遍自查清单

报告写完不等于能交。我一般会按一张清单从头走一遍,每条都对应一个可以被追问的点,提前把答案准备好,比答辩现场临场组织语言稳得多。

检查项检查方法合格线
代码可复现新建空目录,只拷脚本和函数文件跑一遍无报错,图形与报告一致
波形正确性步长减半重画一次形状无明显变化
坐标标注每张图都有 xlabel、ylabel、title缺一不可,单位写清
结果分析是否写出振幅、频率、相位、衰减系数等具体参数至少两个可验证参数
参数对照是否说明「改某个参数会怎样」每章至少一处
环境依赖是否注明所用工具箱写明函数所属工具箱

答辩时被问得最多的不是公式推导,而是参数选择。比如「为什么步长取 0.01」「卷积结果的时间轴为什么从 -4 开始」「占空比从 0.5 改成 0.2 频谱会怎么变」,这些都能在报告里提前写好答案。还有一个高频追问是「你这个结果怎么验证是对的」——卷积用面积乘积验证,傅里叶级数用直流分量 D_0 = Aτ/T 验证,零极点用稳定性判据验证,每个结论都配一个独立于作图结果的检验方法,说服力立刻不一样。

从那次卷积时间轴整体错位、图看着没问题但能量算出来差了四倍之后,我每次写完卷积都会强制走一遍「量级、起点、长度」三步核对,宁可多花五分钟,也不在答辩前夜返工。希望这套结构帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进