数字信号处理实验Matlab从入门到实战:5个核心实验+代码详解
你是不是刚接触数字信号处理(DSP)实验,看着Matlab界面一脸懵?或者想复习一下DSP实验的核心内容?今天这篇文章,我把自己当年做实验踩过的坑、总结的干货全掏出来,从最基础的信号生成到滤波处理,5个核心实验带你一步步上手,每个实验都有完整代码和详细解释,保证你看完就能跟着做!
实验1:基本信号的生成与可视化
DSP实验的第一步,肯定是先会生成常见的信号——毕竟后面的滤波、傅里叶变换都得基于这些基础信号来做。比如正弦波、方波、三角波,这些都是DSP里的“老朋友”了。怎么做呢?直接上Matlab代码!
% 实验1:基本信号生成与可视化
clear; clc; close all; % 每次实验前清内存、清命令行、关旧图(超级重要!避免之前的结果干扰)
% 1. 生成正弦波:参数是频率、采样率、时长
Fs = 1000; % 采样频率1kHz(每秒采1000个点)
t = 0:1/Fs:1-1/Fs; % 时间向量:从0到1秒,共1000个点
f1 = 5; % 正弦波频率5Hz
sin_wave = sin(2*pi*f1*t); % 正弦波公式:A*sin(2πft),这里振幅A=1
% 2. 生成方波和三角波
f2 =10; % 方波/三角波频率10Hz
square_wave = square(2*pi*f2*t); % 方波(默认振幅±1)
tri_wave = sawtooth(2*pi*f2*t,0.5); % 三角波:占空比0.5就是对称三角波
%3. 多信号叠加:模拟实际中的混合信号
mixed_wave = sin_wave +0.5*square_wave +0.3*tri_wave;
%4. 可视化:把所有信号画出来对比
subplot(4,1,1); plot(t, sin_wave); title('5Hz正弦波'); xlabel('时间(s)'); ylabel('幅度');
subplot(4,1,2); plot(t, square_wave); title('10Hz方波'); xlabel('时间(s)'); ylabel('幅度');
subplot(4,1,3); plot(t, tri_wave); title('10Hz三角波'); xlabel('时间(s)'); ylabel('幅度');
subplot(4,1,4); plot(t, mixed_wave); title('混合信号波形'); xlabel('时间(s)'); ylabel('幅度');
结果分析:正弦波是平滑的周期性曲线,方波是突然跳变的,三角波是线性上升下降的。混合后的波形把这三个信号的特征都揉在了一起——这就是我们后面要处理的“原材料”啦!
实验2:DFT与频谱分析
时域波形只能看到信号的变化趋势,但要找出里面藏着的频率成分,得靠频谱分析。离散傅里叶变换(DFT)就是把时域信号“翻过来”看频域的工具,Matlab里的fft函数直接就能实现!
% 实验2:DFT与频谱分析
clear; clc; close all;
% 复用实验1的混合信号(省得重新写一遍)
Fs=1000; t=0:1/Fs:1-1/Fs;
f1=5; sin_wave=sin(2*pi*f1*t); f2=10; square_wave=square(2*pi*f2*t); tri_wave=sawtooth(2*pi*f2*t,0.5);
mixed_wave=sin_wave +0.5*square_wave +0.3*tri_wave;
%1. 计算FFT(快速傅里叶变换,DFT的高效实现)
N = length(mixed_wave); % 信号长度
fft_wave = fft(mixed_wave); % 做FFT
mag_fft = abs(fft_wave)/N *2; % 幅度归一化:除以长度N,乘2是因为单边谱(只看正频率)
freq = Fs/2 * linspace(0,1,N/2+1); % 频率轴:从0到Fs/2(奈奎斯特频率)
%2. 画时域和频谱图对比
subplot(2,1,1); plot(t, mixed_wave); title('混合信号时域波形'); xlabel('时间(s)'); ylabel('幅度');
subplot(2,1,2); plot(freq, mag_fft(1:N/2+1)); title('混合信号单边频谱'); xlabel('频率(Hz)'); ylabel('幅度');
grid on; % 加网格线,方便看峰值位置
结果分析:频谱图里是不是在5Hz、10Hz、30Hz、50Hz这些地方有尖峰?这正好对应混合信号的成分:5Hz正弦波、10Hz方波(及其奇次谐波30Hz、50Hz)、10Hz三角波(谐波幅度衰减更快)。原来混合信号里藏着这么多“小秘密”,频谱图一下子就全暴露了!
实验3:FIR滤波器设计与信号滤波
既然知道了混合信号里的频率成分,那我们就能用滤波器把不需要的部分去掉。FIR滤波器是线性相位的,设计简单,适合初学者。比如我们想保留5Hz的正弦波,去掉10Hz以上的成分,怎么做?
% 实验3:FIR滤波器设计与滤波
clear; clc; close all;
% 还是复用混合信号
Fs=1000; t=0:1/Fs:1-1/Fs;
f1=5; sin_wave=sin(2*pi*f1*t); f2=10; square_wave=square(2*pi*f2*t); tri_wave=sawtooth(2*pi*f2*t,0.5);
mixed_wave=sin_wave +0.5*square_wave +0.3*tri_wave;
%1. 设计FIR低通滤波器
fc =8; % 截止频率8Hz(比5Hz高,比10Hz低,正好保留5Hz)
order =100; % 滤波器阶数:阶数越高,过渡带越窄,但计算越慢(100阶足够用)
b = fir1(order, fc/(Fs/2)); % fir1函数:归一化截止频率=fc/(Fs/2)
%2. 滤波:用filtfilt避免相位延迟(比filter函数更直观)
filtered_wave = filtfilt(b,1, mixed_wave);
%3. 对比滤波前后的时域和频谱
% 滤波前频谱
N=length(mixed_wave); fft_mixed=fft(mixed_wave); mag_mixed=abs(fft_mixed)/N*2; freq=Fs/2*linspace(0,1,N/2+1);
% 滤波后频谱
fft_filtered=fft(filtered_wave); mag_filtered=abs(fft_filtered)/N*2;
% 绘图
subplot(4,1,1); plot(t, mixed_wave); title('滤波前时域波形'); xlabel('时间(s)'); ylabel('幅度');
subplot(4,1,2); plot(freq, mag_mixed(1:N/2+1)); title('滤波前频谱'); xlabel('频率(Hz)'); ylabel('幅度');
subplot(4,1,3); plot(t, filtered_wave); title('滤波后时域波形'); xlabel('时间(s)'); ylabel('幅度');
subplot(4,1,4); plot(freq, mag_filtered(1:N/2+1)); title('滤波后频谱'); xlabel('频率(Hz)'); ylabel('幅度');
grid on;
结果分析:滤波后的波形是不是只剩下平滑的5Hz正弦波了?频谱图里10Hz以上的峰值全没了!这就是滤波器的魔力——把我们想要的信号“挑”出来,不需要的“扔掉”。
实验4:IIR滤波器设计与对比
FIR滤波器好是好,但阶数太高时计算量太大。IIR滤波器用更少的阶数就能达到同样的滤波效果,不过它是非线性相位的。我们来对比一下FIR和IIR的区别:
% 实验4:IIR滤波器设计与对比
clear; clc; close all;
% 复用混合信号
Fs=1000; t=0:1/Fs:1-1/Fs;
f1=5; sin_wave=sin(2*pi*f1*t); f2=10; square_wave=square(2*pi*f2*t); tri_wave=sawtooth(2*pi*f2*t,0.5);
mixed_wave=sin_wave +0.5*square_wave +0.3*tri_wave;
%1. 设计IIR低通滤波器(Butterworth型,最常用的IIR之一)
fc=8; order=4; % IIR只用4阶!比FIR的100阶少太多了
[b,a] = butter(order, fc/(Fs/2)); % butter函数设计Butterworth滤波器
%2. 滤波
iir_filtered = filtfilt(b,a, mixed_wave); % 同样用零相位滤波
%3. 对比FIR和IIR的结果
% 先做FIR滤波(复用实验3的参数)
fir_b = fir1(100, 8/(1000/2));
fir_filtered = filtfilt(fir_b,1, mixed_wave);
% 时域对比
subplot(2,1,1); plot(t, fir_filtered); title('FIR滤波后波形'); xlabel('时间(s)'); ylabel('幅度');
subplot(2,1,2); plot(t, iir_filtered); title('IIR滤波后波形'); xlabel('时间(s)'); ylabel('幅度');
% 频谱对比
fft_fir=fft(fir_filtered); mag_fir=abs(fft_fir)/N*2;
fft_iir=fft(iir_filtered); mag_iir=abs(fft_iir)/N*2;
figure;
subplot(2,1,1); plot(freq, mag_fir(1:N/2+1)); title('FIR滤波后频谱'); xlabel('Hz'); ylabel('幅度');
subplot(2,1,2); plot(freq, mag_iir(1:N/2+1)); title('IIR滤波后频谱'); xlabel('Hz'); ylabel('幅度');
结果分析:IIR用4阶就达到了FIR100阶的效果,是不是很惊艳?不过你要是仔细看相位(这里用filtfilt掩盖了),IIR是有相位偏移的。所以实际应用中,要是在意相位就选FIR,在意效率就选IIR——鱼和熊掌不可兼得啊!
实验5:卷积与相关分析
卷积和相关是DSP里的两个“孪生兄弟”:卷积用于计算系统响应,相关用于信号匹配。我们用带噪声的信号来直观感受一下:
% 实验5:卷积与相关分析
clear; clc; close all;
%1. 生成两个信号:A是纯正弦波,B是带噪声的正弦波
Fs=1000; t=0:1/Fs:1-1/Fs;
A = sin(2*pi*5*t); % 纯5Hz正弦波
B = sin(2*pi*5*t) +0.2*randn(size(t)); % 加高斯噪声(模拟实际中的干扰)
%2. 计算卷积
conv_AB = conv(A,B);
conv_t = linspace(0,2-2/Fs, length(conv_AB)); % 卷积后的时间轴(两个1秒信号卷积后是2秒)
%3. 计算互相关:找两个信号的相似性
corr_AB = xcorr(A,B);
corr_t = linspace(-1+1/Fs,1-1/Fs, length(corr_AB)); % 互相关的时间轴(从-1到1秒)
% 绘图
subplot(3,1,1); plot(t,A); title('信号A:纯5Hz正弦波'); xlabel('时间(s)'); ylabel('幅度');
subplot(3,1,2); plot(t,B); title('信号B:带噪声的5Hz正弦波'); xlabel('时间(s)'); ylabel('幅度');
subplot(3,1,3); plot(conv_t, conv_AB); title('A与B的卷积'); xlabel('时间(s)'); ylabel('幅度');
% 互相关绘图(重点看峰值位置)
figure;
subplot(2,1,1); plot(corr_t, corr_AB); title('A与B的互相关'); xlabel('时间差(s)'); ylabel('相关系数');
grid on;
% 找相关峰值
[max_corr, idx] = max(corr_AB);
peak_t = corr_t(idx);
hold on; plot(peak_t, max_corr, 'ro'); text(peak_t+0.1, max_corr, ['峰值在t=', num2str(peak_t,'%.3f'), 's']);
hold off;
结果分析:互相关图里的峰值在t=0附近,说明信号A和B在时间差为0时最相似——这就是噪声中找信号的关键!比如雷达探测目标、语音识别,都用到了相关分析的思想。
写在最后
五个核心实验做完,是不是对DSP实验和Matlab操作有了更清晰的认识?其实这些实验都是DSP的基础,后面还有小波变换、频谱估计等更深入的内容,但只要把这些基础吃透,进阶就会轻松很多。
当年我做这些实验的时候,经常因为采样率设置不对(比如Fs小于信号最高频率的两倍)导致频谱混叠,结果图全乱了——所以记住:奈奎斯特定理一定要遵守!还有滤波器的截止频率要归一化,这些细节都能让你的实验少走弯路。
希望这篇文章能帮到你,要是有问题可以去Matlab官方文档或者论坛找找答案(我当年就是这么过来的)。下次有机会再分享更深入的DSP实验内容,比如语音信号处理或者图像滤波,咱们下次见!

浙公网安备 33010602011771号