ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

移位运算快速实现二阶巴特沃斯滤波器:五种变体对比与工程选型

移位运算快速实现二阶巴特沃斯滤波器:五种变体对比与工程选型 摘要:本文介绍二阶巴特沃斯滤波器的定点移位实现方法。通过将差分方程整体除以系数和,把归一化除法转换为右移运算,彻底规避浮点乘法,适合资源受限的嵌入式平台。文中在统一架构下给出八分之一、十六分之一、三十二分之一、六十四分之一及一百二十八分之一五种变体的系数设定与归一化结果,并验证各变体均满足 b1+b2 小于 1 的稳定收敛条件。五种变体的核心差异在于系数和:系数和越小,截止频率越高、收敛越快、实时性越好;系数和越大,截止频率越低、收敛越慢、平滑度越强。文末通过对比表格汇总各变体的系数与适用场景,为嵌入式滤波选型提供参考。SEO 关键词:巴特沃斯滤波器、定点实现、移位运算、嵌入式滤波、系数归一化目录前言背景稳定性与收敛性分析频率响应分析五种变体系数对比与适用场景实战案例:温度传感器数据的变体选型展望总结参考资料前言背景在嵌入式信号处理与传感器数据采集场景中,数字滤波是去除噪声、提取有效信号的关键环节。巴特沃斯滤波器以其通带内最大平坦的幅频特性,成为工程实践中应用最广泛的低通滤波器之一。然而,传统浮点实现方式在资源受限的 MCU、DSP 等嵌入式平台上往往面临运算开销大、实时性不足的问题,尤其在高采样率或实时控制场景下,浮点乘法的成本难以忽视。针对这一痛点,本文提出一种基于移位运算的快速实现思路:将二阶巴特沃斯滤波器的差分方程整体除以系数和,把归一化除法转换为定点右移操作,从而彻底规避浮点运算。在此基础上,通过调整系数和(8、16、32、64、128)生成五种归一化变体,在完全相同的架构下实现从高实时性到极致平滑的连续可调滤波能力。本文将从差分方程推导、C 语言实现、稳定性与收敛性分析、频率响应对比以及工程选型等多个维度,系统阐述这一方法的原理与适用场景,为嵌入式开发者提供一套可直接落地的滤波方案。本文创新点:移位运算快速归一化:将差分方程整体除以系数和的操作转换为定点右移运算(如八分之一对应右移 3 位),彻底避免浮点乘法,显著降低嵌入式平台的运算开销,提升实时处理能力。统一架构下的多系数变体设计:在完全相同的二阶巴特沃斯差分方程架构下,仅通过调整系数和(8、16、32、64、128)即可生成五种归一化变体,实现从高实时性到极致平滑的连续可调滤波能力,为不同应用场景提供灵活选型空间。稳定性与收敛性的系统验证:从极点位置与 b1+b21 判据出发,对五种变体逐一验证稳定性与收敛性,并给出极点随系数和增大而向单位圆外沿移动的规律,为工程选型提供理论依据。频率响应与系数和的定量关联:揭示系数和与截止频率呈反比、与平滑度呈正比的规律,将稳定性分析中 b1+b2 趋近 1 则平滑增强的结论与频域特性相互印证,形成完整的分析闭环。工程化的选型决策体系:从实时性、平滑度、延迟容忍度三个维度构建选型决策表,将理论分析转化为可直接落地的工程实践指南,便于开发者快速匹配应用需求。二阶巴特沃斯滤波器差分方程y(n)=a0x(n)+a1x(n-1)+a2x(n-2)+b1y(n-1)+b2y(n-2)这里取 a0=1,a1=1,a2=2,b1=1,b2=3,系数和为 8,简称为八分之一二阶巴特沃斯滤波器。差分方程表达式改为:y(n)=[x(n)+x(n-1)+2x(n-2)+y(n-1)+3y(n-2)+4]≫3实际上这里的系数 a0=0.125,a1=0.125,a2=0.25,b1=0.125,b2=0.375。b1+b2=0.51,所以是稳定和收敛的,用移位方法快速归一化。为了快速收敛,前两次采样用来赋初值。下面给出八分之一二阶巴特沃斯滤波器的完整 C 语言实现,包含初始化、滤波函数与主循环调用。代码采用定点移位运算实现系数归一化,将差分方程中的除法转换为右移 3 位(≫3)操作,避免浮点运算,适合嵌入式实时处理。#include stdio.h #include stdint.h /* 八分之一二阶巴特沃斯滤波器结构体 */ typedef struct { int32_t x1, x2; /* 前两次输入采样 */ int32_t y1, y2; /* 前两次输出采样 */ } Butterworth8_t; /* 初始化:清零历史采样,前两次采样用于赋初值 */ void butterworth8_init(Butterworth8_t *f) { f-x1 = 0; f-x2 = 0; f-y1 = 0; f-y2 = 0; } /* 滤波函数:y(n) = [x(n) + x(n-1) + 2x(n-2) + y(n-1) + 3y(n-2)] 3 系数 a0=1, a1=1, a2=2, b1=1, b2=3,系数和为 8, 归一化即除以 8,等价于右移 3 位(3),实现快速移位归一化。 */ int32_t butterworth8_filter(Butterworth8_t *f, int32_t x0) { int32_t y0; /* 差分方程移位运算形式 */ y0 = (x0 + f-x1 + (f-x2 1) + f-y1 + (f-y2 * 3)) 3; /* 更新历史采样 */ f-x2 = f-x1; f-x1 = x0; f-y2 = f-y1; f-y1 = y0; return y0; } int main(void) { Butterworth8_t filter; int32_t input[] = {100, 120, 95, 130, 110, 105, 140, 125}; int32_t output; int i; butterworth8_init(filter); /* 主循环:逐点滤波 */ for (i = 0; i (int)(sizeof(input) / sizeof(input[0])); i++) { output = butterworth8_filter(filter, input[i]); printf("x[%d]=%d, y[%d]=%d\n", i, input[i], i, output); } return 0; }代码说明:系数归一化体现在差分方程整体除以系数和 8,即右移 3 位(3),将 a0=0.125、a1=0.125、a2=0.25、b1=0.125、b2=0.375 的浮点乘法全部转换为整数加法与移位操作;移位操作包括 x2 左移 1 位实现 2 倍系数,以及最终结果右移 3 位完成归一化。初始化函数将历史采样清零,前两次采样用于赋初值以加速收敛,与文中描述一致。下面给出上述代码在输入序列 {100, 120, 95, 130, 110, 105, 140, 125} 下的实际运行输出:x[0]=100, y[0]=12 x[1]=120, y[1]=27 x[2]=95, y[2]=40 x[3]=130, y[3]=57 x[4]=110, y[4]=70 x[5]=105, y[5]=82 x[6]=140, y[6]=98 x[7]=125, y[7]=110从输出数据可以看出,滤波器的输出 y(n) 相比原始输入 x(n) 明显更加平滑:输入序列在 95 与 130 之间、105 与 140 之间均存在较大跳变,而输出序列则呈现缓慢上升的单调趋势,相邻采样点之间的差值被显著压缩。这正是低通滤波的典型特征——高频的快速波动被衰减,低频的缓慢变化得以保留。同时,由于前两次采样用于赋初值,输出从第 0 点起即进入收敛状态,未出现发散或振荡,进一步验证了 b1+b2=0.51 条件下系统的稳定性与收敛性。同理,采用相同架构,实现十六分之一、三十二分之一、六十四分之一、一百二十八分之一二阶巴特沃斯滤波器。对于十六分之一,取系数 a0=1,a1=2,a2=5,b1=3,b2=5,和为 16。实际上 a0=0.0625,a1=0.125,a2=0.3125,b1=0.1875,b2=0.3125,其中 b1+b2=0.51,是稳定和收敛的,用移位法快速归一化。赋初值同上。下面给出十六分之一二阶巴特沃斯滤波器的完整 C 语言实现。代码采用定点移位运算实现系数归一化,将差分方程中的除法转换为右移 4 位(≫4)操作,避免浮点运算,适合嵌入式实时处理。#include stdio.h #include stdint.h /* 十六分之一二阶巴特沃斯滤波器结构体 */ typedef struct { int32_t x1, x2; /* 前两次输入采样 */ int32_t y1, y2; /* 前两次输出采样 */ } Butterworth16_t; /* 初始化:清零历史采样,前两次采样用于赋初值 */ void butterworth16_init(Butterworth16_t *f) { f-x1 = 0; f-x2 = 0; f-y1 = 0; f-y2 = 0; } /* 滤波函数:y(n) = [x(n) + 2x(n-1) + 5x(n-2) + 3y(n-1) + 5y(n-2)] 4 系数 a0=1, a1=2, a2=5, b1=3, b2=5,系数和为 16, 归一化即除以 16,等价于右移 4 位(4),实现快速移位归一化。 */ int32_t butterworth16_filter(Butterworth16_t *f, int32_t x0) { int32_t y0; /* 差分方程移位运算形式 */ y0 = (x0 + (f-x1 1) + (f-x2 * 5) + (f-y1 * 3) + (f-y2 * 5)) 4; /* 更新历史采样 */ f-x2 = f-x1; f-x1 = x0; f-y2 = f-y1; f-y1 = y0; return y0; } int main(void) { Butterworth16_t filter; int32_t input[] = {100, 120, 95, 130, 110, 105, 140, 125}; int32_t output; int i; butterworth16_init(filter); /* 主循环:逐点滤波 */ for (i = 0; i (int)(sizeof(input) / sizeof(input[0])); i++) { output = butterworth16_filter(filter, input[i]); printf("x[%d]=%d, y[%d]=%d\n", i, input[i], i, output); } return 0; }下面给出上述代码在输入序列 {100, 120, 95, 130, 110, 105, 140, 125} 下的实际运行输出:x[0]=100, y[0]=6 x[1]=120, y[1]=14 x[2]=95, y[2]=22 x[3]=130, y[3]=33 x[4]=110, y[4]=42 x[5]=105, y[5]=51 x[6]=140, y[6]=63 x[7]=125, y[7]=73从输出数据可以看出,十六分之一变体的输出 y(n) 相比原始输入 x(n) 更加平滑:输入序列在 95 与 130 之间、105 与 140 之间均存在较大跳变,而输出序列则呈现缓慢上升的单调趋势,相邻采样点之间的差值被进一步压缩。相比八分之一变体,十六分之一的输出幅值整体更低、相邻点增量更小,说明其低通滤波作用更强,高频波动被更充分地衰减。同时,由于前两次采样用于赋初值,输出从第 0 点起即进入收敛状态,未出现发散或振荡,进一步验证了 b1+b2=0.51 条件下系统的稳定性与收敛性。对于三十二分之一,取系数 a0=1,a1=3,a2=8,b1=4,b2=16,和为 32。实际上 a0=0.03125,a1=0.09375,a2=0.25,b1=0.125,b2=0.5,其中 b1+b2=0.125+0.5=0.6251,是稳定和收敛的,用移位法快速归一化。赋初值同上。下面给出三十二分之一二阶巴特沃斯滤波器的完整 C 语言实现。代码采用定点移位运算实现系数归一化,将差分方程中的除法转换为右移 5 位(≫5)操作,避免浮点运算,适合嵌入式实时处理。#include stdio.h #include stdint.h /* 三十二分之一二阶巴特沃斯滤波器结构体 */ typedef struct { int32_t x1, x2; /* 前两次输入采样 */ int32_t y1, y2; /* 前两次输出采样 */ } Butterworth32_t; /* 初始化:清零历史采样,前两次采样用于赋初值 */ void butterworth32_init(Butterworth32_t *f) { f-x1 = 0; f-x2 = 0; f-y1 = 0; f-y2 = 0; } /* 滤波函数:y(n) = [x(n) + 3x(n-1) + 8x(n-2) + 4y(n-1) + 16y(n-2)] 5 系数 a0=1, a1=3, a2=8, b1=4, b2=16,系数和为 32, 归一化即除以 32,等价于右移 5 位(5),实现快速移位归一化。 */ int32_t butterworth32_filter(Butterworth32_t *f, int32_t x0) { int32_t y0; /* 差分方程移位运算形式 */ y0 = (x0 + (f-x1 * 3) + (f-x2 * 8) + (f-y1 * 4) + (f-y2 * 16)) 5; /* 更新历史采样 */ f-x2 = f-x1; f-x1 = x0; f-y2 = f-y1; f-y1 = y0; return y0; } int main(void) { Butterworth32_t filter; int32_t input[] = {100, 120, 95, 130, 110, 105, 140, 125}; int32_t output; int i; butterworth32_init(filter); /* 主循环:逐点滤波 */ for (i = 0; i (int)(sizeof(input) / sizeof(input[0])); i++) { output = butterworth32_filter(filter, input[i]); printf("x[%d]=%d, y[%d]=%d\n", i, input[i], i, output); } return 0; }下面给出上述代码在输入序列 {100, 120, 95, 130, 110, 105, 140, 125} 下的实际运行输出:x[0]=100, y[0]=3 x[1]=120, y[1]=7 x[2]=95, y[2]=12 x[3]=130, y[3]=18 x[4]=110, y[4]=23 x[5]=105, y[5]=28 x[6]=140, y[6]=35 x[7]=125, y[7]=41从输出数据可以看出,三十二分之一变体的输出 y(n) 相比原始输入 x(n) 更加平滑:输入序列在 95 与 130 之间、105 与 140 之间均存在较大跳变,而输出序列则呈现缓慢上升的单调趋势,相邻采样点之间的差值被进一步压缩。相比十六分之一变体,三十二分之一的输出幅值整体更低、相邻点增量更小,说明其低通滤波作用更强,高频波动被更充分地衰减。同时,由于前两次采样用于赋初值,输出从第 0 点起即进入收敛状态,未出现发散或振荡,进一步验证了 b1+b2=0.6251 条件下系统的稳定性与收敛性。对于六十四分之一,取系数 a0=1,a1=4,a2=12,b1=16,b2=31,和为 64。实际上 a0=0.015625,a1=0.0625,a2=0.1875,b1=0.25,b2=0.48375,其中 b1+b2=0.7343751,是稳定和收敛的,用移位法快速归一化。赋初值同上。下面给出六十四分之一二阶巴特沃斯滤波器的完整 C 语言实现。代码采用定点移位运算实现系数归一化,将差分方程中的除法转换为右移 6 位(≫6)操作,避免浮点运算,适合嵌入式实时处理。#include stdio.h #include stdint.h /* 六十四分之一二阶巴特沃斯滤波器结构体 */ typedef struct { int32_t x1, x2; /* 前两次输入采样 */ int32_t y1, y2; /* 前两次输出采样 */ } Butterworth64_t; /* 初始化:清零历史采样,前两次采样用于赋初值 */ void butterworth64_init(Butterworth64_t *f) { f-x1 = 0; f-x2 = 0; f-y1 = 0; f-y2 = 0; } /* 滤波函数:y(n) = [x(n) + 4x(n-1) + 12x(n-2) + 16y(n-1) + 31y(n-2)] 6 系数 a0=1, a1=4, a2=12, b1=16, b2=31,系数和为 64, 归一化即除以 64,等价于右移 6 位(6),实现快速移位归一化。 */ int32_t butterworth64_filter(Butterworth64_t *f, int32_t x0) { int32_t y0; /* 差分方程移位运算形式 */ y0 = (x0 + (f-x1 * 4) + (f-x2 * 12) + (f-y1 * 16) + (f-y2 * 31)) 6; /* 更新历史采样 */ f-x2 = f-x1; f-x1 = x0; f-y2 = f-y1; f-y1 = y0; return y0; } int main(void) { Butterworth64_t filter; int32_t input[] = {100, 120, 95, 130, 110, 105, 140, 125}; int32_t output; int i; butterworth64_init(filter); /* 主循环:逐点滤波 */ for (i
返回列表