当前位置:   article > 正文

STM32实战七 数字滤波_stm32 滤波算法

stm32 滤波算法

数字滤波是数据处理是常用、灵活、有效的方法。前面的按键程序已经用到了滤波,属于开关量滤波,这里要讨论的是模拟量滤波程序,包括最常用的两种方法,中值滤波和平均值滤波。

中值滤波的原理是,每次取最近几个数的中间值作为输出数据,每个波形的最高和最低几个数被滤掉,优点是基本保留原有数据,能有效抑制大幅值低频尖峰干扰,俗称椒盐噪声

平均值滤波,就是对最近一些数求平均,是最常用最简单的方法,对高频低幅值随机噪声有效,缺点是会损失原始数据中的高频分量,对高幅值干扰会扩大影响。下面的程序中应用了移位平均算法,效率高,且不受求平均的数据数目大小的影响。两种滤波方式都有一定延时。

AverageFilter.h

  1. #ifndef __AVERAGEFILTER__
  2. #define __AVERAGEFILTER__
  3. extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段
  4. #pragma diag_remark 368 //消除 warning: #368-D: class "<unnamed>" defines no constructor to initialize the following:
  5. #include "stm32f10x.h"
  6. #pragma diag_default 368 // 恢复368号警告
  7. }
  8. #define AF_MAXWINDOW 150 // 最大窗宽150
  9. class AverageFilter
  10. {
  11. // Construction
  12. public:
  13. AverageFilter( s32 ini, u16 nNum );
  14. // Properties
  15. public:
  16. u16 m_number; // 指定平均的个数,最多150
  17. u16 m_seek; // 游标
  18. s32 m_summation; // 指定数组的总和
  19. s32 m_input[AF_MAXWINDOW]; // 数据缓存
  20. private:
  21. // Methods
  22. public:
  23. s32 filter( s32 vi ); // 滤波算法
  24. // Overwrite
  25. public:
  26. };
  27. #endif

AverageFilter.cpp

  1. /**
  2. ******************************************************************************
  3. * @file AverageFilter.cpp
  4. * @author Mr. Hu
  5. * @version V1.0.0 STM32F103VET6
  6. * @date 06/06/2019
  7. * @brief 均值滤波
  8. ******************************************************************************
  9. * @remarks
  10. * 采用移位平均法,大大提高效率,不受数据数量的影响
  11. */
  12. /* Includes ------------------------------------------------------------------*/
  13. extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段
  14. #pragma diag_remark 368 //消除 warning: #368-D: class "<unnamed>" defines no constructor to initialize the following:
  15. #pragma diag_default 368 // 恢复368号警告
  16. }
  17. #include "AverageFilter.h"
  18. /**
  19. * @date 06/06/2019
  20. * @brief 均值滤波
  21. * @param ini 初始值,避免前几个输出数偏差太大
  22. * @param nNum 滤波数量,最大150,越大效果越好,但延时较多
  23. * @retval None
  24. */
  25. AverageFilter::AverageFilter( s32 ini, u16 nNum )
  26. : m_number(nNum)
  27. , m_seek(0)
  28. , m_summation(0)
  29. {
  30. if( m_number > AF_MAXWINDOW ) // 控制在数组范围内
  31. m_number = AF_MAXWINDOW;
  32. // 初始化数组
  33. for( int i = 0; i < AF_MAXWINDOW; i++ )
  34. {
  35. m_input[i] = ini;
  36. }
  37. // 初始化总和
  38. m_summation = ini * m_number;
  39. }
  40. /**
  41. * @date 06/06/2019
  42. * @brief 滤波算法,采用移位算法,减去第一个,加上最后一个。
  43. * @param vi 输入数据
  44. * @retval 滤波后输出数据
  45. */
  46. s32 AverageFilter::filter( s32 vi )
  47. {
  48. m_summation += ( vi - m_input[m_seek] ); // 总和中减去最早的数,加上新数
  49. // 用循环方法记录输入数据
  50. assert_param(m_number <= AF_MAXWINDOW);
  51. m_input[m_seek] = vi;
  52. if (++m_seek >= m_number)
  53. m_seek = 0;
  54. // 返回平均值
  55. return m_summation / m_number;
  56. }

MedianFilter.h

  1. #ifndef __MEDIANFILTER__
  2. #define __MEDIANFILTER__
  3. extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段
  4. #pragma diag_remark 368 //消除 warning: #368-D: class "<unnamed>" defines no constructor to initialize the following:
  5. #include "stm32f10x.h"
  6. #pragma diag_default 368 // 恢复368号警告
  7. }
  8. #define DF_MAXWINDOW 21 // 最大窗宽,奇数,太大了反而不好
  9. class MedianFilter
  10. {
  11. // Construction
  12. public:
  13. MedianFilter( s32 ini, u16 nNum );
  14. // Properties
  15. public:
  16. u16 m_dfMedian; // 半窗宽,最大10
  17. u16 m_seek; // 输入数据指针
  18. s32 m_input[DF_MAXWINDOW]; // 输入数据,循环使用,不用移位,提高效率
  19. s32 m_sort[DF_MAXWINDOW]; // 排序数据,最近输入的数据排序,取中间值输出
  20. private:
  21. // Methods
  22. public:
  23. s32 filter( s32 vi ); // 滤波算法
  24. // Overwrite
  25. public:
  26. };
  27. #endif

MedianFilter.cpp

  1. /**
  2. ******************************************************************************
  3. * @file MedianFilter.cpp
  4. * @author Mr. Hu
  5. * @version V1.0.0 STM32F103VET6
  6. * @date 06/05/2019
  7. * @brief 中值滤波
  8. ******************************************************************************
  9. * @remarks
  10. * 中值滤波的原理是,每次取最近几个数的中间值作为输出数据,每个波形的最高和最低
  11. * 几个数被滤掉,优点是基本保留原有数据,相当于去掉几个最高数,去掉几个最低数,能有
  12. * 效抑制大幅值低频尖峰干扰,俗称椒盐噪声。
  13. */
  14. /* Includes ------------------------------------------------------------------*/
  15. extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段
  16. #pragma diag_remark 368 //消除 warning: #368-D: class "<unnamed>" defines no constructor to initialize the following:
  17. #pragma diag_default 368 // 恢复368号警告
  18. }
  19. #include "MedianFilter.h"
  20. /**
  21. * @date 06/05/2019
  22. * @brief 中值滤波
  23. * @param ini 初始值,前几个输出数都是这个值
  24. * @param nNum 滤波数,最大10,越大效果越好,但延时较多
  25. * @retval None
  26. */
  27. MedianFilter::MedianFilter( s32 ini, u16 nNum )
  28. : m_dfMedian(nNum)
  29. , m_seek(0)
  30. {
  31. if( m_dfMedian > (DF_MAXWINDOW - 1) / 2 ) // 中值限制在数组范围内
  32. m_dfMedian = (DF_MAXWINDOW - 1) / 2;
  33. // 初始化两个数组
  34. for( int i = 0; i < DF_MAXWINDOW; i++ )
  35. {
  36. m_input[i] = ini;
  37. m_sort[i] = ini;
  38. }
  39. }
  40. /**
  41. * @date 06/05/2019
  42. * @brief 滤波算法
  43. * @param vi 输入数据
  44. * @retval 滤波后输出数据
  45. */
  46. s32 MedianFilter::filter( s32 vi )
  47. {
  48. u8 w1 = m_dfMedian * 2; // 窗宽-1
  49. assert_param(w1 < DF_MAXWINDOW);
  50. // 计算将要移除的值在排序数组中的位置
  51. u8 j = 0;
  52. for (; j <= w1 && m_input[m_seek] != m_sort[j]; j++);
  53. // 移除最早的数据并把新数据插入到适当的位置
  54. // 如果新数据在较小半段,数据后移,否则数据前移,实现排序
  55. // 只处理大于和小于情况,等于时不动
  56. if (vi < m_input[m_seek])
  57. { // 向前移
  58. while (j > 0 && vi < m_sort[j-1])
  59. {
  60. j--;
  61. m_sort[j + 1] = m_sort[j];
  62. }
  63. }
  64. else if (vi > m_input[m_seek])
  65. { // 向后移
  66. while (j < w1 && vi > m_sort[j+1])
  67. {
  68. j++;
  69. m_sort[j - 1] = m_sort[j];
  70. }
  71. }
  72. // 加入新值
  73. assert_param(j >= 0 && j < w);
  74. m_sort[j] = vi;
  75. // 用循环方法记录输入数据,高效
  76. m_input[m_seek] = vi;
  77. if (++m_seek > w1)
  78. m_seek = 0;
  79. // 返回中间值
  80. return m_sort[m_dfMedian];
  81. }

STM32实战系列源码,按键/定时器/PWM/ADC/DAC/DMA/滤波
STM32实战一 初识单片机
STM32实战二 新建工程
STM32实战三 C++ IO.cpp
STM32实战四 定时器和按键
STM32实战五 板载LED显示数据
STM32实战六 PWM加移相正交
STM32实战七 数字滤波
STM32实战八 DAC/ADC
STM32实战九 编码器
STM32开发过程的常见问题

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/236609
推荐阅读
相关标签
  

闽ICP备14008679号