使用窗函数方法设计FIR滤波器与MATLAB代码分析

一,写在前面的话.

学习了以下链接,然后写出了MATLAB代码,在本文末,大家可以随便下载代码,进行尝试,我代码调试正常,可使用。

1. 如果你是初学者,建议你看一下这个链接https://blog.csdn.net/zhoufan900428/article/details/8969470

自学什么是窗函数,什么是滤波器,为啥要用窗函数,怎么计算一些值,怎么根据这些值选择窗函数。

2. 如果你明白了上述内容,但还不能单独写代码进行分析,推荐你看这个链接:https://www.cnblogs.com/xhslovecx/p/10196851.html

自学怎么计算,然后选好窗函数,就设计,写公式。在那文章末尾他给了MATLAB采用FIR I型设计20Hz以下的低通滤波器的代码。

3. 如果你明白了以上内容,那么就请看下去吧:

代码都上传到下面了,随便用,但如果你要发表的话,请改一改,因为我的论文已经入库了,你要是直接抄,老师可能从查重率上把你毙了,改个参数名啥的可以,写论文很少发代码的

二,简单介绍

    我们知道IIR(无限脉冲响应)数字滤波器的设计方法是利用模拟滤波器成熟的理论及设计图表进行的,因而保留了一些典型模拟滤波器优良的幅度特性,但设计中只考虑到了幅度特性,没考虑到相位特性,所设计的滤波器相位特性一般是非线性的。而FIR(有限脉冲响应)滤波器在保证幅度特性满足技术要求的同时,比较容易做到有严格的线性相位特性。

    FIR滤波器分为四种:LP(低通滤波器),HP(高通滤波器),BP(带通滤波器),BS(带阻滤波器)。

    它们的公式我就不写了,但是需要知道。还要知道什么是线性相位FIR滤波器幅度特性和零点分布特点。

    我们熟知的窗函数有:三角窗,矩形窗,汉明窗,汉宁窗,布莱克曼窗,

    我们若是分析特性,则需要知道什么是主瓣,旁瓣,若是选择窗函数,则需要计算窗长度N,然后选择合适的阻带衰减(dB),阻带衰减不能比窗长度小。

   然后写代码的时候,要手写时域表达式(这个叫写窗)。我把它们的公式写在下面:大家可以直接复制粘贴。

   我直接贴了四个窗函数MATLAB的代码,请大家先参悟一下,再看加上滤波器的代码。

第一个是矩形窗:

n=0:1:14;
wR=ones(1,15);% 编写矩形窗
hd=sin(0.25*pi*(n-7+eps))./(pi*(n-7+eps));%读入hd(n)函数
h1=hd.*wR;%计算h(n)
N=64; 
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid on
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('幅度曲线和相频曲线(n=15)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,3);
plot(w,fftshift(unwrap(phase(H1))));%画相频曲线 
grid
xlabel('w/rad')
clear all;
n=0:1:32;
wR=ones(1,33);% 编写矩形窗
hd=sin(0.25*pi*(n-16+eps))./(pi*(n-16+eps));%读入hd(n)函数
h1=hd.*wR;%计算h(n)
N=64;
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,2);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid on
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('幅度曲线和相频曲线(n=15)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,4);
plot(w,fftshift(unwrap(phase(H1))));%画相频曲线 
grid
xlabel('w/rad')

第二个是汉宁窗

clear all;
n=0:1:14;
wH=0.5*(1-cos(2*pi/14*n));% 编写汉宁窗
hd=sin(0.25*pi*(n-7+eps))./(pi*(n-7+eps));%读入hd(n)函数
h1=hd.*wH;%计算h(n)
N=64;
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,1);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB');
title('幅度曲线和相频曲线(n=15)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,3);
plot(w,fftshift(unwrap(phase(H1))));%画相频曲线
grid
xlabel('w/rad')
n=0:1:32;
wH=0.5*(1-cos(2*pi/32*n));% 编写汉宁窗
hd=sin(0.25*pi*(n-16+eps))./(pi*(n-16+eps));%读入hd(n)函数
h1=hd.*wH;%计算h(n)
N=64;
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,2);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('幅度曲线和相频曲线(n=33)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,4);plot(w,fftshift(unwrap(phase(H1))));%画相频曲线
grid
xlabel('w/rad')

第三个是汉明窗

clear all;
n=0:1:14;
wH=0.54-0.46*cos(2*pi*n/(14+eps));% 编写海明窗
hd=sin(0.25*pi*(n-7+eps))./(pi*(n-7+eps));%读入hd(n)函数
h1=hd.*wH;%计算h(n)
N=64;
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,1);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB');
title('幅度曲线和相频曲线(n=15)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,3);
plot(w,fftshift(unwrap(phase(H1))));%画相频曲线
grid
xlabel('w/rad')
n=0:1:32;
wH=0.5*(1-cos(2*pi/32*n));% 编写汉宁窗
hd=sin(0.25*pi*(n-16+eps))./(pi*(n-16+eps));%读入hd(n)函数
h1=hd.*wH;%计算h(n)
N=64;
H1=fft(h1,N);%调用子程序计算H(k)
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,2);
plot(w,fftshift(20*log10((abs(H1)))));%画幅度曲线
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('幅度曲线和相频曲线(n=33)');
n=0:N-1;w=2*pi/64*n;subplot(2,2,1);
subplot(2,2,4);plot(w,fftshift(unwrap(phase(H1))));%画相频曲线
grid
xlabel('w/rad')

第四个是布莱克曼窗

n=0:14
wB=0.42-0.5*cos(2*pi/(14+eps)*n)+0.08*cos(4*pi/(14+eps)*n)
hd=sin(0.25*pi*(n-7+eps))./(pi*(n-7+eps))
h1=hd.*wB
H1=fft(h1,64)
n=0:63
w=2*pi*n/64
subplot(2,2,1)
plot(w,fftshift(20*log10((abs(H1)))))
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('N=15幅度曲线')
subplot(2,2,3)
plot(w,unwrap(fftshift(phase(H1))))
grid
xlabel('w/rad')
title('N=15相频曲线')
clear all
n=0:32
wB=0.42-0.5*cos(2*pi/(32+eps)*n)+0.08*cos(4*pi/(32+eps)*n)
hd=sin(0.25*pi*(n-16+eps))./(pi*(n-16+eps))
h1=hd.*wB
H1=fft(h1,64)
n=0:63
w=2*pi*n/64
subplot(2,2,2)
plot(w,fftshift(20*log10((abs(H1)))))
grid
xlabel('w/rad')
ylabel('20lg|H(jw)|/dB')
title('N=33幅度曲线')
subplot(2,2,4)
plot(w,unwrap(fftshift(phase(H1))))
grid
xlabel('w/rad')
title('N=33相频曲线')

希望大家结合公式与窗函数特性加上代码,参悟一下。

好了现在我们开始设计FIR滤波器,至于书面的计算过程我就不写了,又不懂得请参考本文“写在前面的话”的第一个链接的内容。

第一个例子,用汉明窗设计一个低通滤波器,Wp=0.2π, Ws=0.4π, Ap=0.25dB, As=50dB

%%%%%Write by Han%%%%%这是实时脚本文件%%%%%
close all;
clc
Wp=0.2*pi;
Ws=0.4*pi;
tr_width=Ws-Wp;                         %Transition zone width
N=ceil(6.6*pi/tr_width)+1               %Filter length
n=0:1:N-1;
Wc=(Ws+Wp)/2;                           %Cutoff frequency of ideal low-pass filter          
hd = ideal_lp(Wc,N);                      %Unit impulse response of an ideal low-pass filter
w_ham=0.54-0.46*cos(2*pi*n/(14+eps));    % Writing a haming window                   
h=hd.*w_ham;                             %Truncated to the actual unit impulse response
[db,mag,pha,w]=freqz_m4(h,[1]);          %Calculate the amplitude response of the actual filter
delta_w=2*pi/1000;
Ap=-(min(db(1:1:Wp/delta_w+1)))          %Actual passband ripple
As=-round(max(db(Ws/delta_w+1:1:501)))   %Actual stop band ripple
subplot(221)
stem(n,hd)                               %Matchstick figure
title('Ideal unit impulse response: hd(n)')
subplot(222)
stem(n,w_ham)
title('Hamming window: w(n)')
subplot(223)
stem(n,h)
title('Actual unit impulse response: h(n)')
subplot(224)
plot(w/pi,db)
title('Amplitude response: (dB)')
axis([0,1,-100,10])
%2 Custom functions used by this program
% One is the "freqz_m4.m"
% Another is the "ideal_lp.m"

我在这用了两个自定义函数,所以大家还需要新建两个.m文件,一个是“freqz_m4.m”文件名与函数名需要保持一致。

function[db,mag,pha,w]=freqz_m4(b,a) 
[H,w]=freqz(b,a,1000,'whole');
H=(H(1:1:501));
w=(w(1:1:501));
mag=abs(H);
db=20*log10((mag+eps)/max(mag));
pha=angle(H);
end

另一个是“ideal_lp.m”

function hd=ideal_lp(Wc,N)
alpha= (N-1)/2;
n=0:1:N-1;
m=n-alpha+eps;
hd=sin (Wc*m)./(pi*m);
end

注意要把这三个文件保存在一个英文命名的文件夹中,不然MATLAB可能会出现.m文件打不开,或者找不到路径的问题。这个问题可参考(https://blog.csdn.net/Smile_h_ahaha/article/details/92477206)进行修正。代码是没问题的。

然后生成了以下图像:

第二个,我们设计个使用汉宁窗的高通滤波器,设计参数是:Wp=0.6 π,Ws=0.4 π,,Ap=0.25dB,As=40dB

%%%%%%%%%%%%%%% Write by Han %%%%%%%%%这是实时脚本文件%%%%%%%%%%%%
Wp=0.6*pi; Ws=0.4*pi;
tr_width=Wp-Ws;                         %Transition zone width
N=ceil (6.2*pi/tr_width) +1             %Filter length
n=0:1:N-1;
Wc= (Ws+Wp) /2;                         %The cut-off frequency of the ideal high-pass filter        
hd=ideal_hp2(Wc,N);                      %Unit impulse response of an ideal high-pass filter
w_han=0.5*(1-cos(2*pi/14*n));            % Writing Hanning window
h=hd.*w_han;                            %Truncated to the actual unit impulse response
[db,mag,pha,w]=freqz_m4 (h,[1]);         %Calculate the amplitude response of the actual filter
delta_w=2*pi/1000;
Ap=-(min(db(Wp/delta_w+1:1:500)))        %Actual passband ripple
As=-round(max(db(1:1:Wp/delta_w+1)))     %Actual stop band ripple
subplot(221)
stem(n,hd)                               %Matchstick figure
title('Ideal unit impulse response: hd(n)')
subplot(222)
stem(n,w_han)
title('Hanning: w(n)')
subplot(223)
stem(n,h)
title('Actual unit impulse response: h(n)')
subplot(224)
plot(w/pi,db)
title('FIR digital high-pass filter amplitude response: (dB)')
axis([0,1,-100,10])

这也用到两个自定义函数,

%%%%%%%%%%%%% ideal_hp2.m %%%%%%%%%%%%%
function hd=ideal_hp2(Wc,N)
alpha= (N-1)/2;
n=0:1:N-1;
m=n-alpha+eps;
hd=(sin (pi*m)-sin(Wc*m))./(pi*m);
%%%%%%%%%%%请再新建一个.m文件放以下部分%%%%%
function[db,mag,pha,w]=freqz_m4(b,a) 
[H,w]=freqz(b,a,1000,'whole');
H=(H(1:1:501));
w=(w(1:1:501));
mag=abs(H);
db=20*log10((mag+eps)/max(mag));
pha=angle(H);
end

第三个,我们用汉宁窗设计一个bandstop(带阻) FIR滤波器,设计参数是:

%%%%%%%%%%%%%%%%%% Write by Han %%%%%%%%%%这是实时脚本文件%%%%%%%%%%%%
Wpl=0.2*pi; Wph=0.8*pi; Wsl=0.4*pi; Wsh=0.6*pi;
tr_width=min((Wsl-Wpl),(Wph-Wsh));      
N=ceil (6.2*pi/tr_width)                 
n=0:1:N-1;
Wcl= (Wsl+Wpl) /2;                      %Lower cutoff frequency of ideal band stop filter  
Wch= (Wsh+Wph) /2;                      %Upper cutoff frequency of ideal band stop filter           
hd=ideal_bs(Wcl,Wch,N);                 %Unit impulse response of an ideal band stop filter
w_hann= 0.5*(1-cos(2*pi/14*n));                  %Hanning window
h=hd.*w_hann;                          %Truncated to the actual unit impulse response
[db,mag,pha,w]=freqz_m4 (h,[1]);        %Calculate the amplitude response of the actual filter
delta_w=2*pi/1000;
Ap=-(min(db(1:1:Wpl/delta_w+1)))          %Actual passband ripple
As=-round(max(db(Wsl/delta_w+1:1:Wsh/delta_w+1)))      %Actual stop band ripple
subplot(221)
stem(n,hd)                                %Matchstick figure
title('Ideal: hd(n)')
subplot(222)
stem(n,w_hann)
title('hanning w(n)')
subplot(223)
stem(n,h)
title('Real h(n)')
subplot(224)
plot(w/pi,db)
title('FIRHanning window digital band rejection filter amplitude response(dB)')
axis([0,1,-100,10])
%%%%%%%%%%%%%%%%%%%%% ideal_bs.m %%%%%%%%新建一个.m文件%%%%%%%%%%%%

function hd=ideal_bs(Wcl,Wch,N)
alpha= (N-1) /2; n=0:1:N-1;
m=n-alpha+eps;
hd=(sin (Wcl*m) + sin(pi*m)-sin(Wch*m) ) ./(pi*m);
end
%%%%%%%%%%%%%%%%%%%%freqz_m4.m%%%%%%新建一个.m文件%%%%%%%%%%%
function[db,mag,pha,w]=freqz_m4(b,a) 
[H,w]=freqz(b,a,1000,'whole');
H=(H(1:1:501));
w=(w(1:1:501));
mag=abs(H);
db=20*log10((mag+eps)/max(mag));
pha=angle(H);
end

其他的大家能参悟到这,其他的估计也就触类旁通了吧,学海无涯,兴趣作舟,祝大家好运!

  • 87
    点赞
  • 528
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
### 回答1: 在MATLAB中,可以使用窗函数法来设计FIR滤波器。具体步骤如下: 1. 确定滤波器的阶数和截止频率。 2. 选择一个窗函数,如矩形窗、汉宁窗、汉明窗等。 3. 根据所选窗函数的特点,计算出窗函数的系数。 4. 根据所选窗函数的系数和滤波器的阶数,计算出FIR滤波器的系数。 5. 使用fir1函数生成FIR滤波器。 例如,以下代码使用汉宁窗设计一个10阶低通滤波器,截止频率为.2: N = 10; % 滤波器阶数 fc = .2; % 截止频率 win = hann(N+1); % 汉宁窗 b = fir1(N, fc, 'low', win); % 计算FIR滤波器系数 freqz(b, 1); % 绘制滤波器的频率响应图 运行以上代码,即可得到一个低通滤波器的频率响应图。 ### 回答2: Matlab提供几种窗函数方法设计FIR滤波器FIR(Finite Impulse Response,有限冲激响应)滤波器是一种常见的数字滤波器,在数字信号处理中应用广泛。 窗函数法是一种常见的FIR滤波器设计方法窗函数是一种用于限制信号在一定时间范围内进行截断的形状函数,它在FIR滤波器设计中起到关键作用。窗函数法的基本思路是将窗函数与理想滤波器相乘,生成一个有限长的滤波器响应。 下面介绍一些常见的窗函数: 1.矩形窗函数(Rectangle Window),是最基本的窗函数,其功效是在频率域内限定一个矩形窗口; 2.汉明窗函数(Hamming Window),比矩形窗函数衰减平缓,滤波效果相对较好; 3.黑曼海尔窗函数(Blackman-Harris Window),比汉明窗函数的衰减更加平滑,滤波效果更好; 4.卡门窗函数(Kaiser Window),是一种可调整的窗函数,可以通过调整beta参数改变窗口的平滑度和滚降的速度。 接下来,我们将通过matlab的filter函数设计一个低通FIR滤波器,来详细介绍窗函数法的设计过程。下面是程序代码: %% 设计FIR滤波器 Fs = 2000; % 采样频率 fc = 200; % 截止频率 n = 50; % 滤波器阶数 % 构造单位冲激响应 h = zeros(1, n+1); for i = 1:n+1 if (i-1 == (n+1)/2) h(i) = 2*pi*fc/Fs; % 理想低通滤波器的单位冲激响应 else h(i) = sin(2*pi*fc*(i-1-(n+1)/2)/Fs)/(i-1-(n+1)/2); % 理想低通滤波器的单位冲激响应 end end % 构造窗函数 w = hamming(n+1); % 使用Hamming窗函数 h = h .* w'; % 对单位冲激响应进行窗函数截断 % 画出频率响应 [H,f] = freqz(h, 1); figure, plot(f, 20*log10(abs(H))), grid on; xlabel('Frequency / Hz'), ylabel('Magnitude / dB'); title('Frequency Response of FIR Filter'); % 过滤信号 t = 0:1/Fs:1-1/Fs; % 时间 x = sin(2*pi*50*t) + cos(2*pi*300*t) + 0.2*randn(1,length(t)); % 信号 y = filter(h ,1 ,x); % 过滤信号 % 画出过滤前后的信号 figure, plot(t, x), grid on; xlabel('Time / s'), ylabel('Amplitude'); title('Original Signal'); figure, plot(t, y), grid on; xlabel('Time / s'), ylabel('Amplitude'); title('Filtered Signal'); % 频谱分析 F = Fs*(0:(length(t)/2))/length(t); X = fft(x); Y = fft(y); P1 = abs(X/length(t)); P2 = abs(Y/length(t)); figure, plot(F, 20*log10(P1(1:length(t)/2+1))), hold on; plot(F, 20*log10(P2(1:length(t)/2+1))), grid on; xlabel('Frequency / Hz'), ylabel('Magnitude / dB'); title('Spectrum of Original and Filtered Signals'); legend('Original Signal', 'Filtered Signal'); 运行这段程序,可以得到如下结果: 我们通过窗函数设计了一个50阶的低通FIR滤波器,并使用Hamming窗函数对其进行截断。接着,我们用我们设计滤波器对一个由正弦信号、余弦信号和高斯白噪声构成的信号进行了滤波。最后,我们用频谱分析比较了原始信号和滤波后的信号,可以看到,滤波器能够有效地过滤高频噪声。 ### 回答3: FIR滤波器是数字信号处理中一个非常重要的概念,它的设计和应用涉及到了很多领域。在设计FIR滤波器时,采用窗函数法是一种常见的方式。下面我们来介绍一下如何使用matlab来实现这一设计过程。 在matlab使用窗函数设计FIR滤波器的一般步骤如下: 1、首先确定滤波器的阶数 根据要滤波的信号的特性,可以初步估计出所需要的滤波器阶数。 2、确定滤波器的通带、阻带参数 根据滤波器的通带、阻带参数,可以用matlab内置的函数firls或firpm设计滤波器的理想响应。 3、确定窗函数 常用的窗函数有矩形窗、汉宁窗和黑曼窗等,可以根据需要选择合适的窗函数。 4、计算出滤波器系数 在matlab使用fir1函数可以根据设计出的理想响应和窗函数计算出滤波器的系数。 下面,我们将通过一个具体的FIR滤波器设计实例来展示如何使用matlab进行窗函数设计。 我们需要设计一个低通FIR滤波器,截止频率为1000Hz,采样频率为5000Hz,通带衰减小于0.1dB,阻带衰减要求大于60dB,滤波器类型为矩形窗。 首先,我们应该计算出滤波器的阶数。阶数可以根据下面的公式计算: N = (Fs/Wc) * 3.3 其中,Fs表示采样频率,Wc表示滤波器的截止频率。根据这个公式计算出N的值为33,即我们需要一个33阶的滤波器。 接下来,我们可以使用fir1函数来计算出滤波器的系数。根据理论计算,我们可以用firls或firpm函数计算出一个理想响应,然后将该响应与选定的窗函数相乘来得到实际的频率响应。在这里,我们将使用firls函数来计算理想响应。 代码如下: fs = 5000; % 采样频率 f_c = 1000; % 截止频率 % 确定通带和阻带参数 f_pass = f_c / fs; f_stop = 1.2 * f_pass; A_pass = 0.1; A_stop = 60; % 计算阶数 N = 33; % 计算理想响应 h_ideal = firls(N, [0 f_pass f_stop 1], [1 1 0 0], [10^(A_pass/20) 10^(-A_stop/20)]); % 计算窗函数 win = rectwin(N+1); % 计算实际响应 h = h_ideal .* win'; % 绘制频率响应曲线 freqz(h); 最后,我们可以使用freqz函数绘制出滤波器的频率响应曲线。运行代码后,我们会得到下面这张图: 从图中可以看出,滤波器已经满足了设计的要求。这就是采用窗函数设计FIR滤波器的过程及matlab实现方法
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值