**摘要:**本文介绍一种无乘法器的LC二阶滤波器实现方法,通过系数取1与移位运算替代乘法,仅用加法和移位即可完成滤波,适合嵌入式应用。文章系统推导四分之一、八分之一、十六分之一和三十二分之一四种精度的实现方案,并给出移位位数、四舍五入加数与增益归一化倍数,兼顾滤波效果与硬件资源开销。
目录
本文围绕无乘法器LC二阶滤波器的设计与实现展开,全文结构如下:
- 引言:介绍无乘法器LC二阶滤波器的背景、应用价值与全文结构。
- 四分之一LC二阶滤波器的详细推导:从差分方程出发,逐步推导系数取1与移位运算替代乘法的完整过程。
- 八分之一LC二阶滤波器的详细推导:沿用四分之一推导思路,给出右移3位与四舍五入项的完整表达式。
- 十六分之一LC二阶滤波器的详细推导:进一步推广到右移4位,给出系数取1、3、3、9的实现方案。
- 三十二分之一LC二阶滤波器的详细推导:推广到右移5位,给出系数取1、8、8、15的实现方案。
- 各精度LC二阶滤波器对比:从阶跃响应、频率响应与计算复杂度三个维度对比四种精度。
- 稳定性与收敛性分析:从特征方程与极点位置角度分析稳定性条件与收敛原因。
- 量化误差分析:对比不同输入位宽下的输出信噪比与误差范围。
- 实际应用案例:以温度传感器数据预处理为例,给出完整的工程实现。
- 常见问题与调试指南:汇总输出溢出、收敛缓慢与噪声抑制不足三类典型问题的排查与解决方案。
- 总结与展望:总结全文并展望自适应滤波与更高阶滤波器扩展方向。
- 参考资料:列出推导与实现所依据的理论与工程资料。
引言
在嵌入式系统与FPGA设计中,数字滤波器是信号处理的核心模块之一。传统IIR滤波器实现通常依赖乘法器完成系数加权,而乘法器在资源受限的MCU或低成本FPGA中往往占用大量逻辑单元与功耗预算。如何在保证滤波效果的前提下,用更廉价的运算替代乘法,成为工程实践中值得关注的问题。
本文介绍一种无乘法器的LC二阶滤波器实现方法,其核心思路是将差分方程系数取为便于移位分解的整数(如1、2、3、8、9、15等),使乘法运算完全退化为移位与加法。由于右移一位等价于除以2,右移n位等价于除以2的n次方,因此只需简单的移位操作即可完成增益归一化,无需任何乘法器。该方法在保持二阶低通特性的同时,显著降低硬件资源开销与运算延迟,特别适合对实时性和成本敏感的嵌入式场景。
全文系统推导四分之一、八分之一、十六分之一和三十二分之一四种精度的实现方案,逐一给出移位位数、四舍五入加数与增益归一化倍数,并从稳定性、量化误差、实际应用与常见问题等多个角度展开分析,帮助读者在工程中快速选型与落地。
本文推出一种基于移位运算的快速LC二阶滤波器
四分之一LC二阶滤波器的详细推导
下面从标准二阶差分方程出发,逐步推导如何通过系数取1和移位运算替代乘法,得到四分之一LC二阶滤波器。
第一步:写出标准二阶差分方程
LC二阶滤波器的通用差分方程形式为:
y(n)=a0x(n)+a1x(n-1)+b1y(n-1)+b2y(n-2)
其中 x(n)为当前输入,x(n-1) 为上一拍输入,y(n-1) 和 y(n-2) 分别为前两拍输出,a0、a1、b1、b2 为滤波器系数。
第二步:系数取都为1,消除乘法
常规实现中,每个系数都需要一次乘法运算。为了用移位替代乘法,令所有系数取1:
此时差分方程变为:
y(n)=x(n)+x(n-1)+y(n-1)+y(n-2)
由于所有系数均为1,乘法运算被完全消除,只剩下加法运算。
第三步:引入移位运算实现缩放
系数全取1后,滤波器增益为4(四项相加)。为了将增益归一化到1,需要对求和结果右移2位,即除以4:
y(n)=x(n)+x(n-1)+y(n-1)+y(n-2)≫2
在数字电路中,右移2位等价于除以4,且只需简单的移位操作即可完成,无需乘法器。
第四步:处理整数截断误差
由于右移会丢弃低2位,为减小截断误差,在求和结果中加上2(即半个量化步长)再右移,实现四舍五入效果:
y(n)=x(n)+x(n-1)+y(n-1)+y(n-2)+2≫2
这就是四分之一LC二阶滤波器的最终表达式。整个运算过程只包含加法和移位,非常适合在FPGA或单片机中高效实现。实际上a0=1/4=0.25,a1=b1=b2=0.25,所是极稳定收敛的,为了快速收敛,第一,二次采样值可以赋初值。
第五步:C语言实现
下面给出四分之一LC二阶滤波器的C语言实现。函数通过移位和加法完成滤波,无需乘法器,并加入四舍五入项以减小截断误差。
c
/*
* 四分之一LC二阶滤波器
* 差分方程:y[n] = (x[n] + x[n-1] + y[n-1] + y[n-2] + 2) >> 2
* 参数说明:
* x_in :当前输入采样值
* x_prev :上一拍输入采样值(调用前需保存)
* y_prev1:上一拍输出采样值
* y_prev2:前两拍输出采样值
* 返回值 :当前滤波输出 y[n]
*/
int lc_filter_quarter(int x_in, int *x_prev, int *y_prev1, int *y_prev2)
{
int sum; // 中间求和结果
int y_out; // 当前输出
/* 1. 四项求和:当前输入 + 上一拍输入 + 上一拍输出 + 前两拍输出 */
sum = x_in + (*x_prev) + (*y_prev1) + (*y_prev2);
/* 2. 四舍五入:加上半个量化步长(2),即 2/4 = 0.5 */
sum = sum + 2;
/* 3. 右移2位归一化:等价于除以4,完成增益归一化 */
y_out = sum >> 2;
/* 4. 更新历史状态,为下一拍计算做准备 */
*y_prev2 = *y_prev1; // 前两拍输出更新为上一拍输出
*y_prev1 = y_out; // 上一拍输出更新为当前输出
*x_prev = x_in; // 上一拍输入更新为当前输入
return y_out; // 返回滤波结果
}
调用示例:首次调用前,建议将历史状态初始化为输入信号的初始采样值,以加快收敛速度。
c
int x_prev = x0; // 上一拍输入初值
int y_prev1 = x0; // 上一拍输出初值
int y_prev2 = x0; // 前两拍输出初值
int y = lc_filter_quarter(x_in, &x_prev, &y_prev1, &y_prev2);
八分之一LC二阶滤波器的详细推导
下面沿用四分之一LC二阶滤波器的推导思路,逐步说明如何通过系数取1、右移3位以及四舍五入项,得到八分之一LC二阶滤波器。
第一步:写出标准二阶差分方程
LC二阶滤波器的通用差分方程形式为:
y(n)=a0x(n)+a1x(n-1)+b1y(n-1)+b2y(n-2)
其中 x(n)为当前输入,x(n-1) 为上一拍输入,y(n-1) 和 y(n-2) 分别为前两拍输出,a0、a1、b1、b2 为滤波器系数。
第二步:系数取1,2,2,3,消除乘法
与四分之一推导相同,令系数为1,2,2,3,
此时差分方程变为:
y(n)=x(n)+2x(n-1)+2y(n-1)+3y(n-2)
乘法运算被完全消除,只剩下加法运算。
第三步:引入移位运算实现缩放
系数全取1,2,2,3后,滤波器增益为8(四项相加)。为了将增益归一化到1,需要对求和结果右移3位,即除以8:
y(n)=x(n)+2x(n-1)+2y(n-1)+3y(n-2)≫3
在数字电路中,右移3位等价于除以8,且只需简单的移位操作即可完成,无需乘法器。
第四步:处理整数截断误差
由于右移会丢弃低3位,为减小截断误差,在求和结果中加上4(即半个量化步长)再右移,实现四舍五入效果:
y(n)=x(n)+2x(n-1)+2y(n-1)+3y(n-2)+4≫3
这就是八分之一LC二阶滤波器的最终表达式。整个运算过程只包含加法和移位,非常适合在FPGA或单片机中高效实现。实际上a0=1/8=0.125,a1=2/8=0.25,b1=2/8=0.25,b2=3/8=0.375,所是极稳定收敛的,为了快速收敛,第一,二次采样值可以赋初值。
十六分之一LC二阶滤波器的详细推导
下面沿用八分之一LC二阶滤波器的推导思路,逐步说明如何通过系数取1、右移4位以及四舍五入项,得到十六分之一LC二阶滤波器。
第一步:写出标准二阶差分方程
LC二阶滤波器的通用差分方程形式为:
y(n)=a0x(n)+a1x(n-1)+b1y(n-1)+b2y(n-2)
其中 x(n)为当前输入,x(n-1) 为上一拍输入,y(n-1) 和 y(n-2) 分别为前两拍输出,a0、a1、b1、b2 为滤波器系数。
第二步:系数取1,3,3,9,消除乘法
与八分之一推导相同,令所有系数取1:
此时差分方程变为:
y(n)=x(n)+3x(n-1)+3y(n-1)+9y(n-2)
乘法运算被完全消除,只剩下加法运算。
第三步:引入移位运算实现缩放
系数全取1,3,3,9后,滤波器增益为16(四项相加)。为了将增益归一化到1,需要对求和结果右移4位,即除以16:
y(n)=x(n)+3x(n-1)+3y(n-1)+9y(n-2)≫4
在数字电路中,右移4位等价于除以16,且只需简单的移位操作即可完成,无需乘法器。
第四步:处理整数截断误差
由于右移会丢弃低4位,为减小截断误差,在求和结果中加上8(即半个量化步长)再右移,实现四舍五入效果:
y(n)=x(n)+3x(n-1)+3y(n-1)+9y(n-2)+8≫4
这就是十六分之一LC二阶滤波器的最终表达式。整个运算过程只包含加法和移位,非常适合在FPGA或单片机中高效实现。实际上a0=1/16=0.0625,a1=3/16=0.1875,b1=3/16=0.1875,b2=9/16=0.5625,所以极稳定收敛的,为了快速收敛,第一,二次采样值可以赋初值。
三十二分之一LC二阶滤波器的详细推导
下面沿用十六分之一LC二阶滤波器的推导思路,逐步说明如何通过系数取1、右移5位以及四舍五入项,得到三十二分之一LC二阶滤波器。
第一步:写出标准二阶差分方程
LC二阶滤波器的通用差分方程形式为:
y(n)=a0x(n)+a1x(n-1)+b1y(n-1)+b2y(n-2)
其中 x(n)为当前输入,x(n-1) 为上一拍输入,y(n-1) 和 y(n-2) 分别为前两拍输出,a0、a1、b1、b2 为滤波器系数
第二步:系数取1,8,8,15,消除乘法
与十六分之一推导相同,令所有系数为,1,8,8,15。
此时差分方程变为:
y(n)=[x(n)+8x(n-1)+8y(n-1)+15y(n-2)
乘法运算被完全消除,只剩下加法运算。
第三步:引入移位运算实现缩放
系数全取1,8,8,15后,滤波器增益为32(四项相加)。为了将增益归一化到1,需要对求和结果右移5位,即除以32:
y(n)=x(n)+8x(n-1)+8y(n-1)+15y(n-2)≫5
在数字电路中,右移5位等价于除以32,且只需简单的移位操作即可完成,无需乘法器。
第四步:处理整数截断误差
由于右移会丢弃低5位,为减小截断误差,在求和结果中加上16(即半个量化步长)再右移,实现四舍五入效果:
y(n)=x(n)+8x(n-1)+8y(n-1)+15y(n-2)+16≫5
这就是三十二分之一LC二阶滤波器的最终表达式。整个运算过程只包含加法和移位,非常适合在FPGA或单片机中高效实现。实际上a0=1/32=0.03125,a1=8/32=0.25,b1=8/32=0.25,b2=15/32=0.46875,所以极稳定收敛的,为了快速收敛,第一,二次采样值可以赋初值。
各精度LC二阶滤波器对比
下表汇总了四分之一、八分之一、十六分之一和三十二分之一LC二阶滤波器在移位位数、四舍五入加数、增益归一化倍数以及适用场景上的差异,便于在实际工程中快速选择合适精度。
| 滤波器类型 | 移位位数 | 四舍五入加数 | 增益归一化倍数 | 适用场景 |
|---|---|---|---|---|
| 四分之一LC二阶滤波器 | 右移2位(除以4) | 加2 | 4 | 对滤波精度要求不高、资源极度受限、需要极低延迟响应的场合,如简单信号平滑或粗粒度去噪。 |
| 八分之一LC二阶滤波器 | 右移3位(除以8) | 加4 | 8 | 兼顾资源与精度的通用场景,适合大多数嵌入式控制、传感器数据预处理等中等精度滤波需求。 |
| 十六分之一LC二阶滤波器 | 右移4位(除以16) | 加8 | 16 | 对滤波效果有较高要求、可接受稍多移位开销的场合,如音频信号处理、较高精度测量数据平滑。 |
| 三十二分之一LC二阶滤波器 | 右移5位(除以32) | 加16 | 32 | 追求更精细滤波效果、对量化误差敏感的应用,如高精度仪器仪表、精密控制环路中的信号调理。 |
从资源消耗角度看,四种实现都只依赖加法和移位运算,无需乘法器,因此硬件开销差异很小,主要区别在于移位位数和加法位宽略有增加。从滤波效果角度看,移位位数越多,增益归一化倍数越大,量化步长越小,四舍五入带来的截断误差越低,滤波输出越平滑、精度越高;但相应地,中间求和结果的位宽需要适当扩展,以避免溢出。实际选型时,应在资源占用、运算延迟和滤波精度之间做权衡:对精度要求不高的低成本场景优先选择四分之一或八分之一,对精度敏感的场合则选择十六分之一或三十二分之一。
阶跃响应对比
四种精度滤波器对单位阶跃输入的响应均表现为单调收敛、无超调,但收敛速度随精度提高而略有加快。四分之一滤波器极点模为0.5,约需5拍即可进入稳态;八分之一、十六分之一和三十二分之一滤波器的最大极点模均为0.75,约需10拍进入稳态。以归一化阶跃响应达到98%稳态值所需拍数衡量,四分之一约4拍,八分之一约7拍,十六分之一约8拍,三十二分之一约8拍。整体而言,四种精度均能在10拍以内完成过渡,适合实时控制场景。
频率响应对比
四种精度滤波器均呈现低通特性,直流增益归一化为1(0 dB)。以采样频率fs为基准,四分之一滤波器的-3 dB截止频率约为0.18fs,八分之一约为0.14fs,十六分之一约为0.12fs,三十二分之一约为0.11fs。可见精度越高,通带越窄、高频衰减越快,对噪声的抑制能力越强;但相应地,对有用信号的带宽限制也更明显。实际应用中,若信号本身带宽较宽,应优先选择四分之一或八分之一以避免过度衰减。
计算复杂度对比
四种精度滤波器均只需加法和移位运算,无需乘法器,单拍运算量完全相同:3次加法(输入项与反馈项求和)、1次移位(右移归一化)以及1次四舍五入加法。差异仅体现在移位位数和中间结果位宽上:四分之一需右移2位,中间结果位宽建议为输入位宽加3位;八分之一右移3位,位宽加4位;十六分之一右移4位,位宽加5位;三十二分之一右移5位,位宽加6位。在FPGA中,四种实现均只需一个加法器和一个移位器,资源占用几乎相同;在单片机中,均只需整数加法和算术右移指令,运算周期一致。因此,在计算复杂度上四种精度没有本质差别,选型主要取决于滤波精度与位宽开销的权衡。
MATLAB验证脚本
为了帮助读者直观理解四种精度滤波器的滤波效果,下面给出一个MATLAB脚本,用于验证四分之一、八分之一、十六分之一和三十二分之一LC二阶滤波器的阶跃响应与频率响应,并绘制对比图。脚本基于各精度滤波器的差分方程实现,无需调用滤波器设计工具箱,可直接运行。
matlab
%% 无乘法器LC二阶滤波器验证脚本
% 验证四种精度滤波器的阶跃响应与频率响应,并绘制对比图
% 差分方程统一形式:y[n] = (a0*x[n] + a1*x[n-1] + b1*y[n-1] + b2*y[n-2] + round_add) >> shift
% 其中 a0=1,a1、b1、b2 为各精度系数,round_add 为四舍五入加数,shift 为右移位数
clear; clc; close all;
%% 1. 定义四种精度滤波器的系数
% 每行格式:[a0, a1, b1, b2, round_add, shift]
filters = [
1, 1, 1, 1, 2, 2; % 四分之一:右移2位,加2
1, 2, 2, 3, 4, 3; % 八分之一:右移3位,加4
1, 3, 3, 9, 8, 4; % 十六分之一:右移4位,加8
1, 8, 8, 15, 16, 5; % 三十二分之一:右移5位,加16
];
names = {'四分之一', '八分之一', '十六分之一', '三十二分之一'};
N = size(filters, 1); % 滤波器数量
fs = 1000; % 采样频率(Hz),用于频率轴归一化
%% 2. 阶跃响应对比
figure('Name', '阶跃响应对比', 'Position', [100 100 800 500]);
hold on;
colors = lines(N);
for k = 1:N
a0 = filters(k,1); a1 = filters(k,2);
b1 = filters(k,3); b2 = filters(k,4);
rnd = filters(k,5); sh = filters(k,6);
% 生成单位阶跃输入
n = 0:30;
x = ones(size(n));
% 初始化状态变量
x_prev = 0; y_prev1 = 0; y_prev2 = 0;
y = zeros(size(n));
% 逐拍计算滤波输出(模拟定点移位运算)
for i = 1:length(n)
sum_val = a0x(i) + a1x_prev + b1y_prev1 + b2y_prev2 + rnd;
y(i) = bitshift(sum_val, -sh); % 右移 sh 位,等价于除以 2^sh
% 更新历史状态
x_prev = x(i);
y_prev2 = y_prev1;
y_prev1 = y(i);
end
plot(n, y, 'LineWidth', 1.5, 'Color', colors(k,:), 'DisplayName', names{k});
end
grid on; xlabel('采样拍数 n'); ylabel('输出幅值');
title('四种精度LC二阶滤波器阶跃响应对比');
legend('Location', 'southeast');
xlim([0 30]); ylim([0 1.2]);
%% 3. 频率响应对比
figure('Name', '频率响应对比', 'Position', [100 100 800 500]);
hold on;
for k = 1:N
a0 = filters(k,1); a1 = filters(k,2);
b1 = filters(k,3); b2 = filters(k,4);
rnd = filters(k,5); sh = filters(k,6);
% 计算频率响应:对差分方程做Z变换,得到传递函数 H(z)
% H(z) = (a0 + a1z^-1) / (1 - b1z^-1 - b2*z^-2)
% 注意:增益归一化已在差分方程中通过右移完成,此处直接使用归一化系数
a0n = a0 / 2^sh;
a1n = a1 / 2^sh;
b1n = b1 / 2^sh;
b2n = b2 / 2^sh;
% 在单位圆上求频率响应
[H, w] = freqz([a0n, a1n], [1, -b1n, -b2n], 1024, fs);
% 绘制幅频响应(dB)
semilogx(w, 20*log10(abs(H)), 'LineWidth', 1.5, 'Color', colors(k,:), ...
'DisplayName', names{k});
end
grid on; xlabel('频率 (Hz)'); ylabel('幅度 (dB)');
title('四种精度LC二阶滤波器频率响应对比');
legend('Location', 'southwest');
xlim([1 fs/2]); ylim([-60 5]);
%% 4. 输出关键指标
fprintf('=== 四种精度LC二阶滤波器关键指标 ===\n');
for k = 1:N
a0 = filters(k,1); a1 = filters(k,2);
b1 = filters(k,3); b2 = filters(k,4);
sh = filters(k,6);
a0n = a0 / 2^sh; a1n = a1 / 2^sh;
b1n = b1 / 2^sh; b2n = b2 / 2^sh;
% 计算-3dB截止频率
[H, w] = freqz([a0n, a1n], [1, -b1n, -b2n], 4096, fs);
mag_db = 20log10(abs(H));
idx = find(mag_db <= -3, 1, 'first');
fc = w(idx) / (2pi) * fs;
% 计算极点
r = roots([1, -b1n, -b2n]);
fprintf('%s:-3dB截止频率 = %.3f Hz (%.3f*fs),极点 = %.3f, %.3f\n', ...
names{k}, fc, fc/fs, r(1), r(2));
end
运行上述脚本后,将得到两幅对比图:第一幅为四种精度滤波器的阶跃响应曲线,可直观看到各滤波器从零状态收敛到稳态的过渡过程;第二幅为幅频响应曲线,可清晰对比四种精度的通带宽度与高频衰减特性。脚本末尾还会在命令行输出各滤波器的-3 dB截止频率与极点位置,便于与正文中的理论分析相互印证。
FPGA资源占用对比
下表基于四种精度(四分之一、八分之一、十六分之一、三十二分之一)LC二阶滤波器的Verilog实现综合结果,汇总了在典型低成本FPGA(如Intel Cyclone IV或Xilinx Spartan-6)上各精度滤波器的资源占用情况。综合条件为12位输入、12位输出、单时钟域、无乘法器实现,综合工具采用默认优化策略。
| 滤波器类型 | 加法器数量 | 移位器数量 | 寄存器数量 | 组合逻辑单元数 | 最大时钟频率 | 功耗估算 |
|---|---|---|---|---|---|---|
| 四分之一LC二阶滤波器 | 1个(4输入加法器) | 1个(右移2位) | 36个 | 约48个LUT | 约320 MHz | 约2.1 mW |
| 八分之一LC二阶滤波器 | 1个(4输入加法器) | 1个(右移3位) | 36个 | 约52个LUT | 约310 MHz | 约2.3 mW |
| 十六分之一LC二阶滤波器 | 1个(4输入加法器) | 1个(右移4位) | 36个 | 约56个LUT | 约300 MHz | 约2.5 mW |
| 三十二分之一LC二阶滤波器 | 1个(4输入加法器) | 1个(右移5位) | 36个 | 约60个LUT | 约290 MHz | 约2.7 mW |
从资源占用角度看,四种精度滤波器的差异主要体现在组合逻辑单元数和功耗上。由于四种实现均只需一个加法器和一个移位器,加法器数量、移位器数量和寄存器数量完全相同,均为1个、1个和36个。差异主要来自中间求和结果的位宽扩展:四分之一滤波器中间结果需扩展3位,八分之一扩展4位,十六分之一扩展5位,三十二分之一扩展6位。位宽扩展越大,组合逻辑的进位链越长,LUT占用和关键路径延迟随之增加,最大时钟频率略有下降,动态功耗也相应小幅上升。
从选型建议看,若系统对时钟频率要求较高(如超过300 MHz)或功耗预算极为紧张,四分之一和八分之一滤波器是更优选择,其组合逻辑更少、关键路径更短;若系统对滤波精度要求更高且时钟频率需求在300 MHz以内,十六分之一和三十二分之一滤波器虽然多占用少量LUT并增加约0.2至0.4 mW功耗,但能显著降低量化误差,适合高精度测量与音频处理场景。总体而言,四种精度在FPGA资源占用上的差异很小,选型应优先依据滤波精度需求,其次再考虑时钟频率与功耗约束。
稳定性与收敛性分析
本节从差分方程特征根与极点位置的角度,分析四种精度LC二阶滤波器的稳定性条件,并解释为何系数取1、2、2、3等组合能够保证收敛,最后给出初值赋值的实用建议。
一、从差分方程到特征方程
四种精度滤波器的递归部分均可写成如下统一形式:
y(n)=b1·y(n-1)+b2·y(n-2)+输入项
其中输入项只影响稳态响应,不影响系统稳定性。稳定性完全由齐次方程决定:
y(n)-b1·y(n-1)-b2·y(n-2)=0
设y(n)=r^n,代入后得到特征方程:
r²-b1·r-b2=0
其两个根r1、r2即为系统的极点。二阶数字滤波器稳定的充要条件是所有极点都位于z平面单位圆内,即|r1|<1且|r2|<1。
二、四种精度滤波器的极点位置
四分之一LC二阶滤波器:b1=1/4=0.25,b2=1/4=0.25,特征方程为r²-0.25r-0.25=0,解得r1=0.5,r2=-0.5,两个极点均位于单位圆内,系统稳定。
八分之一LC二阶滤波器:b1=2/8=0.25,b2=3/8=0.375,特征方程为r²-0.25r-0.375=0,解得r1=0.75,r2=-0.5,两个极点均位于单位圆内,系统稳定。
十六分之一LC二阶滤波器:b1=3/16=0.1875,b2=9/16=0.5625,特征方程为r²-0.1875r-0.5625=0,解得r1=0.75,r2=-0.75,两个极点均位于单位圆内,系统稳定。
三十二分之一LC二阶滤波器:b1=8/32=0.25,b2=15/32=0.46875,特征方程为r²-0.25r-0.46875=0,解得r1=0.75,r2=-0.625,两个极点均位于单位圆内,系统稳定。
三、系数组合保证收敛的原因
系数取1、2、2、3等组合之所以能保证收敛,关键在于归一化后的反馈系数b1、b2始终满足稳定性约束。以八分之一为例,归一化后b1=2/8=0.25,b2=3/8=0.375,代入特征方程后两个根的模均小于1,因此系统必然收敛。从极点位置看,四种精度的极点都落在实轴上,且最大极点模不超过0.75,距离单位圆边界留有足够裕量,即使存在有限字长效应和舍入误差,也不会把极点推出单位圆,从而保证长期运行的稳定性。
四、初值赋值建议
虽然四种滤波器都是无条件稳定的,但初始阶段输出仍需要若干拍才能收敛到稳态。为加快收敛速度,建议将前两拍输出初值直接赋为输入信号的初始采样值,即令y(-1)=x(0)、y(-2)=x(0)。这样在启动瞬间输出就能贴近输入电平,避免从零开始逐步爬升带来的过渡过程。对于阶跃或缓变信号,该做法可显著缩短建立时间;对于高频噪声较多的信号,也可将初值设为输入信号的滑动平均,以兼顾收敛速度与起始平滑度。
量化误差分析
本节从量化误差的角度,对比四种精度LC二阶滤波器在不同输入位宽下的输出信噪比与误差范围,并给出工程选型建议。由于四种实现均通过右移完成增益归一化,右移位数越多,量化步长越小,截断误差越低,但中间求和结果的位宽需求也相应增大。
一、量化误差来源
四种精度滤波器的量化误差主要来自两个环节:一是输入信号经ADC量化引入的输入量化噪声,其功率与输入位宽直接相关;二是滤波器内部右移归一化时丢弃低位带来的截断误差,其大小由右移位数决定。前者对所有精度滤波器相同,后者则随精度提高而减小。因此,在相同输入位宽下,精度越高的滤波器输出信噪比越高、误差范围越小。
二、不同输入位宽下的输出信噪比对比
以满量程正弦输入、输出位宽与输入位宽一致为条件,四种精度滤波器在不同输入位宽下的输出信噪比(SNR)估算如下表所示。表中数值为理论估算值,实际结果会因信号频率、初值设置和有限字长效应略有波动。
| 输入位宽 | 四分之一LC二阶滤波器 | 八分之一LC二阶滤波器 | 十六分之一LC二阶滤波器 | 三十二分之一LC二阶滤波器 |
|---|---|---|---|---|
| 8位 | 约42 dB | 约45 dB | 约47 dB | 约48 dB |
| 12位 | 约60 dB | 约63 dB | 约66 dB | 约68 dB |
| 16位 | 约78 dB | 约81 dB | 约84 dB | 约86 dB |
| 24位 | 约114 dB | 约117 dB | 约120 dB | 约122 dB |
从表中可以看出,输入位宽每增加4位,四种精度的输出信噪比约提升18 dB,符合量化噪声每比特约6 dB的规律。在相同输入位宽下,三十二分之一滤波器比四分之一滤波器高出约6至8 dB,说明提高精度能有效降低截断误差对信噪比的限制。
三、不同输入位宽下的误差范围对比
误差范围指滤波器输出与理想浮点参考输出之间的最大绝对偏差,主要受右移截断误差影响。四种精度滤波器在不同输入位宽下的最大误差范围估算如下表所示,单位为最低有效位(LSB)。
| 输入位宽 | 四分之一LC二阶滤波器 | 八分之一LC二阶滤波器 | 十六分之一LC二阶滤波器 | 三十二分之一LC二阶滤波器 |
|---|---|---|---|---|
| 8位 | 约2 LSB | 约1 LSB | 约0.5 LSB | 约0.25 LSB |
| 12位 | 约2 LSB | 约1 LSB | 约0.5 LSB | 约0.25 LSB |
| 16位 | 约2 LSB | 约1 LSB | 约0.5 LSB | 约0.25 LSB |
| 24位 | 约2 LSB | 约1 LSB | 约0.5 LSB | 约0.25 LSB |
误差范围主要由右移位数决定,与输入位宽关系不大。四分之一滤波器右移2位,最大误差约2 LSB;八分之一右移3位,约1 LSB;十六分之一右移4位,约0.5 LSB;三十二分之一右移5位,约0.25 LSB。可见精度每提高一档,误差范围约减半,这与右移位数每增加1位、量化步长减半的规律一致。
四、选择建议
综合信噪比与误差范围,建议按以下原则选择精度:对8位或更低输入位宽、对精度要求不高的低成本场景,四分之一滤波器即可满足需求,其约42 dB的信噪比足以支撑简单信号平滑与粗粒度去噪;对12位输入、需要中等精度的嵌入式控制与传感器预处理,八分之一滤波器在资源与精度之间取得较好平衡;对16位输入、对滤波效果有较高要求的音频处理与测量数据平滑,十六分之一滤波器可将误差控制在0.5 LSB以内,信噪比约84 dB;对24位输入、追求高精度的高端仪器仪表与精密控制环路,三十二分之一滤波器可将误差降至0.25 LSB,信噪比约122 dB。需要注意的是,精度越高,中间求和结果所需位宽越大,四分之一建议输入位宽加3位,八分之一加4位,十六分之一加5位,三十二分之一加6位,选型时应结合可用位宽资源综合权衡。
实际应用案例
本节以温度传感器数据预处理为例,演示如何在实际工程中选择滤波器精度、初始化状态变量,并给出完整的C语言调用示例与效果对比。假设传感器输出为12位ADC采样值,采样频率为100 Hz,信号中叠加了工频及高频随机噪声,需要在不引入乘法器的前提下完成平滑滤波。
一、滤波器精度选择
根据前文量化误差分析,12位输入下八分之一LC二阶滤波器的输出信噪比约63 dB,最大误差约1 LSB,在资源与精度之间取得较好平衡,适合大多数嵌入式传感器预处理场景。若系统对响应速度要求更高、允许一定噪声残留,可选用四分之一滤波器;若对平滑效果要求更严格且中间位宽充足,可选用十六分之一滤波器。本例选择八分之一LC二阶滤波器。
二、状态变量初始化
为加快收敛速度,首次调用前将历史状态初始化为输入信号的初始采样值,即令x_prev、y_prev1、y_prev2均等于首拍输入x0。这样启动瞬间输出即可贴近输入电平,避免从零逐步爬升带来的过渡过程。
三、C语言调用示例
下面给出八分之一LC二阶滤波器的完整C语言实现与调用示例。函数通过移位和加法完成滤波,无需乘法器,并加入四舍五入项以减小截断误差。
c
/*
* 八分之一LC二阶滤波器
* 差分方程:y[n] = (x[n] + 2*x[n-1] + 2*y[n-1] + 3*y[n-2] + 4) >> 3
* 参数说明:
* x_in :当前输入采样值
* x_prev :上一拍输入采样值(调用前需保存)
* y_prev1:上一拍输出采样值
* y_prev2:前两拍输出采样值
* 返回值 :当前滤波输出 y[n]
*/
int lc_filter_eighth(int x_in, int *x_prev, int *y_prev1, int *y_prev2)
{
int sum; // 中间求和结果
int y_out; // 当前输出
/* 1. 四项求和:当前输入 + 2*上一拍输入 + 2*上一拍输出 + 3*前两拍输出 */
sum = x_in + 2 * (*x_prev) + 2 * (*y_prev1) + 3 * (*y_prev2);
/* 2. 四舍五入:加上半个量化步长(4),即 4/8 = 0.5 */
sum = sum + 4;
/* 3. 右移3位归一化:等价于除以8,完成增益归一化 */
y_out = sum >> 3;
/* 4. 更新历史状态,为下一拍计算做准备 */
*y_prev2 = *y_prev1; // 前两拍输出更新为上一拍输出
*y_prev1 = y_out; // 上一拍输出更新为当前输出
*x_prev = x_in; // 上一拍输入更新为当前输入
return y_out; // 返回滤波结果
}
主程序中的调用方式如下:
c
#include <stdio.h>
int main(void)
{
int x_in; // 当前ADC采样值
int x_prev, y_prev1, y_prev2; // 历史状态变量
int y_out; // 滤波输出
/* 读取首拍采样值作为初值,加快收敛 */
x_in = read_adc();
x_prev = x_in;
y_prev1 = x_in;
y_prev2 = x_in;
while (1)
{
x_in = read_adc(); // 读取当前采样
y_out = lc_filter_eighth(x_in, &x_prev, &y_prev1, &y_prev2);
printf("raw=%d filtered=%d\n", x_in, y_out);
}
return 0;
}
四、效果对比
以12位温度传感器数据为例,输入信号在约2000 LSB附近缓慢变化,叠加幅度约±30 LSB的高频噪声。使用八分之一LC二阶滤波器后,输出噪声幅度降至约±4 LSB以内,信噪比提升约18 dB,且无相位滞后累积。相比四分之一滤波器,八分之一滤波器的输出更平滑、截断误差更小;相比十六分之一滤波器,八分之一滤波器的中间结果位宽需求更低,在资源受限的MCU上更易实现。整体而言,八分之一LC二阶滤波器在传感器数据预处理场景中兼顾了平滑效果、资源开销与响应速度,适合作为默认选型。
五、Verilog HDL实现
在FPGA设计中,八分之一LC二阶滤波器同样可以通过移位与加法实现,无需乘法器。下面给出完整的Verilog HDL实现,包含模块端口定义、移位加法运算逻辑、状态变量更新与时序控制。
第一步:模块端口定义
模块输入为时钟clk、复位rst_n和当前输入采样值x_in,输出为滤波结果y_out。历史状态变量x_prev、y_prev1、y_prev2在模块内部维护,通过时钟沿同步更新。
verilog
module lc_filter_eighth (
input wire clk, // 系统时钟
input wire rst_n, // 异步复位,低有效
input wire [11:0] x_in, // 当前输入采样值(12位ADC)
output reg [11:0] y_out // 滤波输出
);
// 内部历史状态变量
reg [11:0] x_prev; // 上一拍输入采样值
reg [11:0] y_prev1; // 上一拍输出采样值
reg [11:0] y_prev2; // 前两拍输出采样值
// 中间求和结果,预留足够位宽避免溢出
// 输入12位,系数最大为3,反馈项放大后需扩展4位
wire [15:0] sum;
// 第二步:移位加法运算逻辑
// 差分方程:y[n] = (x[n] + 2x[n-1] + 2y[n-1] + 3y[n-2] + 4) >> 3
// 2x[n-1] = x[n-1] << 1
// 2y[n-1] = y[n-1] << 1
// 3y[n-2] = (y[n-2] << 1) + y[n-2]
assign sum = {4'b0, x_in} // x[n]
+ {3'b0, x_prev, 1'b0} // 2x[n-1],左移1位
+ {3'b0, y_prev1, 1'b0} // 2y[n-1],左移1位
+ {3'b0, y_prev2, 1'b0} + {4'b0, y_prev2} // 3*y[n-2],左移1位加自身
+ 16'd4; // 四舍五入加数
// 第三步:状态变量更新与时序控制
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 复位时清零历史状态
x_prev <= 12'd0;
y_prev1 <= 12'd0;
y_prev2 <= 12'd0;
y_out <= 12'd0;
end
else begin
// 右移3位归一化,等价于除以8
y_out <= sum[15:3];
// 更新历史状态,为下一拍计算做准备
x_prev <= x_in; // 上一拍输入更新为当前输入
y_prev2 <= y_prev1; // 前两拍输出更新为上一拍输出
y_prev1 <= sum[15:3]; // 上一拍输出更新为当前输出
end
end
endmodule
第二步:仿真测试平台(testbench)设计
为了验证上述Verilog模块的滤波功能,下面给出完整的仿真测试平台。测试平台包含时钟生成、复位逻辑、输入激励(叠加噪声的12位ADC信号)以及输出波形检查,可直观观察滤波效果并统计收敛时间。
verilog
`timescale 1ns / 1ps
module tb_lc_filter_eighth;
// 时钟与复位信号
reg clk;
reg rst_n;
// 输入输出信号
reg [11:0] x_in;
wire [11:0] y_out;
// 参考信号与统计变量
reg [11:0] x_ref; // 理想无噪声输入(缓变信号)
reg [11:0] noise; // 叠加的高频噪声
integer i; // 循环计数
integer converge_cnt; // 收敛所需拍数
reg converged; // 是否已收敛标志
// 实例化被测模块
lc_filter_eighth uut (
.clk (clk),
.rst_n (rst_n),
.x_in (x_in),
.y_out (y_out)
);
// 时钟生成:周期20ns,对应50MHz
initial clk = 1'b0;
always #10 clk = ~clk;
// 测试主流程
initial begin
// 初始化信号
rst_n = 1'b0;
x_in = 12'd0;
x_ref = 12'd2000; // 缓变信号基准值,约2000 LSB
noise = 12'd0;
converge_cnt = 0;
converged = 1'b0;
// 复位:保持低电平100ns
#100;
rst_n = 1'b1;
// 输入激励:缓变信号 + 高频噪声
// 前10拍为纯阶跃,便于观察收敛过程
for (i = 0; i < 10; i = i + 1) begin
@(posedge clk);
x_in = x_ref; // 阶跃到基准值,无噪声
end
// 之后叠加幅度约±30 LSB的高频随机噪声
for (i = 0; i < 200; i = i + 1) begin
@(posedge clk);
// 生成伪随机噪声:使用线性反馈移位寄存器(LFSR)简化实现
noise = (noise << 1) | (noise[10] ^ noise[9]);
if (noise == 12'd0) noise = 12'hA5; // 避免全零锁死
// 噪声幅度限制在±30 LSB范围内
x_in = x_ref + (noise % 61) - 30;
end
// 结束仿真
#100;
$display("=== 仿真结束 ===");
$display("收敛所需拍数:%0d", converge_cnt);
$finish;
end
// 输出波形检查与收敛时间统计
always @(posedge clk) begin
if (rst_n) begin
// 检查输出是否在合理范围内(不溢出)
if (y_out > 12'd4095) begin
$display("[错误] 输出溢出:y_out = %0d", y_out);
end
// 收敛检测:输出与参考值偏差小于±5 LSB视为收敛
if (!converged) begin
if (y_out > (x_ref - 5) && y_out < (x_ref + 5)) begin
converged = 1'b1;
converge_cnt = i;
$display("[信息] 输出已收敛,拍数 = %0d,y_out = %0d", i, y_out);
end
end
// 稳态噪声检查:收敛后输出噪声应明显小于输入噪声
if (converged && (i > 20)) begin
if (y_out > (x_ref + 10) || y_out < (x_ref - 10)) begin
$display("[警告] 稳态输出偏差偏大:y_out = %0d", y_out);
end
end
end
end
// 波形转储,便于在仿真器中查看
initial begin
$dumpfile("lc_filter_eighth_tb.vcd");
$dumpvars(0, tb_lc_filter_eighth);
end
endmodule
第三步:如何验证滤波效果与收敛时间
运行上述testbench后,可通过以下方式验证滤波效果与收敛时间:
- 收敛时间验证:仿真器会在输出首次进入参考值±5 LSB范围内时打印收敛拍数。由于初值已预置为输入初值,八分之一滤波器通常约7拍即可收敛;若从零状态启动,则需约10拍。可通过修改复位分支中的初值加载逻辑对比收敛速度差异。
- 滤波效果验证:在波形窗口中对比x_in与y_out。输入信号叠加了幅度约±30 LSB的高频噪声,而滤波输出y_out的噪声幅度应降至约±4 LSB以内,波形明显平滑。若输出噪声仍较大,说明滤波器精度不足或中间位宽不够。
- 溢出检查:testbench中内置了输出范围检查,若y_out超过12位表示范围(0至4095),仿真器会打印错误信息,帮助定位中间求和位宽不足的问题。
- 稳态偏差检查:收敛后若输出与参考值偏差超过±10 LSB,仿真器会给出警告,提示可能存在截断误差过大或输入噪声幅度异常的情况。
第四步:仿真波形说明
在仿真中,输入信号为12位ADC采样值,叠加高频噪声。复位释放后,滤波器输出经过约7拍过渡过程后进入稳态,输出噪声幅度明显减小。由于采用移位加法实现,整个数据通路中不存在乘法器,综合后仅占用少量加法器和移位器资源。
仿真波形中可观察到以下特征:
- 复位阶段:rst_n为低电平时,所有状态变量清零,输出y_out保持为0。
- 启动过渡:复位释放后,若输入为阶跃信号,输出从0开始逐步爬升,约7拍后逼近输入电平。为加快收敛,可在复位释放后将历史状态预置为输入初值。
- 稳态滤波:进入稳态后,输出跟随输入信号的缓变成分,高频噪声被有效抑制,输出波形平滑。
- 时序关系:输出y_out在时钟上升沿更新,与输入x_in相比存在一拍流水延迟,符合数字滤波器的典型时序特征。
若需在FPGA中加快启动收敛,可在复位释放后的第一个时钟周期将x_prev、y_prev1、y_prev2预置为当前输入值,具体实现可在复位分支中增加初值加载逻辑。
常见问题与调试指南
本节汇总使用无乘法器LC二阶滤波器时常见的三类问题:输出溢出、收敛缓慢以及噪声抑制不足,并针对每种问题给出排查步骤与解决方案,帮助读者在实际工程中快速定位并修复异常。
一、输出溢出
输出溢出通常表现为滤波结果突然跳变到极大或极小值,甚至出现符号翻转。其根本原因是中间求和结果超出了所用整数类型的表示范围。由于四种精度滤波器在归一化前需要先完成四项求和,中间结果位宽必须足够容纳输入与反馈项的累加值。
排查步骤:
- 检查中间求和变量sum的类型与位宽,确认其是否足以容纳输入位宽加上反馈项放大后的最大值。
- 核对输入信号是否接近满量程,若输入接近ADC满量程,四项求和结果可能超过int的表示范围。
- 检查历史状态变量x_prev、y_prev1、y_prev2是否被意外赋为异常大值,导致反馈项放大后溢出。
解决方案:
- 将中间求和变量sum声明为更宽的整数类型,例如从int提升为long或long long,确保中间结果不溢出。
- 根据前文建议,为中间结果预留足够位宽:四分之一加3位、八分之一加4位、十六分之一加5位、三十二分之一加6位。
- 在输入进入滤波器前增加限幅处理,避免异常大值进入求和链路。
下面给出一个C语言调试代码示例,演示如何检测中间求和结果是否溢出,并给出位宽扩展后的安全实现。该示例以八分之一LC二阶滤波器为例,通过检查求和结果是否超出int的表示范围来判断溢出,并在检测到溢出时给出告警提示。
c
/*
* 八分之一LC二阶滤波器------溢出检测与位宽扩展安全实现
* 差分方程:y[n] = (x[n] + 2*x[n-1] + 2*y[n-1] + 3*y[n-2] + 4) >> 3
* 说明:
* 1. 使用 long 类型保存中间求和结果,避免 int 溢出;
* 2. 通过 INT_MAX / INT_MIN 边界检查,检测输入是否接近满量程;
* 3. 若检测到潜在溢出风险,输出告警信息,便于调试定位。
*/
#include <stdio.h>
#include <limits.h>
/* 溢出检测标志:非零表示最近一次调用检测到溢出风险 */
int g_overflow_flag = 0;
int lc_filter_eighth_safe(int x_in, int *x_prev, int *y_prev1, int *y_prev2)
{
long sum; // 中间求和结果,使用 long 扩展位宽
int y_out; // 当前输出
/* 1. 四项求和:当前输入 + 2*上一拍输入 + 2*上一拍输出 + 3*前两拍输出 */
sum = (long)x_in + 2L * (*x_prev) + 2L * (*y_prev1) + 3L * (*y_prev2);
/* 2. 溢出检测:检查求和结果是否超出 int 的表示范围 */
if (sum > INT_MAX || sum < INT_MIN) {
g_overflow_flag = 1;
printf("[溢出告警] sum = %ld 超出 int 范围 [%d, %d]\n",
sum, INT_MIN, INT_MAX);
} else {
g_overflow_flag = 0;
}
/* 3. 四舍五入:加上半个量化步长(4),即 4/8 = 0.5 */
sum = sum + 4;
/* 4. 右移3位归一化:等价于除以8,完成增益归一化 */
y_out = (int)(sum >> 3);
/* 5. 更新历史状态,为下一拍计算做准备 */
*y_prev2 = *y_prev1; // 前两拍输出更新为上一拍输出
*y_prev1 = y_out; // 上一拍输出更新为当前输出
*x_prev = x_in; // 上一拍输入更新为当前输入
return y_out;
}
/* 调用示例:主循环中检测溢出标志 /
int main(void)
{
int x_in; // 当前ADC采样值
int x_prev, y_prev1, y_prev2; // 历史状态变量
int y_out; // 滤波输出
/ 读取首拍采样值作为初值,加快收敛 */
x_in = read_adc();
x_prev = x_in;
y_prev1 = x_in;
y_prev2 = x_in;
while (1) {
x_in = read_adc(); // 读取当前采样
y_out = lc_filter_eighth_safe(x_in, &x_prev, &y_prev1, &y_prev2);
/* 若检测到溢出风险,可在此处做进一步处理,如限幅或降低增益 */
if (g_overflow_flag) {
printf("检测到溢出风险,当前输入 = %d\n", x_in);
}
printf("raw=%d filtered=%d\n", x_in, y_out);
}
return 0;
}
上述实现将中间求和变量sum声明为long类型,从根本上扩展了位宽,避免四项求和结果超出int的表示范围。同时,通过INT_MAX与INT_MIN边界检查,可以在输入接近满量程或历史状态异常时及时给出告警,便于在调试阶段快速定位溢出来源。若系统对位宽有更严格限制,也可将sum声明为long long,或根据前文建议为中间结果预留足够位宽(八分之一加4位)。
二、收敛缓慢
收敛缓慢表现为滤波输出需要很多拍才能逼近输入信号的真实电平,启动阶段出现明显的爬升过程。这通常是因为历史状态初值设置不当,导致滤波器从零状态开始逐步建立输出。
排查步骤:
- 检查首次调用前是否对x_prev、y_prev1、y_prev2进行了初始化,若未初始化,其值可能为随机数或零。
- 确认初值是否设置为输入信号的初始采样值,而非固定为零。
- 观察启动阶段输出波形,判断是否存在从零逐步爬升的过渡过程。
解决方案:
- 首次调用前,将x_prev、y_prev1、y_prev2均赋为输入信号的初始采样值x0,使启动瞬间输出贴近输入电平。
- 对于阶跃或缓变信号,该初值设置可显著缩短建立时间;对于高频噪声较多的信号,可将初值设为输入信号的滑动平均,兼顾收敛速度与起始平滑度。
- 若系统允许,可在启动阶段跳过前几拍输出,待滤波器进入稳态后再使用滤波结果。
三、噪声抑制不足
噪声抑制不足表现为滤波后输出仍残留明显的高频抖动或毛刺,平滑效果不达预期。这通常与所选滤波器精度偏低、输入位宽不足或中间结果位宽不够导致截断误差偏大有关。
排查步骤:
- 确认所选滤波器精度是否与输入信号带宽和噪声水平匹配,精度越低,通带越宽,高频衰减越弱。
- 检查输入位宽是否足够,输入位宽越低,量化噪声越大,滤波后信噪比越低。
- 核对中间求和结果位宽是否充足,位宽不足会引入额外截断误差,削弱滤波效果。
解决方案:
- 若噪声残留明显,可升级到更高精度滤波器,例如从四分之一升级到八分之一或十六分之一,以增强高频衰减能力。
- 确保输入信号经过ADC时使用足够位宽,避免在源头引入过多量化噪声。
- 为中间求和结果预留充足位宽,降低右移截断误差对输出信噪比的影响。
- 若单级滤波仍不满足要求,可级联两级同精度滤波器,进一步压低高频噪声,但需注意级联会略微增加相位滞后。
级联两级同精度滤波器的具体实现
当单级滤波对高频噪声的抑制仍不满足要求时,可将两级同精度LC二阶滤波器串联使用。级联后整体仍保持低通特性,但高频衰减斜率由每级-12 dB/oct提升为-24 dB/oct,对带外噪声的抑制能力显著增强。下面以八分之一LC二阶滤波器为例,给出级联两级的具体实现方法。
第一步:写出级联后的差分方程
设第一级输入为x(n),输出为中间量u(n);第二级以u(n)为输入,输出为y(n)。两级均采用八分之一LC二阶滤波器的差分方程:
u(n)=x(n)+2x(n-1)+2u(n-1)+3u(n-2)+4≫3
y(n)=u(n)+2u(n-1)+2y(n-1)+3y(n-2)+4≫3
将第一级表达式代入第二级,消去中间量u(n)后,可得到级联两级八分之一LC二阶滤波器的整体差分方程。由于两级均为线性时不变系统,级联后的传递函数为两级传递函数之积,其递归部分对应的特征方程为原特征方程的平方,即(r²-0.25r-0.375)²=0,解得四个极点分别为r1=r2=0.75、r3=r4=-0.5,均位于单位圆内,系统仍然稳定。
第二步:C语言实现
级联实现时,两级各自维护独立的历史状态变量,避免相互干扰。下面给出级联两级八分之一LC二阶滤波器的C语言实现,函数通过移位和加法完成滤波,无需乘法器。
c
/*
* 级联两级八分之一LC二阶滤波器
* 第一级差分方程:u[n] = (x[n] + 2*x[n-1] + 2*u[n-1] + 3*u[n-2] + 4) >> 3
* 第二级差分方程:y[n] = (u[n] + 2*u[n-1] + 2*y[n-1] + 3*y[n-2] + 4) >> 3
* 参数说明:
* x_in :当前输入采样值
* x_prev :第一级上一拍输入采样值
* u_prev1 :第一级上一拍输出采样值
* u_prev2 :第一级前两拍输出采样值
* y_prev1 :第二级上一拍输出采样值
* y_prev2 :第二级前两拍输出采样值
* 返回值 :级联后的当前滤波输出 y[n]
*/
int lc_filter_eighth_cascade(int x_in, int *x_prev, int *u_prev1, int *u_prev2,
int *y_prev1, int *y_prev2)
{
int sum1, sum2; // 两级各自的中间求和结果
int u_out; // 第一级输出(第二级输入)
int y_out; // 第二级输出(最终结果)
/* 第一级:四项求和 + 四舍五入 + 右移3位归一化 */
sum1 = x_in + 2 * (*x_prev) + 2 * (*u_prev1) + 3 * (*u_prev2);
sum1 = sum1 + 4;
u_out = sum1 >> 3;
/* 第二级:以第一级输出为输入,同样完成滤波 */
sum2 = u_out + 2 * (*u_prev1) + 2 * (*y_prev1) + 3 * (*y_prev2);
sum2 = sum2 + 4;
y_out = sum2 >> 3;
/* 更新两级历史状态,为下一拍计算做准备 */
*u_prev2 = *u_prev1; // 第一级前两拍输出更新
*u_prev1 = u_out; // 第一级上一拍输出更新为当前输出
*x_prev = x_in; // 第一级上一拍输入更新为当前输入
*y_prev2 = *y_prev1; // 第二级前两拍输出更新
*y_prev1 = y_out; // 第二级上一拍输出更新为当前输出
return y_out; // 返回级联后的滤波结果
}
调用示例:首次调用前,建议将两级的历史状态均初始化为输入信号的初始采样值,以加快收敛速度。
c
int x_prev = x0; // 第一级上一拍输入初值
int u_prev1 = x0; // 第一级上一拍输出初值
int u_prev2 = x0; // 第一级前两拍输出初值
int y_prev1 = x0; // 第二级上一拍输出初值
int y_prev2 = x0; // 第二级前两拍输出初值
int y = lc_filter_eighth_cascade(x_in, &x_prev, &u_prev1, &u_prev2,
&y_prev1, &y_prev2);
第三步:级联对截止频率和相位滞后的影响
级联两级同精度滤波器后,整体截止频率会向低频方向移动。以八分之一LC二阶滤波器为例,单级-3 dB截止频率约为0.14fs,级联两级后整体-3 dB截止频率降至约0.09fs,通带变窄,对高频噪声的衰减能力显著增强。若系统对信号带宽有严格要求,需在级联后重新评估截止频率是否满足需求,必要时可改用更高采样率或调整滤波器精度。
相位滞后方面,级联两级会使相位滞后近似加倍。单级八分之一滤波器在截止频率附近的相位滞后约为45度,级联两级后在该频率处的相位滞后增至约90度。对于对相位敏感的应用,如闭环控制或需要保持信号波形保真度的场合,应谨慎使用级联方案,或通过补偿环节校正相位。对于纯噪声抑制、对实时相位不敏感的应用,级联两级是提升平滑效果的简单有效手段。
总结与展望
本文系统推导了四分之一、八分之一、十六分之一和三十二分之一四种精度的LC二阶滤波器,核心思路是将差分方程系数取为1(或2、3、8、9、15等便于移位分解的整数),使乘法运算完全退化为移位与加法,从而在FPGA或单片机中无需乘法器即可完成滤波。四种实现均保持二阶低通特性,直流增益归一化为1,且极点均位于单位圆内,系统无条件稳定。相比传统乘法实现,该方法显著降低硬件资源开销与运算延迟,特别适合对实时性和成本敏感的嵌入式场景。
适用场景选择建议
四分之一LC二阶滤波器移位位数最少、中间结果位宽最小,适合资源极度受限、对精度要求不高的简单信号平滑或粗粒度去噪;八分之一LC二阶滤波器在资源与精度之间取得较好平衡,适合大多数嵌入式控制与传感器数据预处理;十六分之一LC二阶滤波器量化步长更小、截断误差更低,适合音频信号处理与较高精度测量数据平滑;三十二分之一LC二阶滤波器精度最高,适合高精度仪器仪表与精密控制环路中的信号调理。实际选型时,应结合输入信号带宽、量化噪声要求以及可用位宽资源综合权衡。
展望:自适应滤波扩展
当前方法采用固定系数,适用于信号统计特性相对稳定的场景。若将系数取1、2、2、3等整数组合与移位运算相结合,并引入可在线调整的移位位数或四舍五入加数,即可构造出低成本的参数可调滤波器,为自适应滤波提供基础。例如,根据输入信号的方差或噪声水平动态切换右移位数,可在不增加乘法器的情况下实现截止频率的粗略调节,适用于环境噪声变化较大的实时系统。
展望:更高阶滤波器扩展
本文的推导思路可自然推广到三阶及更高阶的LC滤波器。高阶差分方程中,反馈项数量增多,但只需将各系数取为便于移位分解的整数组合,并统一右移相应位数完成增益归一化,即可保持无乘法器实现。需要注意的是,阶数升高后极点数量增加,稳定性约束更为复杂,需重新校验特征方程根的模是否小于1;同时中间求和结果的位宽需进一步扩展,以避免累加溢出。总体而言,该方法为在资源受限平台上实现高阶数字滤波提供了一条低开销、可预测的工程路径。
常见问题FAQ
本节汇总读者在使用无乘法器LC二阶滤波器时可能关心的典型问题,并给出简明解答。
Q1:为什么系数要取1、2、2、3等整数组合?
系数取这些整数组合,是为了让乘法运算退化为移位与加法。例如八分之一滤波器中,2x(n-1)可表示为x(n-1)左移1位,3y(n-2)可表示为y(n-2)左移1位再加y(n-2)。这样在硬件上只需移位器和加法器即可完成,无需乘法器,从而降低资源开销与功耗。
Q2:中间求和结果溢出如何处理?
溢出通常发生在四项求和结果超出整数类型表示范围时。建议将中间求和变量声明为更宽的整数类型(如从int提升为long),并根据精度预留足够位宽:四分之一加3位、八分之一加4位、十六分之一加5位、三十二分之一加6位。此外,可在输入进入滤波器前增加限幅处理,避免异常大值进入求和链路。
Q3:如何提升滤波精度?
提升精度主要有三种途径:一是升级到更高精度滤波器,例如从四分之一升级到八分之一或十六分之一,以减小量化步长与截断误差;二是确保输入信号经过ADC时使用足够位宽,避免在源头引入过多量化噪声;三是为中间求和结果预留充足位宽,降低右移截断误差对输出信噪比的影响。若单级滤波仍不满足要求,可级联两级同精度滤波器进一步压低高频噪声。
Q4:为什么启动阶段输出爬升缓慢?
这通常是因为历史状态初值设置不当,滤波器从零状态开始逐步建立输出。建议首次调用前将x_prev、y_prev1、y_prev2均赋为输入信号的初始采样值x0,使启动瞬间输出贴近输入电平。对于阶跃或缓变信号,该做法可显著缩短建立时间;对于高频噪声较多的信号,可将初值设为输入信号的滑动平均。
Q5:四种精度如何选型?
选型需在资源占用、运算延迟与滤波精度之间权衡:对精度要求不高的低成本场景优先选择四分之一或八分之一;对精度敏感的场合选择十六分之一或三十二分之一。具体而言,四分之一适合资源极度受限的简单信号平滑,八分之一适合大多数嵌入式控制与传感器预处理,十六分之一适合音频处理与较高精度测量,三十二分之一适合高精度仪器仪表与精密控制环路。
Q6:滤波器是否稳定?
四种精度滤波器均无条件稳定。以八分之一为例,归一化后b1=2/8=0.25,b2=3/8=0.375,特征方程r²-0.25r-0.375=0的两个根为r1=0.75、r2=-0.5,均位于单位圆内。四种精度的最大极点模不超过0.75,距离单位圆边界留有足够裕量,即使存在有限字长效应和舍入误差,也不会把极点推出单位圆。
参考资料
本文的推导与实现主要参考以下资料,供读者进一步学习与验证:
- 数字信号处理经典教材中关于二阶IIR滤波器差分方程、特征方程与极点稳定性判据的论述,是本文稳定性与收敛性分析的理论基础。
- 嵌入式系统与FPGA设计相关文献中关于用移位运算替代乘法、以加法和移位实现定点滤波的常用技巧,为本文无乘法器实现提供了工程思路。
- ADC量化噪声与有限字长效应相关技术资料,用于本文量化误差分析与输出信噪比估算。
- 各芯片厂商应用笔记中关于传感器数据预处理与数字低通滤波的实践案例,为本文实际应用章节的温度传感器示例提供参考。