在这里插入代码片@[toc]
概要
直接I型IIR滤波器是基于二阶Biquad级联的方式来实现的。每个Biquad由一个二阶的滤波器组成:
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
Matlab相关参数获取
在matlab中运行
`Matlab相关参数获取
Fs = 40e3; % 采样频率
Fcut = 1e3; % 截止频率
N = 4; % 滤波器阶数
% 计算归一化截止频率
Wn = Fcut / (Fs/2);
% 使用butter函数计算滤波器系数
[b, a] = butter(N, Wn, 'low');
disp('b coefficients:');
disp(b);
disp('a coefficients:');
disp(a);
`## 技术名词解释
提示:这里可以添加技术名词解释
```c
IIR滤波算法
#define NUM_TAPS 4 // 滤波器阶数
int input[200] = {}; // 输入信号(AD采集的数据)
float output[200]; // 输出信号
float a[NUM_TAPS + 1] = {1, -3.5897, 4.8513, -2.9241, 0.663}; // 滤波器系数a
float b[NUM_TAPS + 1] = {0.0000312, 0.000125,0.0001874, 0.000125, 0.0000312}; // 滤波器系数b
int delayLine[NUM_TAPS + 1]; // 延迟线
void IIR_Filter(int * input, float* output, int numSamples)
{
for (int j = 0; j < numSamples; j++)
{
// 更新延迟线
for (int i = NUM_TAPS; i > 0; i--)
{
delayLine[i] = delayLine[i - 1];
}
delayLine[0] = input[j];
// 计算输出
float sum = 0;
for (int i = 0; i <= NUM_TAPS; i++)
{
sum += b[i] * delayLine[i];
if (i > 0)
{
sum -= a[i] * output[j - i];
}
}
output[j] = sum ;
}
}
int main(void)
```c
{
int m ;
systick_config();
USART0_init();
timer1_config();
// 初始化延迟线
for (int i = 0; i <= NUM_TAPS; i++)
{
delayLine[i] = 0;
}
// 调用IIR滤波器
IIR_Filter(input, output, 200);
// 输出滤波后的数字
for (int i = 0; i < 200; i++)
{
printf("%f,\r\n", output[i]);
}
while(1);
}
输入输出数据对比
matlab输出输出对比程序
y = A1;
figure(1);
plot(y);%画出输入信号图形
title('输入信号');
Hd = fir;%引入滤波器,Hd包含了fir_8滤波器的各项参数
d = filter(Hd,y);%通过filter函数将信号y送入参数为Hd的滤波器,输出信号d
figure(2);
plot(d);%画出通过滤波器的信号d的波形
title('输出信号');
figure(3);
plot(y,'r');%画出输入信号图形
hold on;%保持画出的输入信号图形
plot(d,'b');%画出输出信号波形
title('输入/输出信号');
legend('输入信号','输出信号');
matlabIIR滤波器设计方法:对于不同类型的滤波器需要转化结构类型,FS的采样频率需要与AD的采样频率保持一致,它是滤波器的采样频率,FS越大在前面延时数据越多,可以通过调节FS来确定理想的滤波器。FC是截至频率。上述的IIR滤波算法是单节类型的结构。
在有DSP功能的单片机中可以使用DSP中的IIR库函数进行数据的实时处理****以下对DSP,iir库进行简单说明
/****************IIR滤波**********************/
#define numStages 2 /* 2阶IIR滤波的个数 */
#define TEST_LENGTH_SAMPLES 200 /* 采样点数 */
#define BLOCK_SIZE 200 /* 调用一次arm_biquad_cascade_df1_f32处理的采样点个数 */
uint32_t blockSize = BLOCK_SIZE;
uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE; /* 需要调用arm_biquad_cascade_df1_f32的次数 */
float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]={0}; /* 采样点 */
float32_t testOutput[TEST_LENGTH_SAMPLES]; /* 滤波后的输出 */
static float32_t IIRStateF32[4*numStages]; /* 状态缓存 */
arm_biquad_casd_df1_inst_f32 S;
static int m=0 ;
static int n=0 ;
/* 巴特沃斯低通滤波器系数 */
const float32_t IIRCoeffs32LP[5*numStages] = {
1.0f, 2.0f, 1.0f, 1.987804709796042512692793025053106248379f,
-0.988049970587248416187264865584438666701f,
1.0f, 2.0f, 1.0f, 1.971148608851041927891856175847351551056f,
-0.971391814566879729930803932802518829703f `在这里插入代码片`
};
uint16_t adc_dma_value[200];
static void arm_iir_f32_lp(void)
{
uint32_t i;
// arm_biquad_casd_df1_inst_f32 S;
// float32_t ScaleValue;
float32_t *inputF32, *outputF32;
/* 初始化输入输出缓存指针 */
inputF32 = &testInput_f32_50Hz_200Hz[0];
outputF32 = &testOutput[0];
/* 初始化 */
if(m==0){
arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0],
(float32_t *)&IIRStateF32[0]);
m=1;
}
/* 实现IIR滤波,这里每次处理1个点 */
for(i=0; i < numBlocks; i++)
{
arm_biquad_cascade_df1_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize),
blockSize);
}
}
``
unsigned int GetAD (void)
{
int i ;
float32_t sum=0.f ;
float32_t average ;
float32_t ScaleValue;
float32_t result;
long AD_Value=0;
// n++;
//标定值,arm_biquad_cascade_df1_f32();函数输出的out数据需要乘以标定值才是真实值
ScaleValue = 0.000061315197801517181720731830552040265f * 0.000060801428959431312582222667328935017f ;
//数据类型转化
for (i = 0; i < TEST_LENGTH_SAMPLES; i++) {
testInput_f32_50Hz_200Hz[i] = adc_dma_value[i];
}
arm_iir_f32_lp();
if(n<3)
{
n++;
return Threshold;
}
for (i = 0; i < 200; i++) {
sum += testOutput[i]*ScaleValue;
}
average = (float)sum / 200;
//result = average*ScaleValue;
AD_Value=(int)average;
return (uint16_t )AD_Value;
}
上述代码实现ADC不停的采集数据,通过DMA传输,DMA每采集200个数据就触发中断,在DMA中断中运行getAD()函数进行滤波处理。实现了每采集两百个数据进行一次滤波的实时处理,可以对采集数据和处理数据进行修改。其中的n用来避免刚开始运行的时候产生的无效数据对整体功能的影响,m用来限制只初始化一次,然后持续运行出来函数。
arm_biquad_cascade_df1_init_f32();初始化函数
arm_biquad_cascade_df1_f32();处理函数
上述IIR滤波器的结构,和参数的获取可以参考[添加链接描述](https://img.anfulai.cn/bbs/94547/%E5%AE%89%E5%AF%8C%E8%8E%B1_STM32-V5%E5%BC%80%E5%8F%91%E6%9D%BF_%E7%AC%AC2%E7%89%88DSP%E6%95%B0%E5%AD%97%E4%BF%A1%E5%8F%B7%E5%A4%84%E7%90%86%E6%95%99%E7%A8%8B%EF%BC%88V2.7%EF%BC%89.pdf)
实时处理需要注意在DMA执行中断程序的时候,ADC还是会持续工作,表示DMA传输的地址中的值还是会持续的更新。
## 技术细节
` 提示:这里可以添加技术细节`
例如:
* API
* 支持模型类型
## 小结
` 提示:这里可以添加总结`
例如:
提供先进的推理,复杂的指令,更多的创造力。