一阶IIR滤波器的C语言设计和优化

对于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;
}


  • 9
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
IIR滤波器,全称为无限脉冲响应滤波器(Infinite Impulse Response Filter),是一种数字滤波器,常用于信号处理和数字滤波的应用中。它的特点是有记忆性且可以实现较窄的通带和高衰减的阻带,适用于对信号进行频域操作。 IIR滤波器可以通过差分方程描述,其输出信号y(n)与输入信号x(n)之间的关系可以表示为: y(n) = b0*x(n) + b1*x(n-1) + b2*x(n-2) + ... - a1*y(n-1) - a2*y(n-2) - ... 其中,b0, b1, b2, ... 是前向系数,a1, a2, ... 是反馈系数。这些系数可以根据滤波器的要求来确定,例如截止频率等。 在C语言中实现IIR滤波器可以通过循环结构来实现上述差分方程的运算。具体步骤如下: 1. 定义输入信号x(n)和输出信号y(n)的数组,并初始化。 2. 定义滤波器的系数b0, b1, b2, ...和a1, a2, ...。 3. 使用循环结构依次计算输出信号y(n)的每一个值。 - 对于每个n,在计算y(n)之前,先计算x(n)的权重和,即 b0*x(n) + b1*x(n-1) + b2*x(n-2) + ... - 然后计算y(n)的权重和,即 - a1*y(n-1) - a2*y(n-2) - ... - 将两个权重和相加得到y(n)的值,并更新数组中的值。 4. 循环处理数组中的每个n,直到处理完所有的输入信号。 需要注意的是,IIR滤波器的实现可能存在数值问题,如数值溢出和数值不稳定性等。在设计时,需要选择合适的滤波器结构和系数,以及采取一些数值稳定化的措施,以确保滤波器的性能和稳定性。 总之,通过C语言可以实现IIR滤波器,只需根据差分方程和系数定义相应的循环结构计算即可。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值