一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 606|回复: 9
收起左侧

[51单片机] 发一个改进型的滑动滤波算法

[复制链接]
发表于 2021-9-18 09:22 | 显示全部楼层 |阅读模式

很多时候,我们在编程中需要用到滑动滤波,最简单的滑动滤波方式是将数组依次前移,最后一个元素更新为最新加入的数据,再求和求平均,代码如下:

    static u16 Sum;
    static u8 Arr[16];
    static u8 i;
    u8 Average;


    for(i=0; i i<15; i++)
    {
        Arr[i+1] = Arr[i]; // 数组依次前移
    }
    Arr[15] = NewData;     // 更新新数据

    Sum = 0;
    for(i=0; i<16; i++)
    {
        Sum += Arr[i];     // 累加
    }

    Average = Sum / 16;    // 求平均



这种方式每次添加新数据都会将所有的成员移动一次,所有的成员累加,为了提高效率可以修改代码如下:

    Sum -= Arr[i];     // 减去旧数据
    Arr[i] = NewData;  // 更新新数据
    Sum += Arr[i];     // 新数据累加
    Average = Sum / 16; //求平均

    i ++;
    if(i >= 16)
    {
        i = 0;
    }


这样的话,每次更新数据前,先减去旧数据,再将旧数据更新为新数据,累加再求平均,
每次更新新数据,只需做一次加法,一次减法,一次除法和两次赋值操作就可以了,效率有明显提高,代码量也少很多。



发表于 2021-9-18 10:39 | 显示全部楼层
谢谢分享!
发表于 2021-9-19 11:17 | 显示全部楼层
原来我用过一个软件滤波方法,和楼主这个有点类似,但不用数组。假如对16个采样进行滤波,方法是 总和=(上次总和-上次平均值+本次采样值);   本次平均值=总和/16 。
发表于 2021-9-27 09:22 | 显示全部楼层
楼主帮忙解释一下,哪里移动了

第一次

Arr[1] = Arr[0]
Arr[2] = Arr[1]
......
Arr[15] = Arr[14]

Arr[15] = NewData;


第二次,还是一样的,,Arr[15] 移动过吗? Arr[1]---Arr[114] 就没变过  Arr[0] 都没有给过值   


点评

是的,Arr[15] = NewData; 要改成 Arr[0] = NewData;  详情 回复 发表于 2021-10-9 20:25
分析的对,楼主应该把赋值顺序弄反了。  详情 回复 发表于 2021-9-27 18:38
发表于 2021-9-27 18:38 | 显示全部楼层
zhuyi2576 发表于 2021-9-27 09:22
楼主帮忙解释一下,哪里移动了

第一次

分析的对,楼主应该把赋值顺序弄反了。
 楼主| 发表于 2021-10-9 20:25 | 显示全部楼层
zhuyi2576 发表于 2021-9-27 09:22
楼主帮忙解释一下,哪里移动了

第一次

是的,Arr[15] = NewData; 要改成 Arr[0] = NewData;

点评

Arr[1] = Arr[0] //0 Arr[2] = Arr[1] //0 ...... Arr[15] = Arr[14] //0 Arr[0] = NewData1; Arr[0]---------------Arr[15] 第一次 NewData1,0 0 0 0 。。。。 第二次  详情 回复 发表于 2021-10-10 14:57
发表于 2021-10-10 14:57 | 显示全部楼层
356053261 发表于 2021-10-9 20:25
是的,Arr[15] = NewData; 要改成 Arr[0] = NewData;

Arr[1] = Arr[0]  //0
Arr[2] = Arr[1]  //0
......
Arr[15] = Arr[14] //0
Arr[0] = NewData1;

         Arr[0]---------------Arr[15]
   
第一次  NewData1,0 0 0 0 。。。。                     
第二次  NewData2,NewData1,NewData1,NewData1.......  
第三次  NewData3,NewData2,NewData2,NewData2.......  

第16次  NewData16,NewData15,NewData15,NewData15.....


不清楚怎么移动的,求解释






点评

for(i=0; i  详情 回复 发表于 2021-10-10 16:48
只有第15次,没有第16次,这种是最基础的,用指针和用数组原理上是一样的, 如果使用改进型的写法,则效率和计算量都会提升很多  详情 回复 发表于 2021-10-10 16:43
发表于 2021-10-10 15:03 | 显示全部楼层
int filter(int dat)
{
    #define filter_len 10                                       // 滤波缓存数据长度
    static int buffer[filter_len] = {0};                        // 历史数据缓冲区
    static int *ptr = (int*)buffer + (filter_len - 1);          // 初始指针指向缓冲区最后
    static int sum = 0;
    static int cnt = 0;
   
    sum -= *ptr;                                                // 移出最前面的一个历史值
    sum += dat;                                                 // 前面(N-1)的数据加上新值求和
    *ptr = dat;                                                 // 将新值存入缓冲区(从后向前存数据)
    if (--ptr < buffer) ptr += filter_len;                      // 缓冲区指针重(指向缓冲区尾元素)
    if (cnt < filter_len) cnt++;                                // 滤波计数
   
    return (sum + (cnt >> 1)) / cnt;                            // 返回平均值(四舍五入)
}

 楼主| 发表于 2021-10-10 16:43 | 显示全部楼层
zhuyi2576 发表于 2021-10-10 14:57
Arr[1] = Arr[0]  //0
Arr[2] = Arr[1]  //0
......

只有第15次,没有第16次,这种是最基础的,用指针和用数组原理上是一样的,

如果使用改进型的写法,则效率和计算量都会提升很多
 楼主| 发表于 2021-10-10 16:48 | 显示全部楼层
本帖最后由 356053261 于 2021-10-10 16:52 编辑
zhuyi2576 发表于 2021-10-10 14:57
Arr[1] = Arr[0]  //0
Arr[2] = Arr[1]  //0
......

for(i=0; i<15; i++)
    {
        Arr[ i ] = Arr[i+1]; // 数组依次前移
    }
    Arr[15] = NewData;     // 更新新数据


应该是这样写的,很久没有这样写的,随手写出来的,没有经过仔细推敲,误人子弟了

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-25 23:57 , Processed in 0.055679 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表