关于IIR高通滤波器,个人认为AVR应用笔记AVR465中的程序有问题
最近需要检测交流电有效值,因此借用了AVR465中IIR高通滤波器以去掉采样数据中的直流成分相关原版的代码是这样的:
计算公式:y = 0.996*y + 0.996*x - 0.996*x
Sample.PreviousFiltered=Sample.Filtered;// y <- y
TempL=255*(long)Sample.Filtered;
TempL=TempL>>8;
TempI=Sample.Fresh-Sample.Previous;
TempL=TempL+255*(long)TempI;
Sample.Filtered=TempL;
这段代码有2个问题:
1,第5句 TempL=TempL+255*(long)TempI; 我怎么看都觉得与公式不同,因为TempI没有除以256;
2,我认为,以定点计算代替浮点计算,需要有若干小数位参加计算,而该算法没做到这点。因此无法对小数点后的有效数字进行累积。我的实验也证明这点,
当电源电压是220伏时,测量结果完全正确,这是突然撤掉220伏,则测量结果会在56伏左右跳动,无法回零。
因此我认为是相邻采样点的差值接近零时,0.996的乘法的小数部分被抛弃了。下面是我自己的代码:
s32 templ;
s16 tempi;
templ = (s32)ADC_Last_Result*255;
templ >>= 8;
tempi = pbuf - ADC_Buf_Last;
tempi *= 255;
tempi >>= 8;
templ += (s32)tempi;
ADC_Last_Result = templ;//乘以0.996
显然我的代码也是有定点小数位被舍弃的问题。
程序正在调试中,稍后吧带16位定点小数运算的算法贴上,以表明结论是否正确,也欢迎高手指正。 问题已解决,贴上修改后的代码,11位定点小数的:
s32 templ;
templ = (s32)ADC_Last_Result;
templ += (s32)pbuf<<11;//11位小数
templ -= (s32)ADC_Buf_Last<<11;//11位小数
templ *= 255;
templ >>= 8;//乘以0.996
ADC_Last_Result = templ; 回复【楼主位】lihui_mc软硬兼施
-----------------------------------------------------------------------
请问一下,avr单片机的AD:输入是多少时它的内部寄存器从0-1023变化? make 回复【2楼】haimaod
回复【楼主位】lihui_mc软硬兼施
-----------------------------------------------------------------------
请问一下,avr单片机的ad:输入是多少时它的内部寄存器从0-1023变化?
-----------------------------------------------------------------------
输入0到1023/1024vref的时候 楼主能说说这个公式的含义吗y = 0.996*y + 0.996*x - 0.996*x,频率点是怎么定的 补上公式不知道对不对
*
* X= exp(-2.0 * pi * Fc)
* A0 = (1 + X) / 2
* A1 = -(1 + X) / 2
* B1 = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC high-pass filter:
*
* || C
* ----||--------->
* || |
* <
* > R
* <
* |
* V
页:
[1]