欢迎光临深圳市海芯微半导体有限公司官网

GD兆易创新|雅特力|极海半导体|国民技术|MCU代理商

国内品牌MCU/单片机授权代理商

MCU/单片机应用解决方案供应商

咨询热线

13352916901
当前位置:主页 > 常见问题 >

单片机开发中常用的7种滤波算法

文章出处:未知 人气:发表时间:2025-07-09 17:58
       在每一个嵌入式项目中,工程师都像一位在嘈杂环境中努力捕捉清晰声音的调音师。来自传感器的原始数据,就如同混杂着环境噪声
 
的初始音源,而滤波算法,正是我们手中那款功能各异的“调音台”。我们的挑战在于,这个“调音台”——微控制器(MCU)——性能并非无
 
限,它的计算速度和内存空间都极其宝贵,并且整个系统还要求我们做出近乎实时的响应。是在追求极致平滑的信号时耗尽MCU的算力,
 
还是选择一个轻量级方案以保证系统的流畅运行?这正是一门关于“权衡与取舍”的艺术。为了帮助您在这门艺术中游刃有余,我们精选了
 
7种嵌入式开发中最常用、最高效的滤波算法。接下来,让我们一同探索这些工具的特性,学习如何为您的项目搭配出最优的“滤波组合拳”。
 
  1.限幅滤波法(Clipping Filter)
 
   原理:设定一个允许的最大偏差阈值。当采集到新值时,将其与上一次的有效值比较,如果二者差值的绝对值超过该阈值,就认为新值
 
是无效的“野点”,并用上一次的值来代替它。
 
  优点:实现非常简单,计算开销极小。能有效消除偶然出现的、幅度很大的脉冲干扰。
 
  缺点:对于连续的、小幅度的噪声无能为力。如果信号本身变化就很快,可能会将正常的信号变化当作干扰滤除。
 
  适用场景:测量值基本稳定,但偶尔会受到强干扰导致数据跳变。如:ADC采样、数字量输入检测。
 
  #include"filter.h"
 
  #define DEVIATION 10
 
  float limit_filter(float new_value)
 
  {
 
  static int num=0;
 
  static float value=0;//需要赋一个初值
 
  num++;
 
  if(num==1)
 
  value=new_value;
 
  else
 
  {
 
  if((new_value-value>DEVIATION)||(value-new_value>DEVIATION))
 
  return value;
 
  }
 
  return new_value;
 
  }
 
  2.中位值滤波法(Median Filter)
 
  原理:开辟一个N个元素的缓冲区,连续采集N个样本放入其中(N通常取奇数,如3,5,7)。将这N个样本进行排序,取最中间的那个值
 
作为本次滤波的输出。
 
  优点:对椒盐噪声(随机出现的尖峰脉冲)有极佳的抑制效果。相比均值滤波,它能更好地保留信号的边缘细节,不易模糊。
 
  缺点:需要一个缓冲区来存储N个样本,占用RAM。排序过程消耗CPU资源,在N较大时,计算量会明显增加。
 
  适用场景:信号中存在不规则的尖峰干扰,且需要保留信号的跳变特性。如:有开关噪声干扰的传感器、图像处理领域。
 
  #include"filter.h"
 
  #define MIDDLE_FILTER_N 11
 
  float middle_filter(float new_value)
 
  {
 
  static float value_buf[MIDDLE_FILTER_N];
 
  float temp;
 
  uint8_t count,i;
 
  for(count=0;count<MIDDLE_FILTER_N-1;count++)
 
  {
 
  value_buf[count]=value_buf[count+1];
 
  }
 
  value_buf[MIDDLE_FILTER_N-1]=new_value;
 
  for(i=MIDDLE_FILTER_N;i>0;i--)
 
  {
 
  #if 0
 
  if(value_buf<i><value_buf[i-1])
 
  {
 
  temp=value_buf<i>;
 
  value_buf<i>=value_buf[i-1];
 
  value_buf[i-1]=temp;
 
  }
 
  #endif
 
  if(value_buf<i>>0)
 
  {
 
  if(value_buf<i><value_buf[i-1])
 
  {
 
  temp=value_buf<i>;
 
  value_buf<i>=value_buf[i-1];
 
  value_buf[i-1]=temp;
 
  }
 
  }
 
  else if(value_buf<i><0)
 
  {
 
  if(value_buf<i>>value_buf[i-1])
 
  {
 
  temp=value_buf<i>;
 
  value_buf<i>=value_buf[i-1];
 
  value_buf[i-1]=temp;
 
  }
 
  }
 
  }
 
  return value_buf[(MIDDLE_FILTER_N-1)/2];
 
  }
 
  3.算术平均滤波法(Arithmetic Mean Filter)
 
  原理:连续采集N个样本,将这N个样本值求和,再除以N,得到的结果即为滤波输出。为了提高实时性和效率,通常使用“滑动平均”
 
(Moving Average)的方式实现。
 
  优点:对周期性、符合高斯分布的随机噪声有很好的平滑效果。算法简单,N越大,信号越平滑。
 
  缺点:对信号变化的响应迟钝,有明显的滞后。对偶然的脉冲干扰抑制效果差,一个坏点会拉偏整个平均值。
 
  适用场景:信号变化缓慢、实时性要求不高的场合。如:测量温度、湿度、电压等慢变量。
 
  #include"filter.h"
 
  #define AVERAGE_N 12
 
  float average_filter(float new_value)
 
  {
 
  static float average_value_buf[AVERAGE_N];
 
  static float average_sum=0;
 
  uint8_t count;
 
  average_sum-=average_value_buf[0];
 
  for(count=0;count<AVERAGE_N-1;count++)
 
  {
 
  average_value_buf[count]=average_value_buf[count+1];
 
  }
 
  average_value_buf[AVERAGE_N-1]=new_value;
 
  average_sum+=average_value_buf[11];
 
  return(average_sum/(AVERAGE_N*1.0));
 
  }
 
  4.消抖滤波法(Debounce Filter)
 
  原理:此算法专门用于处理机械开关(如按键)的抖动。它不是平滑模拟信号,而是确认一个数字状态的改变。方法是检测到输入状态
 
变化后,等待一个短暂的延时(如20ms),再次确认输入状态是否与之前一致。如果一致,才认为状态真正发生了改变。
 
   优点:能可靠地消除机械触点闭合与断开瞬间的电平抖动。是处理按键、开关等数字输入必不可少的环节。
 
  缺点:会带来一个固定的响应延迟。不适用于模拟量的滤波。
 
  适用场景:所有机械按键、开关、继电器等数字量输入信号的检测。
 
  #include"filter.h"
 
  #define SHAKE_N 12
 
  float shake_filter(float new_value,float now_value)
 
  {
 
  static uint8_t count=0;
 
  if(now_value!=new_value)
 
  {
 
  count++;
 
  if(count>=SHAKE_N)
 
  {
 
  count=0;
 
  return new_value;
 
  }
 
  }
 
  return now_value;
 
  }
 
  5.一阶滞后滤波法(First-Order Lag Filter)
 
  原理:也常被称为一阶低通滤波或RC滤波。它模拟了硬件RC电路的滤波效果。其核心是一个递推公式:本次输出=A*本次采样+(1-A)*
 
上次输出。系数A(0<A<1)决定了滤波的强度,A越小,滤波效果越平滑,但响应越慢。
 
  优点:计算量极小,资源消耗低,只需存储上一次的输出值实时性好,平滑度可以通过调整系数A来灵活控制。
 
  缺点:存在相位滞后。对脉冲干扰抑制能力一般。
 
  适用场景:通用性极强,是MCU中最常用的滤波算法之一,适用于绝大多数需要平滑处理且对实时性有要求的模拟量。
 
  #include"filter.h"
 
  #define FIRST_LAG_PROPORTION 0.4
 
  float first_order_lag_filter(float new_value)
 
  {
 
  static float first_order_value,first_order_last_value;
 
  first_order_value=first_order_last_value;
 
  first_order_last_value=new_value;
 
  return(1-FIRST_LAG_PROPORTION)*first_order_value+
 
  FIRST_LAG_PROPORTION*new_value;
 
  }
 
  5.加权递推平均滤波法(Weighted Recursive Average Filter)
 
  -------------
 
  原理:这是一阶滞后滤波法的一种延伸和别称。它强调了“递推”(Recursive,本次输出依赖于上次输出)和“加权”
 
(Weighted,对当前采样值和历史滤波结果赋予不同权重)这两个核心思想。一阶滞后滤波法是其最经典、最简单的实现形式。
 
  优点:在平滑度和响应速度之间取得了很好的平衡。资源消耗小,实现高效。
 
  缺点:相比简单的算术平均,理解上稍复杂一点。
 
  适用场景:与一阶滞后滤波法完全相同,适用于需要平衡平滑度和灵敏度的各种场合。
 
  #include"filter.h"
 
  #define WEIGHT_AVERAGE_N 12
 
  uint8_t coe[WEIGHT_AVERAGE_N]={1,2,3,4,5,6,7,8,9,10,11,12};
 
  uint8_t sum_coe=1+2+3+4+5+6+7+8+9+10+11+12;
 
  float weighted_filter(float new_value)
 
  {
 
  static float weight_average_buf[WEIGHT_AVERAGE_N];
 
  uint8_t count;
 
  float sum=0;
 
  for(count=0;count<AVERAGE_N-1;count++)
 
  {
 
  weight_average_buf[count]=weight_average_buf[count+1];
 
  }
 
  weight_average_buf[AVERAGE_N-1]=new_value;
 
  for(count=0;count<WEIGHT_AVERAGE_N;count++)
 
  sum+=weight_average_buf[count]*coe[count];
 
  return(sum/(sum_coe*1.0));
 
  }
 
  7.卡尔曼滤波(Kalman Filter)
 
  原理:一种最优化的自回归数据处理算法。它不仅仅是“滤波”,更是一个“预测-校正”的循环过程。它会建立一个系统状态模型,
 
根据上一时刻的状态预测当前时刻的状态,再用当前的测量值来校正这个预测,从而得到一个最优的估计值。
 
  优点:理论上是处理高斯白噪声下线型系统问题的最优滤波器。非常适合用于融合多种传感器数据
 
(如加速度计和陀螺仪融合姿态解算)。不仅能滤波,还能预测系统状态。
 
  缺点:数学模型复杂,理解和实现难度大。计算量远大于前几种算法,对MCU性能要求高。需要对系统进行精确建模,模型不准会导致
 
效果变差。
 
  适用场景:高精度系统,如飞行器姿态解算(IMU)、机器人定位导航、电池电量SOC估算等。
 
  #include"filter.h"
 
  //一维卡尔曼滤波的简化模型(估计一个恒定电压)
 
  float x_hat=0;//状态的后验估计值(最优估计)
 
  float P=1;//后验估计的协方差(不确定度)
 
  float Q=0.01;//过程噪声协方差(预测模型本身的不确定度)
 
  float R=0.1;//测量噪声协方差(传感器测量的误差)
 
  float K;//卡尔曼增益
 
  float kalman_filter(float measurement){
 
  //1.预测(因为模型是恒定电压,预测值就是上一次的最优值)
 
  float x_hat_minus=x_hat;
 
  float P_minus=P+Q;
 
  //2.更新(校正)
 
  K=P_minus/(P_minus+R);//计算卡尔曼增益
 
  x_hat=x_hat_minus+K*(measurement-x_hat_minus);//更新最优估计
 
  P=(1-K)*P_minus;//更新不确定度
 
  return x_hat;
 
  }

同类文章排行

最新资讯文章

点击这里给我发消息 销售一部
点击这里给我发消息 销售二部
点击这里给我发消息 销售三部
点击这里给我发消息 技术支持