高通有限冲激响应滤波器FIR于DSP上的实现 - 下载本文

高通有限冲激响应滤波器FIR于DSP上的实现

IIR数字滤波器能保留一些典型模拟滤波器优良的幅度特性,但设计中只考虑了幅度特性,没考虑相位特性,所设计的滤波器相位特性一般是非线性的。为了得到线性相位特性,对IIR滤波器必须另外加相位校正网络,是滤波器设计变的复杂,成本也高。FIR滤波器在保证幅度特性满足技术要求的同时,很容易做到严格的线性相位特性。稳定和线性相位特性是FIR滤波器突出的优点。它的系统函数为

H(z)??h(n)z?n

n?0N?1本设计利用窗函数法来设计FIR滤波器。由于理想的滤波器的单位取样响应是无限长的,且是非因果的,为了构造一个长度为N的线性相位滤波器,只有将单位取样响应截取一段,这里就用到了窗函数。窗函数设计法的基本原理是用有限长的单位脉冲响应序列h(n)逼近hd(n),hd(n)为期望理想滤波器的单位脉冲响应序列。方法是用窗函数w(n)将hd(n)截断,并进行加权处理,即

h(n)= hd(n) w(n)

用h(n)作为实际设计的FIR数字滤波器的单位脉冲响应序列,相应的频率响应函数为用窗函数设计的实际滤波器的频响函数。调整窗口长度N可以有效的控制过渡带的宽度,减少带内波动以及加大阻带的衰减只能从窗函数的形状上找解决方法。这里利用了哈明窗,它的旁瓣峰值幅度为-41/dB,过渡带宽为8pi/N,阻带最小衰减为-53/dB。

利用matlab产生一个80阶的高通滤波器,采用哈明窗,采样频率为6kHz,截止频率为3kHz,matlab程序如下: % n: 阶数

% fp:高通截止频率 % fsample:采样率 % w:窗函数值

% h:返回设计好的FIR滤波器系数 n=120;

fsample=7000; fp=3000;

w=hamming(n+1); wp=fp/(fsample/2); %ws=fs/(fsample/2); h=fir1(n,wp,'high',w); m=0:n; figure(1)

subplot(2,1,1);plot(m,w);grid; ylabel('w(n)');xlabel('n'); subplot(2,1,2);plot(m,h);grid; ylabel('h(n)');xlabel('n'); figure(2) freqz(h)

xlabel('\\omega^pi')

ylabel('|H(e^j\\omega|dB)') subplot(2,1,2)

xlabel('\\omega^pi')

程序产生的图形如下:

图一

图一中上图是窗函数参数,下图是滤波器参数

图二

图二中上图是相对幅值响应,下图是相位响应

2. 利用matlab求的h的参数,编写dsp的程序,相应程序如下: /* fir_test.c */

#include \

#define L 80 /* Number of FIR filter coefficients */ #define Fs 6000 /* 9000 Hz sampling frequency */ #define T 1/Fs

#define f1 400 /* 800 Hz frequency */ #define f2 1800 /* 1800 Hz frequency */ #define f3 3300 /* 3300 Hz frequency */ #define PI 3.1415926

#define w1 (2*PI*f1*T) /* 2*pi*f1/Fs */ #define w2 (2*PI*f2*T) /* 2*pi*f2/Fs */ #define w3 (2*PI*f3*T) /* 2*pi*f3/Fs */

#define a1 0.333 /* Magnitude for wave 1 */ #define a2 0.30 /* Magnitude for wave 2 */ #define a3 0.30 /* Magnitude for wave 3 */

extern float firC(float *,float *,unsigned int);

/* High-pass FIR filter coefficients */

float hh[]={-1.14361737749628e-020 ,2.81071199533121e-005,

-0.000104762148808631, 0.000190622649920012 ,-0.000188360514955522, 5.31949187585617e-018, 0.00038632360096985, -0.000834992671158477, 0.00108072071827029, -0.000843248564750587 ,-1.39180844191428e-017, 0.00127004390697416, -0.0024670341890541, 0.00292749706766469, -0.00212585059236375, 8.25113383218456e-018, 0.0028645477989133, -0.00532726277238321, 0.00609021466525661, -0.00428339507592519, -4.04683228269962e-018, 0.00548740467392238, -0.0100086120581683 ,0.011261388469816, -0.00782187111360178 ,1.02534145840692e-016, 0.00987263562446114, -0.0179696233475638, 0.0202573173966555

,-0.0141604007858742, -6.70581141910393e-018, 0.0184104770007767, -0.0343909128329517, 0.0402041686332826 ,-0.0295592934806454, 6.76127588024641e-017, 0.0456771960323911, -0.0995670330523718 ,0.15045420403542, -0.186793354305917,

0.199967872009154,-0.186793354305917, 0.15045420403542

,-0.0995670330523718, 0.0456771960323911, 6.76127588024641e-017, -0.0295592934806454, 0.0402041686332826, -0.0343909128329517, 0.0184104770007767, -6.70581141910393e-018, -0.0141604007858742 ,0.0202573173966555, -0.0179696233475638, 0.00987263562446114, 1.02534145840692e-016, -0.00782187111360178, 0.011261388469816

,-0.0100086120581683, 0.00548740467392238, -4.04683228269962e-018, -0.00428339507592519, 0.00609021466525661, -0.00532726277238321, 0.0028645477989133, 8.25113383218456e-018, -0.00212585059236375, 0.00292749706766469, -0.0024670341890541, 0.00127004390697416, -1.39180844191428e-017, -0.000843248564750587, 0.00108072071827029 ,-0.000834992671158477, 0.00038632360096985, 5.31949187585617e-018,

-0.000188360514955522, 0.000190622649920012, -0.000104762148808631, 2.81071199533121e-005, -1.14361737749628e-020, };

float xx[L]; /* input buffer */ float yy[L]; /* Output buffer */ float xtemp,ytemp;

main() {

unsigned int i;

float signal;

unsigned int n=0; for(i=0;i

xx[i]=0;

yy[i]=0; }

while(1) {

signal = a1*cos((float)w1*n); signal += a2*cos((float)w2*n); signal += a3*cos((float)w3*n); n++;

xtemp=signal; for(i=L-1;i>0;i--) { xx[i] = xx[i-1]; } xx[0]=xtemp;

ytemp = firC(xx,hh,L); for(i=L-1;i>0;i--) { yy[i] = yy[i-1]; } yy[0]=ytemp; } }

/* ********************************************************* * firC.c 该程序用于实现FIR滤波器 * L--滤波器的阶数

* hh[i]--滤波器的系数,i=0,1,...,L-1 * xx[i]--输入信号向量,i=0,1,...,L-1; * y_out-- 输出信号的当前值

************************************************************ */ float firC(float *xx,float *hh,int L) {

float y_out; int i;

y_out = 0.0; for(i=0;i

return y_out; }

运行程序,观看相应的波形图,在程序中输入三个频率为400,1800,3300的信号来观察滤波效果

图三

在图三中上图为相应的输入信号,下图为输出信号。根据程序的设计,下图的输出信号应为经过高通滤波器后产生的频率为3300的信号,但是实际出来的信号为比较杂乱的呈三角波状的波形,而不是一个比较正规的正弦波图形。经过思考也没有找到问题所在。

图四 输入信号频谱 图四中是输入信号的频谱,输入信号是频率为400,1800,3300的三个信号的叠加,频谱中清晰的显示了这个叠加信号的频谱

图五 输出信号频谱

图五中式输出信号频谱,输入信号经过高通滤波器进行滤波后,将频率为800,1800的信号都滤掉,剩下频率为3300的信号通过滤波器。