MATLAB实现连续时间信号卷积:从符号积分到数值仿真
2026/9/17 19:45:31 网站建设 项目流程

简介:面向信号处理初学者的实验指导文档,核心内容是使用 MATLAB 实现连续时间信号的卷积运算。文档从卷积的概念与物理意义讲起,结合单位冲激响应的理解,逐步给出 sconv 通用函数的完整代码、示例题目与运行波形,并通过调整抽样时间 p 对比结果,直观展示数值近似与理论卷积的关系。包内仅含 1 个 doc 文件,体积约 186KB,内容精炼,适合“信号与系统”课程实验参考或考前复习。目前已有 436 人浏览学习,说明该资料对同类学习者具有较高的参考价值。文档还附有实验要求与实验心得,既能辅助读者完成课后习题,也可作为撰写实验报告的模板;其中对卷积结果波形图的解读,有助于加深对信号时域运算的掌握,是一份兼具操作性和理论性的小型实用资料。

1. 连续时间信号卷积运算为什么需要MATLAB

做信号与系统实验时,手算两个矩形脉冲的卷积只需要分段积分,一旦换成指数信号与三角波叠加,分段点一多,纸面上就开始漏项。连续时间信号卷积的定义式是一个积分,但真正把它当积分去算,大多数人会被换元、翻转、移位和分段上下限折磨到怀疑积分表。MATLAB的价值不在替你做数学,而在让你把“卷积怎么算出来”从纸面搬到命令窗口,一遍遍改参数、看波形、验证自己的分段结果。对电子、自动化、通信专业的学生来说,这个实验是第一次体会“连续系统时域分析也能数值化”;对工程师来说,卷积是实现滤波、系统响应和相关性分析的基本积木。这篇内容就围绕“连续时间信号卷积”这一个题目,把符号计算、数值离散和时间轴对齐这三条路全部走一遍,让你在实验报告之外,真正能把卷积当工具用。

2. 卷积积分原理与MATLAB实现路径选择

2.1 连续卷积的数学定义与物理含义

因果系统输出是输入激励与系统冲激响应的卷积积分,数学形式写为:

[ y(t) = \int_{-\infty}^{+\infty} x(\tau) h(t-\tau) d\tau ]

这里 (x(\tau)) 是输入信号,(h(t-\tau)) 是冲激响应翻转和平移后的结果。物理含义很直白:任意激励可以拆成无数个冲激函数的加权积分,系统对每个冲激的响应叠加起来就是总响应。连续时间信号卷积运算的关键在于确定积分有效区间,也就是 (x(\tau)) 和 (h(t-\tau)) 都非零的 (\tau) 取值范围。这个范围会随 (t) 变化而变化,所以手算时总要按 (t) 分段讨论。

MATLAB处理这个积分有两种视角。第一种是符号视角,直接把 (x(t)) 和 (h(t)) 写成符号表达式,交给int去积;第二种是数值视角,把连续时间信号按采样间隔离散成数组,用离散卷积近似连续卷积。选择哪种路径,取决于你手里信号的表达形式、精度要求以及实验题目是否要求同时给出解析式和波形。

2.2 解析法:符号计算适合简单信号

用MATLAB内置的符号数学工具箱,可以直接对卷积积分做符号积分。常见做法是:

syms t tau x = heaviside(t) - heaviside(t-1); % 矩形脉冲,0<t<1 h = exp(-t) * heaviside(t); % 单边指数衰减信号 % 计算卷积积分表达式 y = int(x * subs(h, t, t-tau), tau, -inf, inf); y = simplify(y);

这里的subs(h, t, t-tau)把 (h(t)) 变量替换为 (t-\tau),然后对 (\tau) 从负无穷到正无穷积分。符号方法的好处是结果精确,能直接写出分段函数表达式;坏处是一旦信号包含piecewise或非基本初等函数,积分可能非常慢,甚至返回未求值的积分原式。

实际做实验时,我会先用符号方法求一遍解析结果,这样后面画图时心里有底。

2.3 数值法:采样与离散卷积的关系

数值法回避积分运算,直接对信号采样。设连续信号 (x(t)) 和 (h(t)) 以采样间隔 (dt) 采样得到序列 (x[n]) 和 (h[n]),那么连续卷积的近似值为:

[ y(k,dt) \approx dt \cdot \sum_{n} x[n], h[(k-n)] ]

右端正是离散序列的卷积,乘以一个 (dt) 因子。这个近似成立的前提是信号带宽有限且采样率满足奈奎斯特条件,同时 (dt) 足够小,不然积分误差会被肉眼看出。MATLAB里的conv函数就是做离散卷积的,但它不关心采样间隔和时间轴,所以用之前必须先把时间段定义清楚。

2.4 路径选择建议

对比项符号积分int数值卷积conv
输入形式符号表达式离散数组
结果特点精确分段表达式近似离散点
耗时简单信号快,复杂信号可能卡住无论什么信号都很快
时间轴处理返回符号,画图需fplot需手动构造
适合场景验证手算结果工程仿真、任意波形
工具箱要求Symbolic Math Toolbox基本MATLAB即可

3. 用MATLAB实现连续卷积的最小可运行代码

3.1 方法一:用int做符号卷积

先看符号方法的最小完整示例。假设输入是门函数 (x(t)=u(t)-u(t-2)),系统冲激响应是 (h(t)=e^{-t}u(t)),那么卷积结果是 ((1-e^{-2})e^{-t}u(t)-u(t-2)) 类似的形式,下面直接求并画图。

syms t tau x = heaviside(t) - heaviside(t-2); h = exp(-t) * heaviside(t); x_tau = subs(x, t, tau); % 将 x(t) 变为 x(tau) h_t_minus_tau = subs(h, t, t - tau); % 将 h(t) 变为 h(t-tau) y = int(x_tau * h_t_minus_tau, tau, -inf, inf); y_simple = simplify(y); disp(y_simple); % 绘制符号结果 figure; fplot(y_simple, [-2, 6]); xlabel('t'); ylabel('y(t)'); title('符号卷积结果'); grid on;

逻辑说明:第一步把 (x(t)) 和 (h(t)) 都替换成积分变量 (\tau) 的函数,其中 (h) 要替换成 (t-\tau)。int求对 (\tau) 的无穷积分,simplify整理分段条件。这里没有调用任何额外函数,代码直接可运行。

参数说明:heaviside是MATLAB的单位阶跃函数,默认在零点值为0.5,但与理想阶跃在积分下等价。int的积分区间写成-inf, inf,表示全域积分,MATLAB自动根据阶跃函数确定有效范围。fplot直接画符号表达式,不需要先eval成数组。

3.2 方法二:用conv做数值卷积

数值方法是实验报告里最常用的。核心是定义时间向量和采样间隔,然后调用conv,最后记得乘上dt

dt = 0.01; % 采样间隔,越小越精确 t = -2:dt:6; % 定义时间范围 x = double(t >= 0 & t < 2); % 门函数:0<=t<2 时为1 h = exp(-t) .* double(t >= 0); % 指数衰减:t>=0 时为 exp(-t) y = conv(x, h) * dt; % 离散卷积乘以dt得到近似连续卷积 % 构造卷积后的时间轴:conv结果长度为 length(x)+length(h)-1 t_conv = (0:length(y)-1)*dt + t(1) + t(1); t_conv = t_conv - t_conv(1) + (-2); % 统一起点为-2 figure; plot(t_conv, y); xlabel('t'); ylabel('y(t)'); grid on;

逻辑说明:conv(x,h)输出长度为两个序列长度之和减一,对应的起始时间近似等于两个序列起始时间之和。这里的时间轴构造最容易出错,必须先确定两个起始点,再根据采样间隔递增。代码里把起点统一设置为-2,是因为 (x) 和 (h) 的起点都是-2的样本点,所以卷积后首点对应时间约为两个起点相加-4,但实验通常关心非零区间,我会再手动偏移到合理范围。

参数说明:dt是精度控制的关键,取0.01时肉眼几乎看不出误差;改小到0.001会显著增加计算量,但结果更稳。double(t >= 0 & t < 2)把逻辑数组转成0/1数组,用来表示信号取值。

3.3 方法三:手动积分循环,用于理解运算过程

如果不想用conv这个“黑盒”,可以自己写双重循环来理解卷积的本质。

dt = 0.01; t = -2:dt:6; x = double(t >= 0 & t < 2); h = exp(-t) .* double(t >= 0); n = length(t); y_manual = zeros(1, 2*n-1); for k = 1:2*n-1 acc = 0; for m = 1:n if (k - m + 1) >= 1 && (k - m + 1) <= n acc = acc + x(m) * h(k - m + 1); end end y_manual(k) = acc * dt; end

逻辑说明:外层循环变量k对应结果数组的索引,内层循环完成 (x[m]) 与 (h[k-m]) 的乘积累加。边界条件判断是为了处理k-m+1越界。这段代码比conv慢但教学意义强,你可以在断点处观察每一次翻转和移位。

参数说明:结果长度是2*n-1,当n=801时结果长度为1601。双重循环复杂度是 (O(n^2)),只适合长度较短的情况,真实工程里不会这么写。

3.4 三种方法的对比与适用边界

方法核心函数输出形式速度精度适用场景
符号法int符号表达式精确理论推导、验证手算
数值法conv离散数组dt相关波形仿真、滤波计算
循环法双层循环离散数组很慢dt相关教学演示、理解原理

4. 卷积结果与时间轴对齐:三个必调参数和常见坑

4.1 采样间隔dt对精度的影响

采样间隔是数值卷积的命根子。dt取得太大,卷积结果会出现“台阶感”,甚至把原本平滑的波形变成锯齿;取得太小,数组长度线性增长,conv本身很快,但绘图可能卡顿。

一个简单实验:分别取dt=0.1, 0.01, 0.001,计算同一个卷积的最大误差。观察发现dt从0.1降到0.01时,误差约缩小十倍;再从0.01降到0.001时,误差进一步缩小十倍,但时间向量的点数从800涨到8000。对于大多数连续时间信号的实验,dt=0.01足够,如果追求高精度并绘制出版级插图,再用dt=0.001

注意,conv本身是精确的离散卷积,误差完全来自“离散化代替连续积分”的近似,所以不能指望增大数组长度消除所有误差,只能让近似更接近真实值。

4.2 时间轴起点的对齐规则

很多人在conv之后直接把结果从0开始画,这是实验报告里最常见的错误。conv(x, h)的结果序列 (y[k]) 对应的连续时间不是从0开始,而是从两个输入序列的起始时间之和开始。如果x的起始时间是t_x0h的起始时间是t_h0,那么结果起始时间约为t_x0 + t_h0

下面给一个通用的时间轴构造函数:

function t_conv = convtime(t1, t2, n1, n2) t_start = t1(1) + t2(1); t_end = t1(end) + t2(end); t_conv = linspace(t_start, t_end, n1 + n2 - 1); end

其中t1t2分别是两个信号的时间向量,n1n2是长度。这个函数用等间隔方式生成结果时间轴,前提是t1t2的间隔一致。如果两个信号采样间隔不同,conv就不能直接使用,必须先插值到同一间隔。

4.3 边界不连续点与heaviside的处理

连续时间信号里常用阶跃u(t)来截断信号。MATLAB的heaviside(0)默认是0.5,而手算时一般认为u(t)=0或1,这个差异在符号积分中不会影响最终结果,因为积分测度忽略单点值;但在数值离散中,如果一个信号在整时刻跳变,比如t=2处从1跳到0,采样点恰好落在边界上时会产生半个值。

常见处理办法是用严格不等式:

x = double(t > 0 & t < 2); % 端点设为0

或者用t >= 0 & t < 2把左闭右开区间,这样卷积结果与理论值更一致。注意若把两个端点都包含进去,某些对称信号可能会出现轻微偏差,导致峰值多一个采样点宽度。

4.4 符号卷积结果中的piecewise与化简陷阱

符号计算int在遇到分段信号时通常会返回piecewise表达式。比如卷积一个矩形脉冲和一个三角波,结果可能在多个分段区间有不同的代数式。simplify可以整理代数式但可能保留piecewise的多个分支。这时不要继续手抄表达式,直接用fplot画图验证波形形状。

如果int返回原积分形式未能求值,先检查信号里是否有过大的复数或未定义常数,再把t限定为实数:

syms t tau real

这个声明能避免MATLAB在复数域上跑偏,加快化简速度。同时把无穷积分区间改成实际非零重叠区间,也能显著提速,例如两个信号非零区间分别是[0, 2][0, 5],那么直接对[0, 7]积分,效果等价但计算量更小。

5. 验证与进阶:从卷积校验到LTI系统响应

5.1 用理论值做数值误差对比

判断数值卷积是否正确,最好的办法是找一个可解析的卷积做对照。取 (x(t)=u(t)-u(t-1)),(h(t)=u(t)-u(t-1)),理论卷积是三角脉冲:

[ y(t) = t,u(t) - 2(t-1)u(t-1) + (t-2)u(t-2) ]

数值上可以做如下误差分析:

dt = 0.005; t = -1:dt:3; x = double(t >= 0 & t < 1); h = double(t >= 0 & t < 1); y_num = conv(x, h) * dt; t_conv = t(1)*2 + (0:length(y_num)-1)*dt; y_theory = t_conv .* (t_conv >= 0) ... - 2*(t_conv - 1) .* (t_conv >= 1) ... + (t_conv - 2) .* (t_conv >= 2); max_err = max(abs(y_num - y_theory)); fprintf('最大绝对误差: %.4e\n', max_err);

这里的fprintf输出误差量级,当dt=0.005时误差通常在 (10^{-3}) 以下。把dt缩小一半再次运行,误差约缩小一半,说明数值卷积收敛到连续卷积的正确结果。t_conv的构造用了双起始时间相加,正好对上理论信号的自变量起点。

5.2 用lsim验证卷积结果

如果你的实验题目要求计算系统响应,除了conv之外还可以用lsim直接对传递函数仿真,两者结果可以互相印证。举例,对传递函数 (H(s)=1/(s+1)),单位阶跃输入下的响应是 (1-e^{-t})。

sys = tf(1, [1 1]); % H(s)=1/(s+1) t_sys = 0:0.01:5; u_sys = ones(size(t_sys)); % 单位阶跃 y_lsim = lsim(sys, u_sys, t_sys); y_th = 1 - exp(-t_sys); plot(t_sys, y_lsim, t_sys, y_th, '--');

逻辑说明:这里把连续系统用传递函数建模,lsim在给定输入和时间向量下仿真输出。与卷积公式相比,lsim内部有更稳定的数值积分算法,但原理一致。两个结果重叠说明你用conv构造的冲激响应和输入信号正确。

参数说明:tf(1, [1 1])的分子是1,分母是s+1,时域冲激响应是exp(-t)u(t)。若冲激响应更复杂,比如二阶系统 (1/(s^2+0.5s+1)),也可以先impulse(sys, t)得到冲激响应数组,再与该信号conv

5.3 一个可复用的通用测试函数

把验证逻辑封装成一个函数,以后做任意信号卷积都能直接调用:

function [y, t_conv] = contconv(x, t, h) dt = t(2) - t(1); y = conv(x, h) * dt; t_conv = t(1) + t(1) + (0:length(y)-1)*dt; end

参数约束是两个信号必须共用同一时间向量t。若信号定义在不同区间,先构造t覆盖并集,再分别在其上赋值。这个函数输出y_convt_conv,把画图时的对齐步骤收进去,不再需要每次重写时间轴偏移逻辑。

最后验证卷积的交换律性质:contconv(x, t, h)contconv(h, t, x)输出的数组完全相同,只有浮点舍入级别差异,这也是检查代码是否有边界越界的好办法。若结果不同,优先检查第一个信号末尾是否因为length(t)不对而多了一个不应有的零点。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询