数字滤波器介绍 详细原理+代码讲解 第一章为什么需要滤波器在嵌入式系统中ADC模拟转数字转换器采集到的信号往往包含噪声。例如电源纹波干扰导致电压读数抖动温度变化引起传感器漂移高频开关噪声叠加在低频信号上如果直接使用原始 ADC 数据来做数据处理和控制这些噪声会导致控制量频繁跳变进而影响系统稳定性。滤波器的作用就是对一系列采样值进行数学处理输出一个平滑、稳定、更接近真实值的结果。1.1 常见滤波器类型对比类型原理优点缺点简单平均N个值求和除以N简单准确响应慢内存大滑动平均固定窗口滚动求平均稳定O(1)计算窗口固定不灵活EWMA指数加权旧值×(1-α) 新值×α内存小响应可调存在截断误差简单平均较为简单本文不做阐述只针对多点滑动平均和EWMA指数加权说明。第二章多点滑动平均滤波器2.1 基本原理滑动平均的核心思想始终保留最近新的N 个采样值每次新值到来时加入新值、丢弃最老的值重新计算平均。下面以16举例。当 N16时平均值 最近16个采样值之和 ÷ 16关键不每次重新对16个值求和而是维护一个「累加和」每次只做一次加法和一次减法。具体代码实现如下2.2 数据结构#define SIZE 16 // 窗口大小 #define SMA_BITS 4 #define SMA_MASK 0x0F typedef struct { sint32 sum; // 累加和窗口大小 sint16 buf[SIZE]; // 数组缓冲区 sint16 sumAvg; // 输出的平均值 uint8 head; // 数组索引值 }SMA_FilterDef;2.3 算法实现void SMA_Fast_Update(SMA_FilterDef*f, sint16 new_val) { f-sum new_val; // 新值加入累加和 f-sum - f-buf[f-head]; // 减去最旧的值 f-buf[f-head] new_val; // 新值放入缓冲区 f-sumAvg f-sum SMA_BITS; // 右移代替除法 f-head (f-head 1) SMA_MASK; // 索引循环递增(0-15) }2.4 关键设计解析为什么用 4 而不是 ÷ 16在 DSP 处理器上除法指令开销很大需要多个时钟周期而位移操作只需 1 个时钟周期。由于 16 2^4所以 4 与 ÷ 16 完全等价且速度更快。为什么步骤2要在步骤4之前步骤2需要先读取旧值来做减法步骤3才覆盖这个位置。若顺序颠倒减去的就是新值本身导致计算错误。溢出风险分析INT16S 范围±32767累加 32 个最大值32767 × 16 524,272INT32S 范围±2,147,483,647远大于 524,272安全无溢出第三章EWMA 指数加权移动平均滤波器3.1 基本原理EWMAExponentially Weighted Moving Average本质是一种RC 低通滤波器公式为output output × (1 - α) input × α其中 α 是平滑系数0 α 1旧值权重 (1 - α)新值权重 αα 越大响应越快但平滑效果越弱跟随输入变化α 越小响应越慢但平滑效果越强对突变不敏感3.2 整数实现在嵌入式系统中通常很少使用浮点运算需要用整数近似实现加快运算和响应速度但会有精度损失。权重α计算如下根据RC低通滤波器微分方程使用零阶保持ZOH离散化后可得α 1 - e^(-T/τ )其中τ RC时间常数T 采样周期 1/f当T τ采样频率远小于信号频率嵌入式系统通常满足时按照泰勒公式展开e^x只保留一阶项高阶项可以忽略不记近似简化为α ≈ T/τ注意计算α时可以使用分数分子分母尽量取2的次方这样可以保证使用移位运算经计算本例程使用 α 16/256 1/16这样公式可以改写为如下形式output (output * 240 input * 16) 8验证240 16 256 2^8权重之和 256 8 等价于 ÷ 256完全等效。3.3 代码分析uint32 RealVoltAvg; uint32 RealVolt; RealVoltAvg (RealVoltAvg* 240 RealVolt * 16) 8;3.4 收敛过程示例输入 100调用次数计算过程输出值0初始—01(0×240 421×16)862(26×240 421×16)81110...4320...67.........40(84×240 100×16)885卡住出现上述情况是因为第40次达到稳定点同时取整会丢掉小数无法收敛到最终稳定点100,存在15误差也称截断误差。3.5 稳定点条件当滤波器输出不再变化时称为达到「稳定点」。稳定点满足f(X) (X * 240 N * 16) 8 X第四章截断误差详解4.1 什么是截断误差整数右移操作会丢弃小数部分这种丢弃称为「截断」。例如6.75 → 取整截断 → 6丢弃了 0.754.2 解决方法余数累积最精确原理每次 8 截断的余数低 8 位不丢弃存入变量下一次运算时加回来彻底消除截断误差。static uint32 e_decimal; // 保存每次小数误差 uint32 RealVoltAvg; uint32 RealVolt; uint32 sum; sum (RealVoltAvg* 240 RealVolt * 16) e_decimal; e_decimal sum 0xFF; // 保存本次余数低8位 RealVoltAvg (uint16)(sum 8);如此可以稳定收敛到目标点100。第五章总结上述两种滤波为常见滤波器方式滑动平均是最近 N 个数据直接平均”更稳定EWMA 指数加权移动平均滤波是“旧值保留 新值少量更新”计算更快响应较快。