代码不依赖任何库,只用到标准 C,可直接用在 STM32 / 51 / DSP / PC 上。
一、FIR 滤波器原理
输出 = 输入 × 系数 的加权和
yn=∑k=0N−1hk⋅xn−kyn = \sum_{k=0}^{N-1} hk \cdot xn-kyn=∑k=0N−1hk⋅xn−k
h[k]:FIR 滤波器系数(固定)x[n-k]:输入的历史数据N:滤波器阶数 + 1
二、最常用结构:直接型(适合单片机 )
特点
结构简单
无递归(稳定)
易移植
阶数高时计算量大
三、C 语言实现
1、FIR 结构体定义
c
#ifndef FIR_FILTER_H
#define FIR_FILTER_H
#include <stdint.h>
typedef struct
{
const float *coeff; // 滤波器系数
float *buffer; // 输入缓冲
uint16_t order; // 阶数
uint16_t index; // 环形缓冲索引
} FIR_Filter_t;
#endif
2、FIR 初始化
c
#include "fir_filter.h"
#include <string.h>
void FIR_Init(FIR_Filter_t *fir,
const float *coeff,
float *buffer,
uint16_t order)
{
fir->coeff = coeff;
fir->buffer = buffer;
fir->order = order;
fir->index = 0;
memset(buffer, 0, order * sizeof(float));
}
3、FIR 单点滤波(核心函数)
c
float FIR_Process(FIR_Filter_t *fir, float input)
{
uint16_t i;
float output = 0.0f;
// 存入新输入(环形缓冲)
fir->buffer[fir->index] = input;
// 卷积计算
for (i = 0; i < fir->order; i++)
{
int buf_idx = (fir->index - i + fir->order) % fir->order;
output += fir->coeff[i] * fir->buffer[buf_idx];
}
// 更新索引
fir->index = (fir->index + 1) % fir->order;
return output;
}
四、使用示例(低通 FIR)
1、定义滤波器系数(示例:16 阶低通)
c
#define FIR_ORDER 16
// 示例系数(截止频率 ≈ 0.2 * Fs)
const float fir_coeff[FIR_ORDER] = {
0.0044, 0.0168, 0.0378, 0.0635,
0.0885, 0.1065, 0.1134, 0.1076,
0.0900, 0.0635, 0.0323, 0.0010,
-0.0266, -0.0467, -0.0569, -0.0561
};
float fir_buffer[FIR_ORDER];
FIR_Filter_t fir;
2、主循环中使用
c
int main(void)
{
float raw, filtered;
FIR_Init(&fir, fir_coeff, fir_buffer, FIR_ORDER);
while (1)
{
raw = read_adc(); // 读取采样数据
filtered = FIR_Process(&fir, raw);
output_dac(filtered); // 输出滤波后数据
}
}
五、整数版本(适合 STM32 / 51,无浮点)
1、Q15 定点 FIR
c
typedef struct
{
const int16_t *coeff;
int16_t *buffer;
uint16_t order;
uint16_t index;
} FIR_Q15_t;
int16_t FIR_Q15_Process(FIR_Q15_t *fir, int16_t input)
{
int32_t acc = 0;
uint16_t i;
fir->buffer[fir->index] = input;
for (i = 0; i < fir->order; i++)
{
int buf_idx = (fir->index - i + fir->order) % fir->order;
acc += (int32_t)fir->coeff[i] * fir->buffer[buf_idx];
}
fir->index = (fir->index + 1) % fir->order;
return (int16_t)(acc >> 15); // Q15 缩放
}
说明:
- 系数用
Q15格式(−32768 ~ 32767) - 适合 无 FPU 的 MCU
参考代码 用c语言实现的fir滤波器 www.youwenfan.com/contentcsv/103571.html
六、FIR 滤波器设计速查表
| 参数 | 建议值 |
|---|---|
| 阶数 | 16 / 32 / 64 |
| 窗函数 | Hamming / Hanning |
| 截止频率 | 0.1 ~ 0.4 × Fs |
| 类型 | 低通 / 高通 / 带通 |
七、常见问题
| 问题 | 原因 |
|---|---|
| 输出失真 | 阶数太低 |
| 延迟大 | FIR 本身线性相位 |
| 计算慢 | 阶数过高 |
| 整数溢出 | Q 格式不对 |