|
用循环缓冲法实现的FIR滤波器:
1. 对于N级FIR滤波器。在数据存储器中开辟一个N单元的缓冲区,用来存放样本和你的FIR系数;
2. 从最新样本开始取数;(关于这一点,存在一点问题,我认为只要你的系数和数据乘对了就OK了,我写的那个是由底部取起)
3. 读到最后一个样本后,输入新样本代替最老样本,而其他数据位置保持变(这使得新老样本的位置关系不是很明显,但是用线性缓冲法的话就不一样。)
4. 定义BK大小,这是实现循环的关键,可以是缓冲地址首尾相连,就象一个圆圈一样
关于FIR滤波器的理论常见相关参考资料,其实当你知道原理后,编程就会变得SO EASY
PS. 例如要实现7阶滤波器,即是N=7,则y=b0*x(n)+b1*x(n-1) +b2*x(n-2)+b3*x(n-3) +b4*x(n-4)+b5*x(n-5)+ b6*x(n-6)
Note:b0~b7是系数;x(n)~x(0)是输入数据
另:线性缓冲法和系数对称法都是FIR滤波器实现的一种方法,后者要用到FIRS指令(这个系数对称法从某书上看到过,有兴趣可以去看看) ==========================================================================
.title "FIR.ASM"
.mmregs .bss y,1 K_FIR_BFFR .SET 40 PA0 .SET 0 PA1 .SET 1 FIR_COFF_TABLE .USECT "FIR_COFF", 40 ; D_DATA_BUFFER .USECT "FIR_BFR", 40 .DATA COFF_FIR_STAR: .WORD -7*32768/10000,-7*32768/10000 ;(我不想改数了,所以就用 40个一样的数) .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .WORD -7*32768/10000,-7*32768/10000 .TEXT .DEF FIR_INT .DEF FIR_TASK FIR_INT: SSBX FRCT ;置FRCT位为1,可以实行小数乘法 STM #FIR_COFF,AR1 ;AR1指向系数 RPT #K_FIR_BFFR-1 ;设置重复次数并将系数由程序区传向数据区 MVPD COFF_FIR_START,*AR1+ STM #D_DATA_BUFFER,AR2 ;将AR2指针指向输入数据区 RPTZ A,#K_FIR_BFFR-1 STL A,*AR2+ ;将DATA_BUFFER清零 STM #(D_DATA_BUFFER+K_FIR_BFFR-1),AR2 ;设置AR2指向到数据的底部 STM #(K_FIR_BFFR+K_FIR_BFFR-1),AR1 ;设置AR1指向到系数的底部 STM #-1,AR0 ; 这个设置将用到AR1+0%的循环寻址中即AR1指针由底部向上索数(AR2同理) LD #D_DATA_BUFFER,DP ;设置页指针 PORTR PA1,@D_DATA_BUFFER ;从I/O口读入数 FIR_TASK: STM #K_FIR_BFFR,BK ;设置块大小(用在循环寻址上) RPTZ A,#K_FIR_BFFR-1 ; MAC *AR1+0%,*AR2+0%,A;(这里就是实现FIR滤波的表达式) STH A,@y PORTW @y,PA0 ;输出结果 BD FIR_TASK PORTR PA1,*AR1+0% ;再读入新数据然后调整AR1指针位置 .END
(以上程序是C54的)
|