1. 信号与系统到底在讲什么:从一门课到一套工程思维
如果你翻过《信号与系统》的目录,大概率会看到连续时间信号、离散时间信号、傅里叶变换、拉普拉斯变换、Z变换、系统响应、卷积、采样定理这些词。很多人第一次学的时候会觉得这是一门纯数学课,公式推来推去,跟实际电路板上的电阻电容好像没什么关系。但真正做过硬件设计、写过MATLAB仿真、调过滤波器的人回头看,会发现这门课其实是在教你一套描述世界的方法:任何随时间变化的物理量都可以看作信号,任何对信号做出响应的物理过程都可以看作系统。
我最初接触这门课是在准备电子工程师相关的项目时。当时手头有一个传感器采集电路,输出信号里混了工频干扰,我第一反应是加电容滤波,但电容值怎么选、截止频率设在哪里、相位延迟会不会影响后续采样,这些问题靠试错效率很低。后来把采集链路抽象成“信号经过一个线性时不变系统”,用传递函数去算幅频响应,很多参数一下子就清楚了。这也是我后来反复跟新人说的一句话:信号与系统不是考试科目,它是你调试电路、做算法仿真、理解通信链路时最底层的语言。
这篇文章面向三类人:第一类是正在学这门课、想知道这些变换到底能干什么的学生;第二类是已经工作、但当年学得比较模糊、现在想补回来的电子工程师;第三类是做MATLAB仿真、图像处理、控制系统,需要把数学工具和工程实现接起来的人。我会从整体框架讲到具体细节,把连续和离散两条线拆开,把变换工具和实际电路、MATLAB代码对应起来,尽量让你看完之后能自己动手复现一个简单的系统分析流程。
提示:这篇文章不会替代教材,但会补上教材里经常缺失的“为什么这么定义”和“工程上怎么用”这两块内容。
2. 整体知识框架与学习路线拆解
2.1 为什么先学分连续时间再过渡到离散时间
大部分教材的编排逻辑是:先讲连续时间信号与系统,再讲离散时间信号与系统。这个顺序不是随便定的。连续时间模型更贴近物理世界的直觉,电容电压、电感电流、温度变化都是连续量,微积分工具也更容易建立“变化率”和“累积”的概念。等你对卷积、冲激响应、频率响应有了感觉,再切到离散域,会发现离散只是把积分换成求和、把微分方程换成差分方程,核心思想没有变。
但这里有一个常见的坑:很多人学连续部分时靠拉普拉斯变换硬算,学离散部分时靠Z变换硬算,最后脑子里只有变换对表格,没有系统概念。我的建议是,每学一个变换,都问自己三个问题:这个变换把什么问题变简单了?它的物理意义是什么?在MATLAB里怎么验证?比如傅里叶变换把卷积变成乘法,拉普拉斯变换把微分方程变成代数方程,Z变换把差分方程变成代数方程。你抓住这条主线,就不会被公式淹没。
2.2 信号分类与系统性质:看似简单,实则决定后续所有判断
信号可以按连续性、周期性、能量功率、确定性随机性来分类。系统性质里最重要的四条是线性、时不变、因果、稳定。这四条看起来是定义题,实际上决定了你后面能不能用卷积、能不能用传递函数、能不能做频域分析。
线性意味着叠加原理成立:两个输入分别作用后的输出之和,等于两个输入之和作用后的输出。时不变意味着系统参数不随时间变化,今天测的冲激响应和明天测的一样。因果意味着输出不依赖未来输入,这对实时系统是硬约束。稳定通常指有界输入产生有界输出,工程上对应系统不会自激振荡。
我见过不少人在做电源电路时忽略稳定性判断,结果环路相位裕度不够,负载一跳变就振荡。这其实就是系统稳定性问题。你如果把它抽象成一个反馈系统,用传递函数分析极点位置,很多问题在画板子之前就能发现。
2.3 变换工具的选择逻辑:不是越多越好,而是看问题类型
| 变换工具 | 适用信号类型 | 主要用途 | 工程对应场景 |
|---|---|---|---|
| 傅里叶级数 | 连续周期信号 | 频谱分解 | 谐波分析、工频干扰识别 |
| 傅里叶变换 | 连续非周期信号 | 频谱分析 | 滤波器设计、信号完整性 |
| 拉普拉斯变换 | 连续信号 | 微分方程求解、系统函数 | 模拟电路传递函数、控制系统 |
| Z变换 | 离散序列 | 差分方程求解、系统函数 | 数字滤波器、离散控制系统 |
| DFT/FFT | 有限长离散序列 | 数值频谱分析 | MATLAB仿真、频谱仪数据 |
这张表建议你贴在书桌前。每次遇到问题,先判断信号类型和你要解决的问题,再选工具。不要一上来就FFT,也不要所有系统都用拉普拉斯。比如你做STM32上的数字滤波,输入是ADC采样序列,那天然就是离散域问题,用Z变换和差分方程更直接。
2.4 MATLAB在信号与系统学习中的定位
MATLAB在这门课里的作用不是“帮你算题”,而是“帮你建立直觉”。很多变换的物理意义,你看公式看不出来,但画个图就明白了。比如卷积,教材上积分式很抽象,但你在MATLAB里用conv函数把两个序列卷一下,再画出来,立刻能理解“翻转、平移、相乘、求和”这个过程。
我常用的几个函数包括:fft做频谱分析,filter实现差分方程,freqz看数字滤波器频率响应,lsim做连续系统仿真,impulse和step看冲激响应和阶跃响应。你不需要一开始就学很多,先把这几个用熟,配合教材例题复现,效果比单纯推公式好得多。
注意:MATLAB版本更新较快,不同版本函数行为可能有细微差异。做教学复现时建议固定一个版本,避免因为版本差异导致结果对不上。
3. 核心细节解析与实操要点
3.1 连续时间信号的基本运算与MATLAB实现
连续时间信号的基本运算包括平移、反褶、尺度变换、微分、积分。这些运算在教材里是画图题,但在工程里对应的是实际操作。比如平移对应延迟,反褶对应时间反转,尺度变换对应采样率变化或时间压缩。
在MATLAB里,连续信号通常用足够小的步长来近似。比如你要画一个矩形脉冲,可以这样写:
t = -2:0.001:2; x = double(abs(t) <= 1); plot(t, x); axis([-2 2 -0.2 1.2]);这里步长0.001决定了时间分辨率。步长太大,脉冲边沿会失真;步长太小,计算量增加。一般取最高频率分量的10倍以上采样率比较稳妥。如果你后面要做傅里叶变换,步长还决定了频率分辨率。
微分和积分在MATLAB里可以用diff和cumsum近似,但要注意数值误差。对于教学演示够用,对于实际工程,建议用更精确的数值方法或直接推导解析式。
3.2 卷积的物理意义与手算加代码验证
卷积是信号与系统里最核心的运算之一。连续卷积公式是积分,离散卷积是求和。它的物理意义是:把输入信号分解成一系列冲激,每个冲激经过系统产生一个冲激响应,所有冲激响应叠加起来就是输出。
手算卷积的步骤是:翻转、平移、相乘、积分或求和。我建议你至少手算三个例子:矩形卷积矩形、指数卷积阶跃、两个短序列的离散卷积。手算一遍之后,再用MATLAB验证:
x = [1 2 3 2 1]; h = [1 1 1]; y = conv(x, h); stem(y);你会发现结果长度是length(x)+length(h)-1。这个细节在数字滤波里很重要,因为输出序列会比输入长,做实时处理时要考虑缓冲区管理。
实操心得:很多人做离散卷积时忘记翻转,直接滑动相乘,结果得到的是相关而不是卷积。相关和卷积在形式上只差一个翻转,但物理意义完全不同。卷积描述系统响应,相关描述相似性度量。
3.3 傅里叶变换的工程直觉:频谱到底在看什么
傅里叶变换把时域信号变成频域表示。工程上,频谱告诉你信号里有哪些频率成分,每个成分的幅度和相位是多少。这对滤波器设计、干扰分析、调制解调都是基础。
举个例子,你有一个50Hz工频干扰叠加在传感器信号上。时域上看,波形有点抖动;频域上看,50Hz处有一个明显的尖峰。你要滤掉它,就可以设计一个陷波滤波器,中心频率设在50Hz。如果没有频谱分析,你只能靠试电容值,效率很低。
在MATLAB里做频谱分析:
fs = 1000; t = 0:1/fs:1-1/fs; x = sin(2*pi*50*t) + 0.5*sin(2*pi*120*t); X = fft(x); f = (0:length(X)-1)*fs/length(X); plot(f, abs(X)); xlim([0 fs/2]);注意这里只画到fs/2,因为实信号的频谱对称,后半段是镜像。频率分辨率是fs/N,N是采样点数。你要提高分辨率,要么增加采样时间,要么增加采样点数。
3.4 拉普拉斯变换与模拟电路传递函数
拉普拉斯变换把微分方程变成代数方程,是分析模拟电路的核心工具。一个RC低通滤波器的传递函数是:
H(s) = 1 / (1 + sRC)
截止频率是1/(2πRC)。你在选电阻电容时,就是根据这个公式反推。比如要截止频率1kHz,选R=1kΩ,则C≈159nF,取标准值150nF或220nF再验算。
在MATLAB里可以画波特图:
R = 1000; C = 159e-9; H = tf([1], [R*C 1]); bode(H); grid on;你会看到幅频特性在截止频率处下降3dB,相频特性在截止频率处滞后45度。这些数值在调试电路时非常有用,因为你可以直接判断信号经过这个电路后衰减了多少、延迟了多少。
3.5 Z变换与数字滤波器差分方程
Z变换在离散域的地位相当于拉普拉斯变换在连续域。一个一阶数字低通滤波器的差分方程可以写成:
y[n] = α x[n] + (1-α) y[n-1]
其中α是滤波系数,决定截止频率。这个方程在MATLAB里用filter实现:
alpha = 0.1; b = [alpha]; a = [1, -(1-alpha)]; x = randn(1, 1000); y = filter(b, a, x); plot(x); hold on; plot(y);你会发现输出比输入平滑,高频噪声被抑制。α越小,截止频率越低,输出越平滑,但延迟也越大。这个权衡在嵌入式开发里很常见,你需要根据采样率和信号带宽来选α。
注意:数字滤波器设计时要注意系数量化误差。定点处理器上,α的精度不够可能导致滤波器性能下降甚至不稳定。建议先用浮点仿真验证,再转定点。
4. 实操过程与核心环节实现
4.1 从零搭建一个信号采集与滤波仿真链路
假设你要做一个温度采集系统,传感器输出0到5V,信号带宽10Hz,但环境有50Hz工频干扰。你的目标是设计一个抗混叠滤波器,然后采样,再在数字域进一步滤波。
第一步,确定采样率。根据采样定理,采样率至少是信号最高频率的2倍。但工程上通常取5到10倍。信号带宽10Hz,干扰50Hz,你希望保留10Hz以内的信号,滤掉50Hz。如果采样率取200Hz,那么50Hz在数字域对应0.25π弧度,可以用数字滤波器抑制。
第二步,设计模拟抗混叠滤波器。截止频率设在略高于10Hz,比如20Hz。用RC低通:
R = 10kΩ,C = 1/(2π2010000) ≈ 796nF,取820nF。
第三步,在MATLAB里仿真整个链路:
fs = 200; t = 0:1/fs:2-1/fs; signal = sin(2*pi*5*t); interference = 0.5*sin(2*pi*50*t); x = signal + interference; % 模拟RC低通 R = 10000; C = 820e-9; fc = 1/(2*pi*R*C); [b,a] = butter(1, fc/(fs/2)); x_filtered = filter(b, a, x); % 数字滤波进一步抑制50Hz [b2,a2] = butter(2, 15/(fs/2)); y = filter(b2, a2, x_filtered); plot(t, x, t, y); legend('原始', '滤波后');这个流程覆盖了从模拟到数字的完整链路。你可以调整参数,观察滤波效果和相位延迟。
4.2 用MATLAB做离散时间系统响应分析
离散时间系统的核心是差分方程和Z变换。假设系统差分方程为:
y[n] - 0.8y[n-1] = x[n]
对应的系统函数是:
H(z) = 1 / (1 - 0.8z^-1)
极点在z=0.8,单位圆内,系统稳定。冲激响应是0.8^n u[n],指数衰减。
在MATLAB里验证:
b = [1]; a = [1, -0.8]; impulse_response = filter(b, a, [1, zeros(1, 49)]); stem(0:49, impulse_response);你会看到冲激响应从1开始,每次乘以0.8。这个系统对阶跃输入的响应会趋向1/(1-0.8)=5。你可以用step响应验证:
step_response = filter(b, a, ones(1, 50)); plot(0:49, step_response);这些基础分析在数字控制系统、通信接收机、音频处理里反复出现。你把这几个例子跑通,后面遇到复杂系统就是组合和扩展。
4.3 采样定理的工程验证与混叠现象复现
采样定理说采样率必须大于信号最高频率的2倍,否则会发生混叠。混叠的后果是高频信号被错误地映射到低频。这个现象在工程里很常见,比如你采样率不够,50Hz干扰可能混叠到10Hz,和有用信号重叠,滤都滤不掉。
在MATLAB里复现混叠:
fs = 60; t = 0:1/fs:1-1/fs; f1 = 10; f2 = 50; x1 = sin(2*pi*f1*t); x2 = sin(2*pi*f2*t); plot(t, x1, t, x2); legend('10Hz', '50Hz');当fs=60Hz时,50Hz信号的混叠频率是|50-60|=10Hz,和有用信号完全重叠。你采样后无法区分。这就是为什么抗混叠滤波器必须在采样之前,而且截止频率要低于fs/2。
实操心得:做ADC采样时,不要只看信号带宽,还要看干扰频率。如果干扰频率接近采样率整数倍,混叠后可能落在低频段。选采样率时尽量避开干扰频率的整数倍关系。
4.4 从传递函数到电路参数的换算过程
传递函数和实际电路之间需要换算。以二阶低通滤波器为例,传递函数标准形式:
H(s) = ωn^2 / (s^2 + 2ζωn s + ωn^2)
其中ωn是自然频率,ζ是阻尼比。你要设计截止频率1kHz、阻尼比0.707的巴特沃斯滤波器,则ωn=2π*1000≈6283 rad/s。
用Sallen-Key拓扑实现,选R1=R2=R,C1=C2=C,则ωn=1/(RC),ζ=1.5(对于单位增益Sallen-Key,ζ=1.5不一定对,这里仅作示例)。实际设计时要用标准公式:
R = 1/(ωn C),然后根据ζ调整电容比例。
在MATLAB里可以用butter函数直接得到系数,再换算成电路参数。这个过程在板级模拟电路设计里很常见,尤其是做传感器信号调理时。
5. 常见问题与排查技巧实录
5.1 卷积结果长度不对或形状异常
这是新手最常见的问题。离散卷积结果长度是N+M-1,如果你用conv函数发现长度不对,先检查输入是不是向量。如果输入是矩阵,conv会按列处理,结果可能不是你想要的。另外,卷积前要确认两个序列的时间起点,如果起点不是0,结果的时间轴要相应平移。
排查步骤:
- 检查输入序列长度和维度。
- 确认是否需要翻转其中一个序列。
- 用简单例子手算验证,比如[1 2]卷积[1 1]结果是[1 3 2]。
- 画图检查结果形状是否符合预期。
5.2 FFT频谱峰值位置不对
FFT峰值位置对应频率是k*fs/N,k是峰值索引。如果你发现峰值不在预期频率,先检查fs和N是否设置正确。另外,如果信号不是整周期采样,会发生频谱泄漏,峰值会扩散。解决方法是用窗函数,比如汉宁窗或汉明窗。
排查步骤:
- 确认fs和N。
- 检查信号频率是否在0到fs/2之间。
- 加窗后再FFT,观察峰值是否集中。
- 如果做功率谱,注意归一化。
5.3 数字滤波器输出振荡或不稳定
数字滤波器不稳定通常是因为极点跑到单位圆外。检查差分方程系数,确保a的根都在单位圆内。另外,系数量化误差也可能导致不稳定,尤其是高阶滤波器。建议用二阶节级联实现高阶滤波器,降低量化敏感度。
排查步骤:
- 用roots(a)检查极点位置。
- 用freqz看频率响应是否正常。
- 如果定点实现,检查系数量化位宽。
- 降低滤波器阶数或改用级联结构。
5.4 模拟电路滤波效果与仿真不符
仿真用的是理想元件,实际电路有寄生参数、容差、温度漂移。比如电容实际值可能偏差20%,电阻偏差5%,截止频率就会偏移。另外,运放的带宽和压摆率也会影响高频响应。
排查步骤:
- 用实际元件值重新仿真。
- 检查PCB布局,避免寄生电容耦合。
- 测量实际频率响应,和仿真对比。
- 如果偏差大,考虑用可调电阻或电容微调。
5.5 MATLAB版本差异导致函数行为变化
MATLAB不同版本对某些函数的默认行为可能不同,比如fft的归一化、filter的初始条件、tf的采样时间设置。如果你复现教材例子结果对不上,先检查版本。
排查步骤:
- 用help或doc查看当前版本函数说明。
- 固定随机数种子,确保结果可重复。
- 如果做教学,建议注明MATLAB版本。
- 关键步骤手动实现,减少对工具箱的依赖。
| 问题现象 | 可能原因 | 排查方法 | 解决建议 |
|---|---|---|---|
| 卷积长度不对 | 输入维度或起点错误 | 检查size和t轴 | 手动验证简单例子 |
| FFT峰值偏移 | fs或N设置错误 | 检查采样参数 | 加窗抑制泄漏 |
| 滤波器振荡 | 极点在外或量化误差 | roots(a)检查 | 级联二阶节 |
| 电路滤波偏差 | 元件容差或寄生参数 | 实测对比仿真 | 用可调元件 |
| 版本结果不一致 | 函数默认行为变化 | 查看版本文档 | 固定版本或手动实现 |
6. 学习资源与工具链的务实建议
6.1 教材选择与配套习题的处理方式
《信号与系统》教材很多,胡光锐版本是很多高校采用的。教材的作用是建立体系,但不要指望一遍看懂。我的建议是:第一遍快速过,知道每章讲什么;第二遍配合MATLAB复现例题;第三遍做习题,重点做那些能对应实际工程的题。
习题不要只求答案,要问自己:这个题对应什么工程场景?如果参数变了会怎样?有没有更简单的解法?比如求卷积,除了积分,能不能用变换域做?能不能用MATLAB验证?
6.2 MATLAB工具箱的取舍与替代方案
MATLAB有信号处理工具箱、控制系统工具箱、通信工具箱等。学习阶段不需要全部安装,核心函数在基础MATLAB里就有。fft、filter、conv、tf、bode这些足够覆盖大部分内容。如果你没有工具箱,可以用Python的NumPy和SciPy替代,核心算法是一样的。
我个人的习惯是:教学演示用MATLAB,因为语法直观、绘图方便;实际项目如果涉及部署,会考虑Python或C。但无论用什么工具,信号与系统的核心概念不变。
6.3 从仿真到硬件的过渡注意事项
仿真通过不代表硬件能跑。从仿真到硬件,要过几道关:元件容差、噪声、寄生参数、电源波动、温度漂移。我的经验是,仿真时留足裕量,比如滤波器截止频率留20%余量,增益留3dB余量。PCB布局时,模拟部分和数字部分分开,地平面完整,敏感信号远离时钟线。
另外,测试时先用信号发生器注入已知信号,逐级测量,确认每一级都正常。不要一上来就接传感器,否则出了问题很难定位。
6.4 持续练习的路径与项目建议
学完基础后,建议做几个小项目巩固:
- 用MATLAB设计一个FIR低通滤波器,并生成C代码在单片机上实现。
- 搭一个RC低通电路,用示波器测幅频响应,和仿真对比。
- 用ADC采集音频信号,做FFT显示频谱。
- 设计一个简单的PID控制系统,用离散系统分析稳定性。
这些项目不需要很复杂,但能把信号与系统的概念串起来。你做完之后,再看教材,会发现很多之前不理解的地方突然通了。
我个人在实际操作中的体会是,信号与系统这门课的价值不在考试,而在你面对一个电路或算法时,能快速判断用什么工具、看什么指标、调什么参数。这种直觉需要反复练习,但一旦建立起来,后面学通信、控制、图像处理都会轻松很多。最后再分享一个小技巧:每次遇到新系统,先画框图,再写方程,再选变换,最后用MATLAB验证。这个流程走顺了,大部分问题都能拆解清楚。