摘要:本文面向嵌入式开发者,介绍基于纯整数运算的二阶滤波器设计,核心公式为 Yn = aXn + bYn-1 + cYn-2,其中 a + b + c = 2^N(N 为右移位数)。通过右移运算替代浮点除法,实现高效、稳定的信号平滑。重点解析三种实用变体:八分之一滤波器(a=1, b=3, c=4)提供平衡的响应与平滑性;十六分之一滤波器(a=1, b=6, c=9)侧重深度平滑与噪声抑制;四分之一滤波器(a=1, b=1, c=2)追求快速响应。涵盖系数设计、稳定性分析、C 语言实现及实战选型,为资源受限系统提供即插即用的滤波方案。本文适合嵌入式开发者、信号处理工程师,解决在资源受限系统中实现高效、稳定的实时信号滤波问题。通过纯整数运算和右移优化,提供三种二阶滤波器变体:八分之一(平衡型)、十六分之一(深度平滑型)、四分之一(快速响应型),涵盖从原理到实战的完整方案,可直接应用于 ADC 采样、传感器数据平滑等场景。目录1. 二阶滤波器设计原理2. C语言实现:八分之一二阶滤波器3. 滤波器对比4. 应用场景与选型建议4.1 八分之一二阶滤波器 (a=1, b=3, c=4)4.2 十六分之一二阶滤波器 (a=1, b=6, c=9)4.3 四分之一二阶滤波器 (a=1, b=1, c=2)4.4 综合选型指南4.5 实战案例:ADC采样滤波二阶滤波器设计原理二阶滤波器采用递推形式 Yn = aXn + bYn-1 + cYn-2,其中 Xn 为当前输入,Yn-1 和 Yn-2 为前两次输出。这种结构通过将当前输入与历史输出加权组合,实现对信号的低通滤波效果。系数 a、b、c 的选取决定了滤波器的频率响应特性。要求系数满足 a + b + c = 2^N (N 为右移位数) 具有重要的物理意义:当输入为直流信号(恒定值)时,滤波器的稳态输出将等于输入值,即直流增益为 1。这保证了滤波器不会改变信号的直流分量,只对交流分量(变化部分)进行平滑处理。在实际应用中,通过将系数设计为 2^N 的倒数形式(如 1/8、1/16、1/4),可以利用右移运算高效实现整数除法,特别适合嵌入式系统等资源受限环境。这是一种简单的二阶滤波器数字表达式。Yn = aXn + bYn-1 + cYn-2这里 a + b + c = 2^N (N为右移位数),为了方便计算,取 a = 1,b = 3,c = 4,表达式变为:Yn = [Xn + 3Yn-1 + 4Yn-2] 3可以简称为八分之一二阶滤波器。系数设计依据:系数 a=1, b=3, c=4 的设计并非基于传统的巴特沃斯或切比雪夫滤波器传递函数,而是为了满足以下工程约束:整数运算友好:系数均为整数,便于嵌入式系统实现右移运算优化:a+b+c=2^3 (N=3),右移3位相当于除以8,避免浮点除法频率响应特性:b=3, c=4 的比值关系提供了适中的阻尼比,在响应速度和平滑性之间取得平衡稳定性保证:系数满足 |b|+|c|1 的简化稳定性条件(实际为3+4=78,但通过右移归一化后满足)为了快速接近真实值,前两次采样可以不用滤波算法,把这两个值赋初值。再举一例,取 a = 1,b = 6,c = 9,a + b + c = 2^4 (N=4)。Yn = [Xn + 6Yn-1 + 9Yn-2] 4可以简称十六分之一二阶滤波器。系数设计依据:a=1, b=6, c=9 的设计同样基于工程实用考虑:更大的分母:a+b+c=16,右移4位实现除以16,提供更精细的量化精度更强的平滑效果:b和c的比值(6:9=2:3)使滤波器具有更低的截止频率,对高频噪声抑制更强保持整数系数:所有系数均为整数,避免浮点运算响应速度权衡:相比八分之一滤波器,十六分之一滤波器响应更慢但平滑性更好,适用于对噪声抑制要求更高的场景也可以取 a = 1,b = 1,c = 2,a + b + c = 4,简称为四分之一二阶滤波器,具有更快响应速度,比起四分之一一阶滤波器,更具有数据平滑性和稳定性。通用设计原则:这些系数设计主要基于以下考虑而非传统滤波器理论:分母为2的幂次:8、16、4都是2的幂次,便于用右移运算替代除法系数比为简单整数:便于硬件乘法器实现(3、4、6、9等系数可通过移位和加法实现)经验调优:通过实际测试确定系数比,在响应速度、平滑性和计算复杂度之间取得平衡归一化约束:始终满足 a+b+c=2^n,确保直流增益为1稳定性分析:在整数运算和右移归一化条件下,文中三种滤波器(八分之一、十六分之一、四分之一)的稳定性判断需要特别关注。对于二阶递推滤波器 Yn = aXn + bYn-1 + cYn-2,其稳定性由特征方程 z² - bz - c = 0 的根决定。在整数实现中,由于系数经过右移归一化,实际参与递推的系数是 b/2ⁿ 和 c/2ⁿ(n为右移位数)。稳定性判据要求特征根位于单位圆内,即 |b/2ⁿ| + |c/2ⁿ| 1。对于文中三种滤波器:八分之一滤波器(a=1, b=3, c=4, n=3):|3/8| + |4/8| = 0.375 + 0.5 = 0.875 1,满足稳定性条件。十六分之一滤波器(a=1, b=6, c=9, n=4):|6/16| + |9/16| = 0.375 + 0.5625 = 0.9375 1,满足稳定性条件。四分之一滤波器(a=1, b=1, c=2, n=2):|1/4| + |2/4| = 0.25 + 0.5 = 0.75 1,满足稳定性条件。从数学上看,三种滤波器都满足 |b| + |c| 2ⁿ 的条件,因此是稳定的。但在实际整数运算中还需注意:溢出问题:计算 Xn + b·Yn-1 + c·Yn-2 时,中间结果可能超出整数范围。例如,当 Yn-1 和 Yn-2 较大时,b·Yn-1 + c·Yn-2 可能溢出。预防措施包括:使用足够位宽的整数类型(如 int32_t 或 int64_t),或在计算前检查数值范围。量化误差累积:右移运算会引入截断误差,长期运行可能导致输出漂移。可通过定期重置滤波器状态或使用舍入(而非截断)来缓解。初始值影响:前两次采样直接赋初值可避免因零初始状态引起的过大瞬态响应,但若初值与实际信号差异较大,仍会有一段过渡过程。总体而言,文中三种滤波器在系数设计时已隐含考虑了稳定性约束,通过右移归一化确保了 |b/2ⁿ| + |c/2ⁿ| 1。在实际应用中,只要注意溢出防护和量化误差,即可获得稳定可靠的滤波效果。C语言实现:八分之一二阶滤波器下面是一个完整的C语言函数实现,用于计算八分之一二阶滤波器(a=1, b=3, c=4)。/** * 八分之一二阶滤波器实现 * 滤波器表达式:Y_n = [X_n + 3*Y_{n-1} + 4*Y_{n-2}] 3 * * @param xn 当前输入采样值(整数) * @param prev1 上一次滤波输出值 Y_{n-1}(整数指针,用于更新历史状态) * @param prev2 上上次滤波输出值 Y_{n-2}(整数指针,用于更新历史状态) * @param is_initial 是否为前两次采样(初始值处理标志) * @return 当前滤波输出值 Y_n */ int one_eighth_second_order_filter(int xn, int* prev1, int* prev2, int is_initial) { int yn; if (is_initial) { // 前两次采样:直接使用输入值作为输出,并更新历史状态 yn = xn; *prev2 = *prev1; // 将上一次值移到上上次 *prev1 = yn; // 更新上一次值为当前输出 return yn; } // 正常滤波计算:Y_n = [X_n + 3Y_{n-1} + 4Y_{n-2}] 3 // 使用整数运算,右移3位相当于除以8(八分之一) yn = (xn + 3 * (*prev1) + 4 * (*prev2)) 3; // 更新历史状态 *prev2 = *prev1; // 上一次值变为上上次 *prev1 = yn; // 当前输出变为上一次值 return yn; } /** 简单的调用示例 */ int main() { // 模拟输入采样序列(例如来自ADC的原始数据) int input_samples[] = {100, 105, 98, 102, 110, 95, 103, 108}; int sample_count = sizeof(input_samples) / sizeof(input_samples[0]); // 滤波器状态初始化 int prev1 = 0; // Y_{n-1} 初始值 int prev2 = 0; // Y_{n-2} 初始值 int is_ini