找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10448|回复: 20
打印 上一主题 下一主题
收起左侧

AD数据滤波算法,适用于各种MCU实时数据处理的场合

  [复制链接]
跳转到指定楼层
楼主
前面闲来无事,整理了下平时用得比较多的部分MCU滤波算法,当然 代码网上都有,我只是做了一个搬运工,合并了一些算法,整理成模块函数,需要用的时候直接调用就可以。
这里简单介绍包含的内容,详细代码和使用说明在附件里。大家可自行查阅。

AD滤波算法函数模块说明:
  一、该模块包含滤波算法有:中位值滤波、中位值平均滤波、递推平均滤波、一阶滞后滤波。用户可根据项目不同情况选用不同的滤波算法。
1.1、中位值滤波:连续采样N次(N取奇数),把N次采样值按大小排列,取中间值为本次有效值。适用范围能有效克服因偶然因素引起的波动干扰,对温度、液位的变化缓慢的被测参数有良好的滤波效果。不过对流量、速度等快速变化的参数不宜。
1.2、中位值平均滤波:连续采用N个数据,去掉一个最大值和一个最小值,然后计算N-2个数据的算术平均值。适用范围:对应偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差。但是测量速度较慢, 比较浪费RAM。
1.3递推平均滤波:把连续取N个采样值看成一个队列,队列的长度固定为N,每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据,把队列中得N个数据进行算术平均运算,就可以获得新的滤波结果。
适用范围:对周期性干扰有良好的抑制作用,平滑度高,适用于高频振荡的系统。缺点是灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差,不易消除由于脉冲干扰所引起的采样值偏差,不适用于脉冲干扰比较严重的场合。
1.4、一阶滞后滤波:对周期性干扰具有良好的抑制作用,适用于波动频率较高得场合。缺点就是相位滞后,灵敏度低,滞后程度取决于a的大小,不能消除滤波频率高于采样频率1/21/2的干扰信号。本次滤波结果result=(1-a)*本次采样值+a*上次值。a=(0~1)
二、滤波函数
2.1、中位值/中位值平均滤波函数
函数名:FILTER_median(TYPE_STATE Flag)
输入值:Flag:选择中位值滤波或中位值平均滤波
                ON:中位值平均滤波  OFF:中位值滤波
返回值:滤波结果
2.2、递推平均滤波函数
函数名:FILTER_recursive()
输入值:无
返回值:sum:滤波结果
2.3、一阶滞后滤波函数
函数名:FILTER_firstorder()
输入值:无
返回值:value:滤波结果
备注:在干电池剩余电量检测中,经过测试对比数据,使用中位值平均滤波算法比较合适。数据整体表现平稳,灵敏度较高,脉冲干扰直接滤除。测试数据如下:

单片机源程序如下:
  1. /*********************************************************
  2. *文件名:  filter.c
  3. *日  期:  2018/7/26
  4. *描  述:  AD滤波算法函数集合
  5. *备  注:  
  6. **********************************************************/
  7. #include "filter.h"
  8. /*************************************
  9.   函数名:Delay
  10.   描  述:软件延时
  11.   输入值:ncount :延时时长
  12.   返回值:无
  13. **************************************/
  14. void Delay(unsigned short int ncount)
  15. {
  16.   for(; ncount != 0; ncount--);
  17. }


  18. /*
  19. uint16_t FILTER_limit()                                        //限幅滤波  A为两次采样最大偏差值
  20. {
  21.   uint16_t new_value=0,value=0;

  22.   new_value = AD_VALUE;

  23.   if ( ( new_value - value > A ) || ( value - new_value > A ) )
  24.                 return value;
  25.   else
  26.                 return new_value;

  27. }
  28.         
  29. */        
  30.         
  31. /*****************************************************
  32.   函数名:FILTER_median
  33.   描  述:中位值滤波:连续采样N次(N取奇数),
  34.         把N次采样值按大小排列,取中间值为本次有效值。
  35.         适用范围能有效克服因偶然因素引起的波动干扰,
  36.         对温度、液位的变化缓慢的被测参数有良好的滤波效果。
  37.         不过对流量、速度等快速变化的参数不宜。
  38.         
  39.   中位值平均滤波:连续采用N个数据,去掉一个最大值
  40.         和一个最小值,然后计算N-2个数据的算术平均值。
  41.         适用范围:对应偶然出现的脉冲性干扰,可消除由于脉冲
  42.         干扰所引起的采样值偏差。但是测量速度较慢, 比较浪费RAM。
  43.         
  44.   输入值:Flag:选择中位值滤波或中位值平均滤波
  45.           ON:中位值平均滤波  OFF:中位值滤波
  46.   返回值:滤波结果
  47.         备注:中位值滤波:N取奇数,N=2^x次方+1 为宜
  48.                                 中位值平均滤波:N=2^x次方+2 为宜
  49. ******************************************************/
  50. unsigned short int FILTER_median(TYPE_STATE Flag)        //中位值滤波   中位值平均滤波  N为采样次数,取奇数  Flag:中位值平均滤波使能
  51. {
  52.                 unsigned short int value_buf[N],temp=0;                        
  53. #if(Flag)
  54.                 unsigned short int sum=0;
  55. #endif
  56.                 unsigned char count,i,j;
  57.                
  58.                 for (count=0;count<N;count++)
  59.                         {
  60.                                 value_buf[count] = AD_VALUE;
  61.                                 Delay(300);                                                                                                //等待AD转换
  62.                         }
  63.                         
  64.                 for(j=0;j<N-1;j++)                                                                          //排序
  65.                         {
  66.                                 for(i=0;i<N-j-1;i++)        
  67.                                         {
  68.                                                 if ( value_buf[i] > value_buf[i+1] )
  69.                                                         {
  70.                                                                 temp =        value_buf[i];
  71.                                                                 value_buf[i] = value_buf[i+1];
  72.                                                                 value_buf[i+1] = temp;
  73.                                                         }
  74.                                         }
  75.                         }
  76. #if(Flag)
  77.                 for(count=1;count<N-1;count++)                                //中位求平均 由Flag标志控制
  78.                         sum+=value_buf[count];
  79.                         return (uint16_t)(sum/(N-2));
  80. #endif
  81.                 return value_buf[(N-1)/2];                                                //中位值
  82. }



  83. /***************************************************
  84.   函数名:FILTER_recursive
  85.   描  述:递推平均滤波:把连续取N个采样值看成一个队列,
  86.         队列的长度固定为N,每次采样到一个新数据放入队尾,并
  87.         扔掉原来队首的一次数据,把队列中得N个数据进行算术平
  88.         均运算,就可以获得新的滤波结果。
  89.         适用范围:对周期性干扰有良好的抑制作用,平滑度高,
  90.         适用于高频振荡的系统。缺点是灵敏度低,对偶然出现的
  91.         脉冲性干扰的抑制作用较差,不易消除由于脉冲干扰所引
  92.         起的采样值偏差,不适用于脉冲干扰比较严重的场合
  93.   输入值:无
  94.   返回值:sum:滤波结果
  95.         备注:N=2^x次方 为宜
  96. ***************************************************/
  97. unsigned short int FILTER_recursive()                                        //递推平均滤波  N为队列长度
  98. {
  99.         unsigned short int sum=0;
  100.         unsigned char count=0;
  101.         static unsigned char i=0,num=0;
  102.         static unsigned short int value_temp[N];
  103.         do{
  104.         if(i<N)                                                                                                        //每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据。(先进先出原则)
  105.         {                                                                                                                                //把队列中的N个数据进行算术平均运算,就可获得新的滤波结果
  106.                 value_temp[i] = AD_VALUE;
  107.                 i++;
  108.                 i=(i==N)?0:i;                                                                        //三目运算 i清零
  109.         }
  110.         num++;
  111.         num=num<N?num:N;
  112. }while(num<N);
  113.         for(count=0;count<N;count++)               
  114.                 sum += value_temp[count];
  115.       
  116.         sum = sum/N;        
  117.         return sum;
  118. }



  119. /*****************************************************************
  120.   函数名:FILTER_firstorder
  121.   描  述:一阶滞后滤波:取a=(0,1)
  122.         本次滤波结果result=(1-a)*本次采样值+a*上次值
  123.         对周期性干扰具有良好的抑制作用,
  124.         适用于波动频率较高得场合。缺点就是相位滞后,灵敏度低,
  125.         滞后程度取决于a的大小,不能消除滤波频率高于采样频率1/21/2的干扰信号
  126.   输入值:无
  127.   返回值:value:滤波结果
  128.         备注:A取值0——100 A值越小,滤波结果越平稳,但是灵敏度越低
  129.                                                                                  A值越大,灵敏度越高,但是滤波结果越不稳定
  130. *****************************************************************/
  131. unsigned short int FILTER_firstorder()                                        //一阶滞后滤波,A取值0——100  
  132. {                                                                                                                                                        
  133.         static unsigned short int value=0;                                                
  134.         unsigned short int new_value;
  135.         value = (value==0)?AD_VALUE:value;        // 三目运算,避免第一次采样value值为0
  136.         new_value = AD_VALUE;                                                               
  137.         
  138.         value = (100-A)*value/100 + A*new_value/100;
  139.         return value;
  140. }
复制代码

  1. /*********************************************************
  2. *文件名:  filter.h
  3. *日  期:  2018/7/26
  4. *描  述:  AD滤波算法函数头文件
  5. *备  注:  
  6. **********************************************************/
  7. #ifndef __FILTER_H__
  8. #define __FILTER_H__

  9. //typedef unsigned          char uint8_t;
  10. //typedef unsigned short     int uint16_t;
  11. //typedef unsigned           int uint32_t;
  12. //typedef unsigned       __int64 uint64_t;

  13. typedef enum {OFF = 0x0, ON = 0x1} TYPE_STATE;


  14. extern unsigned short int meanvalue;                                //        ADC值声明 meanvalue根据情况改变

  15. #define  AD_VALUE          meanvalue                //        ADC采集值 meanvalue根据情况改变可直接宏定义AD函数
  16. #define A 50                                                                                // 一阶滞后滤波系数
  17. #define N 9                                                                                // 采样次数 不同的滤波方法取值不同
  18. #define TIME        300                                                        //AD读取延时,等待AD采集完成 大致够AD采集时间即可

  19. /******** 函******* 数 ******* 声 ******* 明 ********/
  20. unsigned short int FILTER_limit(void);                  //限幅滤波
  21. unsigned short int FILTER_median(TYPE_STATE Flag);                  //中位值滤波   中位值平均滤波 Flag:中位值平均滤波使能
  22. unsigned short int FILTER_recursive(void);        //递推平均滤波
  23. unsigned short int FILTER_firstorder(void);        //一阶滞后滤波

  24. #endif

复制代码


所有资料51hei提供下载:
滤波算法.rar (43.04 KB, 下载次数: 258)


评分

参与人数 2黑币 +55 收起 理由
hzd530 + 5 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏13 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:517610 发表于 2019-4-21 10:32 | 只看该作者
好东西啊,多谢楼主分享
回复

使用道具 举报

板凳
ID:517610 发表于 2019-4-21 10:41 | 只看该作者
这些滤波算法确实挺适合单片机使用,简单方便,哈,谢谢楼主分享
回复

使用道具 举报

地板
ID:225960 发表于 2019-4-21 18:35 | 只看该作者
可以的,码农的搬运工,学习了,正好最近在学习32的AD数据采集
回复

使用道具 举报

5#
ID:346927 发表于 2019-5-17 21:16 | 只看该作者
非常好的资料,多谢楼主分享
回复

使用道具 举报

6#
ID:18591 发表于 2019-5-19 19:38 | 只看该作者
THANSK ~~~~~~~~~~~~
回复

使用道具 举报

7#
ID:511677 发表于 2019-5-23 12:51 | 只看该作者
正是我需要的,谢谢。
回复

使用道具 举报

8#
ID:20672 发表于 2019-9-14 22:48 | 只看该作者
谢谢分享~~
回复

使用道具 举报

9#
ID:428438 发表于 2019-9-16 10:30 | 只看该作者
谢谢楼主,不错。以前AD数据都没有考虑滤波。。。
回复

使用道具 举报

10#
ID:71535 发表于 2019-9-16 18:54 | 只看该作者
东西比较丰富,大家保存备用
回复

使用道具 举报

11#
ID:124631 发表于 2019-10-8 11:07 | 只看该作者
大自然的搬运工
回复

使用道具 举报

12#
ID:142699 发表于 2019-10-9 09:24 | 只看该作者
这个写法比较基础,用结构体写的话会更好用一些
回复

使用道具 举报

13#
ID:68129 发表于 2019-11-7 16:34 | 只看该作者
谢谢分享
回复

使用道具 举报

14#
ID:68129 发表于 2019-11-7 16:39 | 只看该作者
学习了,之前只做了中值平均滤波
回复

使用道具 举报

15#
ID:298628 发表于 2019-11-9 11:36 | 只看该作者
谢谢大佬的分享
回复

使用道具 举报

16#
ID:46475 发表于 2019-12-7 10:43 | 只看该作者
好东西,感谢分享
回复

使用道具 举报

17#
ID:65956 发表于 2019-12-7 14:39 | 只看该作者
源码中有几处带问号“?”的应是什么?
num=num<N?num:N;

value = (value==0)?AD_VALUE:value;        // 三目运算,避免第一次采样value值为0
回复

使用道具 举报

18#
ID:607998 发表于 2020-4-15 15:16 | 只看该作者
谢谢分享~~
回复

使用道具 举报

19#
ID:108573 发表于 2020-4-16 10:58 | 只看该作者
不错,每天来逛逛,下载点资料
回复

使用道具 举报

20#
ID:72029 发表于 2020-4-30 11:30 | 只看该作者
不错,值得参考
回复

使用道具 举报

21#
ID:392070 发表于 2020-6-16 19:53 | 只看该作者
感谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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