还剩4页未读,继续阅读
文本内容:
FIR与HR低通滤波器的最简最快实现在设计单片机程序的过程中,经常需要利用ADC采集外界模拟信号有一些信号我们比较关注它的直流与低频分量,希望将高频噪声滤除,就需要借助低通滤波器低通滤波器常见的利用电子电路实现的方式是一阶RC无源滤波器简单讲就是这样RC滤波器的各类计算略,有需要请谷歌RC滤波器用于单片机ADC输入有许多缺点如果R的取值较小,就要求C较大,同时输入信号阻抗不能过大;如果R的取值较大,则ADC采样瞬间释放的电荷会使得端口电压升高而无法在采样时间内释放到稳定水平这会导致采样精度问题°而即便使用一个运放来缓冲RC滤波器的输出,再接入ADC,也只解决了输入阻抗问题,ADC电路受外界干扰仍然会在转换结果中产生噪声因此,我们希望在单片机内部利用程序来实现低通滤波,彻底摆脱高频噪声数字低通滤波器有两种形式,HR和FIRHR是无限脉冲响应滤波器,它的特点是输出与无限久以前的输入有关这就如同上面RC滤波器的响应,随着时间流逝,输出电压只会无限接近于输入电压,而不会等于用c语言实现HR低通很简单int last=0;〃下面的函数以固定频率运行,函数输出就是HR低通滤波器的输出int lowpass(){int this=ADC();last=(this*1+last*15)/16;〃新的last是旧的last*15/16+this*1/16return last;)如果对函数返回值作图,得到的波形就会和RC滤波器的波形一样要改变截止频率,只需要改变函数第二句中新的last的组成(例如改成3/4和1/4,截止频率会提图)值得注意的是,上述代码使用了整数乘法和2的n次塞除法,因此编译优化后,在8位平台上运行超快如果你使用带有浮点运算模块的平台,请直接使用浮点数HR的特点是节省内存,上面的滤波器只使用了两个变量HR的缺点是不稳定如果你把15改成17,显然这个滤波器的输出会在一段时间后溢出你必须负责保证HR滤波器稳定FIR是有限脉冲响应滤波器,它的特点是输出与有限久以前(一段时间内)的输入有关由于数字系统中采样是离散的,每一段时间内的采样数是固定的,所以FIR滤波器的每一个输出值,可通过对之前的若干个数量固定的采样值进行计算得到特别是,因为对固定数量的采样值的计算在FPGA电路中可以并行实现,因此F1R滤波器常常被用于基于FPGA的数字信号处理系统相对的,HR滤波器不依赖之前的采样,但依赖于之前的滤波器状态(存在反馈),因此在大部分比一阶低通滤波器复杂的应用场合,HR滤波器的各项特性没有FIR稳定(若要实现稳定,对计算精度要求较高),而且计算起来比FIR要慢,设计上也没有通用性下面我用C语言实现一个最简单的FIR低通我们将最近的8次采样值加起来,求平均值,作为输出int buf
[8];int lowpassint k=7;while k--buf[k]=buf[k-l];//将buf
[6]移到buf
[7],buf
[5]移到buf
[6],等等,以空出bu等等buf
[0]=ADC;return buf
[0]+buf
[1]+...+buf
[7]/8;这个滤波器的时域图像有点像这样:值得注意的是,上面这个函数可以被进一步简化,以加速计算上面这种滤波器有另一个名字滑动平均滤波器,这个滤波器大部分股民应该很熟悉虽然时域图像很美观,但是这个滤波器的频域图像一点也不美观FIGURE15-2Frequency responseof themoving averagefilter.The movingaverage isa verypoor low-pass filter,due toits slowroll-off andpoor stopbandattenuation.These curvesarc generatedby Eq.15-2可见,随着点数的增加,图像看起来只是从右向左缩水,对高频的抑制并不好所以如果想要获得比较好的低通效果,不应该增加点数,而应该将多个一样的FIR滤波器串联使用(一个的输出作为下一个的输入)注pass是“遍”的意思,表示迭代次数40-■-------------AI・120-d.Frequency responsedB0-二dEV4pass撕
00.
10.
20.3嚏Frequency T上面是串联使用的幅频响应而时域图像也很美观:mpQpBL2b.Step responseI二mpQ结尾给出的是写这篇文章时随手找到的资料大家一定要学会使用谷歌搜索英文关键词,因为老外比我们对待知识的态度更严肃也更开放analog,com/media/en/technical-documentation/dsp-book/dsp_book_Chl
5.pdf刚才的滑动平均滤波器,时间复杂度是0n设每次处理n个采样可以优化为01的形式int buf
[8];int k=0;int result=0;int lowpass{result-=buf[k];buf[k]=ADC;result+=buf[k];k=k+1%8;return result;。