MATLAB 数字信号处理常用函数整理:从信号生成、FFT 到数字滤波
处理一段 ADC 采样数据时,我们通常会遇到这些问题:怎样画出时域波形?怎样判断里面包含哪些频率?如何抑制高频干扰?设计好滤波器后,又怎样查看它的效果?
MATLAB 提供了许多相关函数。与其按字母顺序记忆,不如沿着实际处理流程学习:
生成或导入数据 → 预处理 → 时域与频域分析 → 设计并执行滤波 → 验证结果。
本文按照速查图中的12个类别,整理常用函数及其用途,并通过一个完整示例串起这条流程。内容面向数字信号处理入门,也适合做嵌入式采样数据分析时查阅。
使用说明:文中的函数包括 MATLAB 基础函数和 Signal Processing Toolbox 函数,部分功能需要相应工具箱。不同版本的接口可能存在差异,可用 doc 函数名 查看本机文档。本文是常用函数精选,并非 MATLAB 全部数字信号处理 API。
一、先分清三个基本量
在编写代码之前,先区分采样率、采样点数和信号频率:
| Fs | 采样率,每秒采集的样本数,单位 Hz | Fs = 1000 |
| N | 一段数据包含的采样点数 | N = 1000 |
| f0 | 信号的频率,单位 Hz | f0 = 50 |
| Ts | 采样周期,Ts = 1/Fs,单位 s | Ts = 0.001 |
例如,用1000 Hz采样率生成1000个采样点:
Fs = 1000;
N = 1000;
t = (0:N–1) / Fs;
x = sin(2*pi*50*t);
这里的 t 从0开始,最后一个点是0.999 s。采用 (0:N-1)/Fs 可以准确控制点数,避免把 0:1/Fs:1 产生的1001个点误当成1000个点。
对长度为 N 的数据做 N 点 FFT,频率网格间距为 Fs/N。它与观察时长、窗函数共同影响频谱分析;仅增加补零长度,并不会让原本无法区分的两个近邻频率真正变得可分辨。
二、12类常用函数速查
为了方便建立整体认识,我将 MATLAB 数字信号处理中常用的函数按用途整理成了下面这张速查图,涵盖信号生成、频谱分析、滤波器设计和重采样等12个类别。初学时可以用它梳理知识框架,后续处理采样数据时,也可以对照查找需要的函数。 
01 信号生成与序列
| sin / cos / exp | 正弦、余弦、指数序列 |
| zeros / ones / linspace | 零序列、常量、等间隔点 |
| rand / randn | 均匀分布 / 标准正态随机数 |
| square / sawtooth | 方波 / 锯齿波 |
| chirp / sinc | 扫频信号 / 归一化 sinc |
| rectpuls / tripuls / pulstran | 矩形脉冲 / 三角脉冲 / 脉冲列 |
例如 randn(size(t)) 可以生成与时间向量同尺寸的标准正态随机序列。写成 0.1*randn(size(t)) 时,噪声标准差为0.1。sinc(x) 使用归一化定义,即 sin(pi*x)/(pi*x),在零点取值为1。
02 数据导入与预处理
| readmatrix / load | 读取数值文件 / MAT 数据 |
| audioread / audiowrite | 读取 / 写入音频 |
| detrend | 去均值或去线性趋势 |
| mean / std / var | 均值 / 标准差 / 方差 |
| movmean / movmedian | 滑动平均 / 滑动中位数 |
| normalize / fillmissing | 数据标准化 / 缺失值填充 |
导入数据后,先检查有没有表头、缺失值、异常点和单位换算问题。detrend(x) 默认去除线性趋势,detrend(x,0) 去除均值。去直流也可以写成 x-mean(x),但如果直流分量本身就是测量目标,就不应随意删除。
03 时域运算与信号特征
| conv / cconv | 线性卷积 / 圆周卷积 |
| xcorr / xcov | 互相关或自相关 / 协方差序列 |
| diff / cumsum | 差分 / 累加 |
| rms / peak2peak | 有效值 / 峰峰值 |
| findpeaks / find | 峰值检测 / 查找满足条件的索引 |
| hilbert / envelope | 解析信号 / 包络提取 |
rms 适合计算采样信号的有效值,peak2peak 表示最大值与最小值之差。xcorr 可用于观察周期性或估计两路信号的时延,实际使用时应结合返回的 lags,并确认输入顺序对应的时延符号。
04 FFT 与频域变换
| fft / ifft | 快速傅里叶变换 / 逆变换 |
| fftshift / ifftshift | 零频居中 / 撤销移位 |
| abs / angle / unwrap | 幅值 / 相位 / 相位展开 |
| real / imag / conj | 实部 / 虚部 / 共轭 |
| nextpow2 | 求不小于输入值的 2 次幂指数 |
| dct / idct | 离散余弦变换 / 逆变换 |
fft 的输出通常是复数。abs(X) 得到模值,angle(X) 得到相位,但原始模值不能直接视为正确标定的单边幅度谱。对于幅值很小的频率分量,相位容易被噪声影响,解释时应结合幅度。
05 窗函数
| rectwin | 矩形窗 |
| hann / hamming | 汉宁窗 / 海明窗 |
| blackman / blackmanharris | 布莱克曼窗 / 布莱克曼–哈里斯窗 |
| kaiser / tukeywin | 凯泽窗 / 渐变余弦窗 |
| gausswin / triang / bartlett | 高斯窗 / 三角窗 / 巴特利特窗 |
| chebwin / flattopwin | 切比雪夫窗 / 平顶窗 |
截取有限长度的数据,相当于给信号加了一个窗。不同窗函数在主瓣宽度和旁瓣抑制之间有不同取舍。加窗后若要精确读取正弦幅值,需要考虑窗的相干增益;估计功率谱密度时则应采用相应的功率归一化方式。
06 FIR 滤波器设计
| fir1 | 窗函数法设计 FIR |
| fir2 | 任意幅频响应 FIR 设计 |
| firpm / firpmord | 等波纹设计 / 估计阶数 |
| firls | 最小二乘 FIR 设计 |
| kaiserord | 凯泽窗法阶数与参数估计 |
| designfilt | 按指标设计数字滤波器 |
fir1(64,0.2) 中,64是阶数,返回65个系数;0.2表示相对于奈奎斯特频率的归一化截止频率。常见对称线性相位 FIR 的群延迟为阶数的一半,64阶对应32个采样周期,这一点在实时控制中尤其需要注意。
07 IIR 滤波器设计
| butter / buttord | 巴特沃斯设计 / 估计阶数 |
| cheby1 / cheb1ord | 切比雪夫 I 型 / 估计阶数 |
| cheby2 / cheb2ord | 切比雪夫 II 型 / 估计阶数 |
| ellip / ellipord | 椭圆滤波器 / 估计阶数 |
| bilinear / impinvar | 双线性变换 / 冲激响应不变法 |
| tf2sos / zp2sos | 传递函数 / 零极点转二阶节 |
IIR 通常能用较低阶数实现较陡的幅频变化,但需要关注相位、稳定性和数值精度。高阶 IIR 采用高阶多项式系数直接实现时可能数值敏感,工程中常采用二阶节结构;设计时也应尽量采用适合数值计算的表示形式。
08 滤波执行与降噪
| filter | 按差分方程执行数字滤波 |
| filtfilt | 前后向零相位滤波,适合离线处理 |
| sosfilt | 二阶节级联滤波 |
| lowpass / highpass | 直接执行低通 / 高通滤波 |
| bandpass / bandstop | 直接执行带通 / 带阻滤波 |
| medfilt1 / sgolayfilt | 一维中值 / Savitzky–Golay 滤波 |
fir1、butter 主要用于设计系数,filter 才是把系数应用到数据上。filtfilt 执行前后向滤波,可获得零相位效果,但等效幅频响应也会改变,并存在边界处理问题,不能把它看成普通实时滤波器的无延迟替代品。
09 系统响应与稳定性
| freqz | 数字滤波器频率响应 |
| impz / stepz | 冲激响应 / 阶跃响应 |
| grpdelay / phasedelay | 群延迟 / 相位延迟 |
| zplane | 零极点图 |
| roots / tf2zp / zp2tf | 求根 / 系数与零极点形式互转 |
| isstable | 判断数字滤波器稳定性 |
fft(x) 回答“这段数据中有什么频率”,freqz(b,a) 回答“这个滤波器如何改变不同频率”。零极点图可以帮助理解系统特性;对因果有理系统,约去公因子后,BIBO稳定要求所有极点严格位于单位圆内。
10 功率谱与时频分析
| periodogram / pwelch | 周期图 / Welch 功率谱密度 |
| pburg / pyulear / pmusic | 参数谱估计 / MUSIC 伪谱 |
| spectrogram / stft / istft | 时频谱 / 短时傅里叶变换及逆变换 |
| cpsd / mscohere | 互功率谱密度 / 幅值平方相干性 |
| tfestimate | 由输入输出数据估计传递函数 |
| bandpower / snr / thd | 频带功率 / 信噪比 / 总谐波失真 |
pwelch 通过分段、加窗和平均估计功率谱密度,适合观察含噪信号的频率能量分布。spectrogram 适合查看频率成分随时间的变化,例如扫频信号。功率谱密度的单位通常为“信号单位的平方/Hz”,不能与幅度谱混为一谈。
11 重采样与多速率处理
| downsample | 每隔若干点抽取,不自动抗混叠 |
| upsample | 插零上采样,不自动去镜像 |
| decimate | 低通抗混叠滤波后降采样 |
| interp | 插值滤波后提高采样率 |
| resample | 按 p/q 比例重采样,含滤波 |
| upfirdn / interp1 | 插零–FIR–抽取 / 一维插值 |
downsample 只负责抽取数据,不自动完成抗混叠滤波。降采样前应限制信号带宽,或者使用包含相应滤波的 decimate、resample。interp1 是通用插值工具,不能简单认为它等同于带抗混叠处理的采样率转换。
12 绘图、查询与工具
| plot / stem | 连续曲线显示 / 离散序列图 |
| subplot / tiledlayout / nexttile | 多图布局 |
| semilogx / imagesc | 对数频率轴 / 矩阵伪彩图 |
| xlabel / ylabel / title / legend | 坐标标签 / 标题 / 图例 |
| grid / xlim / ylim | 网格 / 坐标范围 |
| help / doc / which / ver | 帮助 / 文档 / 函数定位 / 版本工具箱 |
plot 使用连线展示数据,stem 更适合强调离散采样点。即使画成连续曲线,输入的数据仍然可以是离散序列。遇到函数找不到时,可先用 which 函数名 和 ver 检查路径及工具箱,而不是直接判断为代码写错。
三、一个完整示例:保留50 Hz信号,抑制200 Hz干扰
下面构造一段同时包含50 Hz有效信号、200 Hz干扰和随机噪声的数据,再设计一个四阶低通滤波器,查看滤波前后的变化。
示例需要 Signal Processing Toolbox。代码展示的是算法流程,并非实际硬件测试结果。
clear;
clc;
close all;
rng(0); % 固定随机种子,便于复现
% 1. 生成信号
Fs = 1000; % 采样率,Hz
N = 2000; % 采样点数
t = (0:N–1)/Fs;
x = sin(2*pi*50*t) …
+ 0.5*sin(2*pi*200*t) …
+ 0.15*randn(size(t));
% 2. 设计低通滤波器
fc = 100; % 截止频率,Hz
Wn = fc/(Fs/2); % 归一化截止频率
[b,a] = butter(4,Wn,'low');
% 3. 执行因果滤波
y = filter(b,a,x);
% 4. 观察时域变化
figure;
subplot(2,1,1);
plot(t,x);
xlim([0 0.1]);
grid on;
xlabel('时间 / s');
ylabel('幅值');
title('滤波前');
subplot(2,1,2);
plot(t,y);
xlim([0 0.1]);
grid on;
xlabel('时间 / s');
ylabel('幅值');
title('滤波后:注意启动暂态与相位变化');
% 5. 查看滤波器自身的频率响应
figure;
freqz(b,a,1024,Fs);
% 6. 比较功率谱密度,跳过前200点启动暂态
win = hann(256);
[Pxx,f] = pwelch(x(201:end),win,128,1024,Fs);
[Pyy,~] = pwelch(y(201:end),win,128,1024,Fs);
figure;
plot(f,10*log10(Pxx+eps), …
f,10*log10(Pyy+eps));
grid on;
xlim([0 Fs/2]);
xlabel('频率 / Hz');
ylabel('功率谱密度 / dB(相对于1单位²/Hz)');
legend('滤波前','滤波后');
title('Welch 功率谱密度对比');
阅读结果时,重点检查三件事:
100 Hz截止频率不是一条“超过就全部删除”的边界。实际滤波器存在过渡带,四阶巴特沃斯滤波器在截止频率附近约为−3 dB,而不是幅值立即变成零。
这里跳过200点只是示例处理,实际暂态长度应根据滤波器响应判断。固定跳过一段数据并不是所有滤波器通用的规则。
四、FFT单边幅度谱怎样正确画?
如果目的是读取正弦信号的幅值,可以先用一个整周期、偶数长度的简单例子理解归一化过程:
Fs = 1000;
N = 1000; % 本例 N 为偶数
t = (0:N–1)/Fs;
x = 2*sin(2*pi*50*t);
X = fft(x);
A2 = abs(X)/N; % 双边幅度谱
A1 = A2(1:N/2+1); % 保留非负频率
A1(2:end–1) = 2*A1(2:end–1); % 直流与奈奎斯特点不翻倍
f = (0:N/2)*Fs/N;
figure;
plot(f,A1);
grid on;
xlabel('频率 / Hz');
ylabel('幅值');
xlim([0 150]);
在这个无噪声、整周期的例子中,50 Hz处幅值应接近2。若改成非整周期信号或加入窗函数,还要考虑频谱泄漏及窗增益;不能把这几行代码机械套用于所有幅值测量场景。
以上索引针对偶数 N。当 N 为奇数时,没有恰好位于奈奎斯特频率的最后一个频点,单边谱保留长度与翻倍范围应相应调整。
五、与嵌入式开发结合时,注意这几个区别
1. 离线滤波不等于实时滤波
在电脑上,整段数据通常已经存好,可以前后向处理;在单片机中,程序只能使用已经到达的样本。因此,filtfilt 适合某些离线分析,实时固件则需要可因果实现的算法,并考虑延迟。
2. 分块滤波必须保留状态
连续采集的数据分多块处理时,每块都从零状态开始会引入边界暂态。MATLAB 可以通过下面的方式传递状态:
zi = zeros(max(length(a),length(b))–1,1);
[y1,zf] = filter(b,a,x1,zi);
[y2,zf] = filter(b,a,x2,zf);
这里假设 x1、x2 是同一路连续信号的两个向量数据块。单片机实现同样需要保存历史输入、历史输出或滤波器内部状态。
3. 滤波越平滑,不一定越适合控制
滤波会改变动态响应。用于显示的波形可以接受较大的平滑延迟,而电源控制中的反馈滤波还要考虑相位滞后、控制带宽和稳定性。
4. 仿真系数还需要实现验证
把系数移植到STM32或DSP前,应核对差分方程、系数顺序、反馈项符号及是否要求 a(1)=1,同时检查浮点或定点精度、溢出和执行时间。MATLAB计算正确,并不代表换一种数据类型后仍有完全相同的结果。
六、初学时如何安排顺序?
建议先用少量函数完成一条完整流程,再逐步扩展:
| 看懂数据 | readmatrix、plot、stem、mean、rms | 导入采样值,观察波形和基本指标 |
| 看懂频率 | fft、abs、angle、hann | 理解幅度谱、相位和加窗 |
| 完成滤波 | butter、fir1、filter、freqz | 设计滤波器并解释处理效果 |
| 进一步分析 | pwelch、spectrogram、resample | 分析噪声、时变频率与采样率转换 |
每学一个函数,最好同时回答三个问题:输入是什么、输出代表什么、使用时有哪些条件。 这样遇到真实采样数据时,才能知道该选哪个函数,以及结果是否可信。
参考资料
- MathWorks:Signal Processing Toolbox 文档
- MathWorks:FFT
- MathWorks:FIR滤波器设计 fir1
- MathWorks:零相位滤波 filtfilt
- MathWorks:Welch功率谱密度 pwelch
- MathWorks:采样率转换 resample
网硕互联帮助中心



评论前必须登录!
注册