对于N阶IIR的计算方程式为:
其中N表示滤波器的级数,当N=1的时候,其方程可以展开为如下所示:
本文的研究对象就是这个一阶方程,其中y为输出数据,x为输入数据,a和b为滤波器的系数。
x[n]为本次要滤波的输入数据,x[n-1]为上一次滤波前的输入数据,y[n-1]为上一次滤波器输出的数据。
设计这个滤波器,主要就是设计其中的系数a和b。
######################################
几乎网上的所有资料都是叫你使用matlab中的fdtool来设计参数,其实如果只是计算滤波参数,
完全不用安装matlab这个几百兆的大家伙,可以使用下面介绍的小工具完成任务:
1.直接在线计算:http://www-users.cs.york.ac.uk/~fisher/mkfilter
2.下载专用小软件ScopeIIR,官方网站:http://iowegian.com/scopeiir
3.下载专用小软件FiWiz,官方网站:http://www1.icsi.berkeley.edu/~storn/fiwiz.html
4.下载专用小软件Iowa Hill,官方网站:http://iowahills.com/8DownloadPage.html
#####################################
无论使用哪种方式计算参数,都要输入采样率,滤波器类型,滤波级数,截止频率等参数。
最后都会得到A0,A1,A2,B0,B1,B2这样的滤波器系数,直接代入到公式中计算就可以了。
默认情况下,公式中的数据用代码都是采用浮点数float或者double来计算,这样可以提高精度,
但是大量的浮点乘法计算量比较大,特别是对于主频不高的单片机而言就更为吃力;
所以我们希望可以使用定点整数以减少计算量,甚至希望用移位器和加法器来代替乘法。
下面就举一个实例来研究如何减少计算量:
我们要设计一个采样率为1000,截止频率为100,滤波器类型为Butterworth,阶数为1的IIR低通滤波器,
通过计算得到如下参数:
B[0]=+1.000000
B[1]=+1.000000
A[1]=-0.509525
(细心的人可能会发现高通滤波器和低通滤波器的区别只有B[1]这个参数,一个为+1.00,一个为-1.00)
代入公式得到:y[n]=x[n]+x[n-1]+0.509525*y[n-1]
我们优化的重点就是这个0.50952*y[n-1],利用移位法来代替小数乘法,
原理就是把小数分解为1/M[0]+1/M[1]+...的方式,其中M[n]必须为2的整数次幂,
分解的次数越多,分母越大,误差就越小,可以根据实际情况需要选择分解的精度。
分解过程:
0.509525 * 1024 = 521(注:需要更高精度,可以把1024改为2048,4096,8192.......)
=521/1024
=(512+8+1)/1024
=512/1024+8/1024+1/1024
=1/2+1/8+1/1024
所以这个公式可以改写为:y[n]=x[n]+x[n-1]+y[n-1]/2+y[n-1]/8+y[n-1]/1024
最后附上C语言代码:
/*************************************************************************************************
* 输入待滤波的数据,返回滤波后的数据
* 由于输入输出都是整型数据,为了防止数据溢出或数据太小,可以将输入数据先左/右移N位,最后返回时再右/左移N位
**************************************************************************************************/
int iir_filter(int x1)
{
static int x0;
static int y0;
int y1;
y1 = x1 + x0 + (y0>>1) + (y0>>3) + (y0>>10);
x0 = x1;
y0 = y1;
return y1;
}