目录
2. Matlab工具箱filterDesigner生成IIR8阶椭圆滤波器系数
函数 arm_biquad_cascade_df1_init_f32
1.IIR滤波器介绍
ARM官方提供的直接I型IIR库支持Q7,Q15,Q31和浮点四种数据类型。其中Q15和Q31提供了快速版本。
直接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]
直接I型算法每个阶段需要5个系数和4个状态变量。
这里有一点要特别的注意,有些滤波器系数生成工具是采用的下面公式实现:
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
比如matlab就是使用上面的公式实现的,所以在使用fdatool工具箱生成的a系数需要取反才能用于直接I型IIR滤波器的函数中。
高阶IIR滤波器的实现是采用二阶Biquad级联的方式来实现的。其中参数numStages就是用来做指定二阶Biquad的个数。比如8阶IIR滤波器就可以采用numStages=4个二阶Biquad来实现。
如果要实现9阶IIR滤波器就需要将numStages=5,这时就需要其中一个Biquad配置成一阶滤波器(也就是b2=0,a2=0)。
2. Matlab工具箱filterDesigner生成IIR8阶椭圆滤波器系数
下面我们讲解如何通过filterDesigner工具箱生成滤波器系数。首先在matlab的命令窗口输入filterDesigner就能打开这个工具箱(电脑没有matlab也可以使用网页版的,本人用的就是网页版的):
filterDesigner界面打开效果如下:
我们需要的截止频率为10hz,采样率为250HZ,设置如下
默认生成的 IIR 滤波器类型是 Direct-Form II, Second-Order Sections(直接 II 型,每个
Section 是一个 二阶滤波器)。这里我们需要将其转换成Direct-Form I, Second-Order
Sections,因为本章使用的IIR滤波器函数是Direct-Form I的结构。 转换方法:点击 Edit->Convert
Structure,界面如下,这里我们选择第一项,并点击 OK:
转换好以后再点击 File-Export,第一项选择 Coefficient File(ASCII):
第一项选择好以后,第二项选择Decimal:
两个选项都选择好以后,点击 Export 进行导出,导出后保存即可。
保存后Matlab会自动打开untitled.fcf文件,可以看到生成的系数
由于前面选择的是8阶IIR滤波,生成的结果就是由4组二阶IIR滤波系数组成,系数的对应顺序如下:
由于Matlab设计IIR所使用的公式与DSP库函数中有所不同,故需对系数的处理:去掉每行的a0,并把a1,a2取反。经过处理后的系数才可与DSP库结合使用,另外下面4组是每个二阶滤波器的增益,滤波后的结果要乘以这4个增益数值才是实际结果:
0.608551805262785516781320893642259761691
0.420200533983016655259490335083683021367
0.188703183637426996632768805284285917878
0.008371840872980450265483653993214829825
实际的滤波系数调用方法,看下面的例子即可
3.DSP库的安装使用
通过GitHub下载,地址:GitHub - ARM-software/CMSIS_5: CMSIS Version 5 Development Repository
4.具体使用示例
函数 arm_biquad_cascade_df1_init_f32
void arm_biquad_cascade_df1_init_f32(
arm_biquad_casd_df1_inst_f32 * S,
uint8_t numStages,
const float32_t * pCoeffs,
float32_t * pState);
- 函数描述:
这个函数用于 IIR 初始化。 - 函数参数:
◆ 第 1 个参数是 arm_biquad_casd_df1_inst_f32 类型结构体变量。
◆ 第 2 个参数是 2 阶滤波器的个数。
◆ 第 3 个参数是滤波器系数地址。
◆ 第 4 个参数是缓冲状态地址
函数 arm_biquad_cascade_df1_f32
- 函数原型:
-
void arm_biquad_cascade_df1_f32( const arm_biquad_casd_df1_inst_f32 * S, float32_t * pSrc, float32_t * pDst, uint32_t blockSize);
函数描述:
这个函数用于 IIR 滤波。
函数参数:
◆ 第 1 个参数是 arm_biquad_casd_df1_inst_f32 类型结构体变量。
◆ 第 2 个参数是源数据地址。
◆ 第 3 个参数是滤波后的数据地址。
◆ 第 4 个参数是每次调用处理的数据个数,最小可以每次处理 1 个数据,最大可以每次全部处理完。 -
IIR滤波器与DSP库结合使用
-
/* * @Descripttion: main * @Author: Cheng * @Date: 2024-05-08 14:06:15 * @LastEditTime: 2024-05-08 14:06:15 * * Copyright 2024 */ #include "main.h" #include "arm_math.h" extern uint8_t read_flag; /*! \brief main function \param[in] none \param[out] none \retval none */ static FilterState x_filter_state; static FilterState y_filter_state; static FilterState z_filter_state; /*% 离散时间 IIR 滤波器(实数) % ---------------- % 滤波器结构 : 直接 I 型,二阶节 % 节数 : 4 % 稳定 : 是 % 线性相位 : 否 SOS 矩阵: b0 b1 b2 a0 a1 a2 1 -1.871329986332524564218715568131301552057 1 1 -1.883217591080840414008434891002252697945 0.937253227826082335738533402036409825087 1 -1.763596688085204311491338557971175760031 1 1 -1.841349414704919640328739660617429763079 0.874973529167388908156510751723544672132 1 -0.764306729111819960209572855092119425535 1 1 -1.803936748444220583564856497105211019516 0.817480187395823065799049800261855125427 1 -1.896005581016128482829685708566103130579 1 1 -1.916868836897071881608667354157660156488 0.981783959561862595855075142026180401444 注意,实际使用ARM官方的IIR函数调用的时候要将a1和a2取反,a0不要。另外下面4组是每个二阶滤波器的增益,滤波后的结果要乘以这4个增益数值才是实际结果: 定标值: 0.608551805262785516781320893642259761691 0.420200533983016655259490335083683021367 0.188703183637426996632768805284285917878 0.008371840872980450265483653993214829825 */ // 定义滤波器系数 #define FILTER_ORDER 8 #define NUM_STAGES (FILTER_ORDER / 2) const float32_t sos_coeffs[NUM_STAGES * 5] = { 1.0f, -1.871329986332524564218715568131301552057, 1.0f, 1.883217591080840414008434891002252697945,-0.937253227826082335738533402036409825087, 1.0f, -1.763596688085204311491338557971175760031,1.0f, 1.841349414704919640328739660617429763079, -0.874973529167388908156510751723544672132, 1.0f, -0.764306729111819960209572855092119425535, 1.0f, 1.803936748444220583564856497105211019516, -0.817480187395823065799049800261855125427, 1.0f, -1.896005581016128482829685708566103130579, 1.0f, 1.916868836897071881608667354157660156488, -0.981783959561862595855075142026180401444 }; float32_t IIRState[4 * NUM_STAGES]; int main(void) { static uint8_t data_ready_flag = 0; static float x_measure_data = 0; static float y_measure_data = 0; static float z_measure_data = 0; static float xfiltered, yfiltered, zfiltered; static int initialized = 0; float32_t ScaleValue=(0.608551805262785516781320893642259761691f*0.420200533983016655259490335083683021367f* 0.188703183637426996632768805284285917878f*0.008371840872980450265483653993214829825f); systick_config(); Uart_Printf_Init(); // 定义滤波器实例 arm_biquad_casd_df1_inst_f32 S; // 初始化滤波器系数 // 初始化滤波器结构 //arm_biquad_cascade_df2T_init_f32(&S, NUM_STAGES, biquadCoeffs, biquadState); arm_biquad_cascade_df1_init_f32(&S, NUM_STAGES, (float32_t *)&sos_coeffs[0], (float32_t *)&IIRState[0]); while (1) { if (read_flag) { x_measure_data = ((measure_data.x_data) / adxl355Scale); y_measure_data = ((measure_data.y_data) / adxl355Scale); z_measure_data = ((measure_data.z_data) / adxl355Scale) - 1; // 应用滤波器 arm_biquad_cascade_df1_f32(&S, &x_measure_data, &xfiltered, 1); arm_biquad_cascade_df1_f32(&S, &y_measure_data, &yfiltered, 1); arm_biquad_cascade_df1_f32(&S, &z_measure_data, &zfiltered, 1); //arm_biquad_cascade_df2T_f32(&S, &z_measure_data, &zfiltered, 1); printf("\r\nacceleration data:%.4f,%.4f,%.4f\r\n", x_measure_data, y_measure_data, z_measure_data); printf("\r\n filter acceleration data:%.4f,%.4f,%.4f\r\n", xfiltered*ScaleValue, yfiltered*ScaleValue, zfiltered*ScaleValue); read_flag = 0; } } }
-
更新:注意本例程对x,y,z三轴数据进行滤波,则float32_t IIRState[4 * NUM_STAGES];和arm_biquad_casd_df1_inst_f32 S;
-
需要三个不同的定义:
-
float32_t IIRStateX[4 * NUM_STAGES];arm_biquad_casd_df1_inst_f32 SX;
-
float32_t IIRStateY[4 * NUM_STAGES];arm_biquad_casd_df1_inst_f32 SY;
-
float32_t IIRStateZ[4 * NUM_STAGES];arm_biquad_casd_df1_inst_f32 SZ;
-
否则会造成滤波数据有错
-
参考:【STM32H7的DSP教程】第6章 ARM DSP源码和库移植方法(MDK5的AC5和AC6)_arm移植dsp库-CSDN博客
【STM32F429的DSP教程】第44章 STM32F429的IIR低通滤波器实现(支持逐个数据的实时滤波)_低通滤波 实时-CSDN博客
【电赛仪器仪表】基于MATLAB的数字滤波器设计与ARM官方DSP库的结合_基于stm32f10x的fir滤波器设计与实现-CSDN博客