一 FIR滤波器设计基础
FIR滤波器的基本结构是一个分节的延时线,每一节的输出加权累加,得到滤波器的输出。数学上可以表示为下,其结构如图1 所示。图1 中x(n)是最近( t = nT) 的输入信号,x (n -i)是延时了i个采样周期的输入信号, h(i)是第i个延时节的加权值(即滤波器系数),y(n)是时刻t=nT时滤波器的输出信号。
二 F2812实现FIR
1 初始化的一些说明
1)添加FIR.H文件,其中:typedef struct {
long *coeff_ptr; /* Pointer to Filter coefficient */
long * dbuffer_ptr; /* Delay buffer ptr */
int cbindex; /* Circular Buffer Index */
int order; /* Order of the Filter */
int input; /* Latest Input sample */
int output; /* Filter Output */
void (*init)(void *); /* Ptr to Init funtion */
void (*calc)(void *); /* Ptr to calc fn */
}FIR16;
定义了16位滤波函数的结构体
2)typedef FIR16 *FIR16_handle;
#define FIR16_DEFAULTS { (long *)NULL, \
(long *)NULL, \
0, \
50, \
0, \
0, \
(void (*)(void *))FIR16_init,\
(void (*)(void *))FIR16_calc}
宏定义了缺省的滤波函数结构体的初值
3)void FIR16_calc(void *);
void FIR16_init(void *);
这两个函数在fir16.asm实现。
2 使用16位FIR滤波函数例子
#define FIR_ORDER 50 /*定义滤波器阶数N为50*/
/* Create an Instance of FIRFILT_GEN module and place the object in "firfilt" section */
#pragma DATA_SECTION(fir, "firfilt");
FIR16 fir= FIR16_DEFAULTS; /* 初始化滤波函数*/
/* Define the Delay buffer for the 50th order filterfilter and place it in "firldb" section */
#pragma DATA_SECTION(dbuffer,"firldb");
long dbuffer[(FIR_ORDER+2)/2]; /*定义滤波器延迟单元本例中
dbuffer[i]=x(n-i)+x(n-50+i), 0<i<25
dbuffer[i]=x(n-25) i=25
*/
/* Define Constant Co-efficient Array and place the .econst/.const section in
non-volatile memory */
const long coeff[(FIR_ORDER+2)/2]= FIR16_LPF50;
定义了滤波器系数coeff (i)=h(i),这里系数和上面的延迟单元的系数长度都是26,这是由于计算系数时使用了MATLAB数字信号处理工具箱中的firl函数,可以方便的得到滤波器的系数。
firl函数用来设计标准频率响应的基于窗函数的FIR滤波器,可实现加窗线性相位FIR数字滤波器的设计。其语法有四种形式:
b=firl(n,W): b=firl(n,W,‘ftype’)
b=firl(n,W,Window) b=firl(n,W ,‘ftype’,Window)
返回值b即为确定的FIR滤波器系数,共n+l维。n为滤波器的阶数,W为归一化低通截止频率,0<W<1;ftype;用来决定滤波器的类型;Window:用来指定滤波器采用的窗函数类型,其默认值为汉明窗。这里采用第四种形式,选择的是低通,汉明窗,取样频率fs=20000hz,截止频率fc=3000hz,W=fc/(fs/2)这是归一化低通截止频率,因为根据取样定理fs>2fc,这样取可以保证0<W<1。
由于返回的是n+l=51阶FIR滤波器系数,根据线性相位其系数对称,n+l=51是奇数采用公式(4)我们只要计算其中的(N+1)/2=26个系数,所以延迟单元和滤波器系数的个数都为26。
main()
{
lpf.dbuffer_ptr=dbuffer;
lpf.coeff_ptr=(long *)coeff;
lpf.order=FIR_ORDER;
lpf.init(&lpf);
}
主函数中对滤波器函数进行初始化;
void interrupt isr20khz()
{
lpf.input=xn;
lpf.calc(&lpf);
yn=lpf.output;
}
运用中断输出经过滤波计算的信号,格式为Q15.
Note:
1. “firldb” section should be aligned to 256word boundary in the data memory (RAM)
2. “firfilt” section can be placed anywhere in the data memory (RAM)
在cmd文件中增加
SECTIONS
{。。。
firldb align(0x100)> DRAMH0 PAGE = 1
firfilt : > DRAMH0 PAGE = 1
}
联系客服