我们来实际操作STM32F4 DSP库的IIR滤波器。
与IIR滤波器函数有关的源文件如下图所示:
STM32F4 DSP库中采用biquad作为一个单元。一个biquad是2阶,n个biquad串联之后就是n阶滤波器。
基本的单元结构如下所示:
我们可以求出一个biquad的差分函数形式是:
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
Matlab里的计算就是按照上面的式子计算的,但是STM32F4 DSP库里的系数a1,a2是取反的。
下面就介绍如何使用MATLAB设计IIR滤波器。
举个例子,我们要设计一个采样率为1kHz,4阶,截止频率100Hz的巴特沃斯滤波器。
首先和设计FIR滤波器一样,首先在MATLAB命令窗口输入fdatool,调出滤波器设计窗口
按照方框所示设置好参数:
点击Design Filter:
注意红框里面是直接II型,我们要把他改为直接I型。
点击Edit->Convert Structure,选择I型:
转化好后,点击File-Export,
第一项选择Coefficient File(ASCII):
第一项选择好以后,第二项选择Decimal:
点击Export,保存后生成如下文件:
系数对应如下:
1 2 1 1 -1.32091343081942 0.63273879288527657
b0 b1 b2 a0 a1 a2
1 2 1 1 -1.0485995763626117 0.29614035756166951
b0 b1 b2 a0 a1 a2
实际使用ARM官方的IIR函数调用的时候要将a1和a2取反。把a0去掉
Scale Values表示每个biquad的增益系数。所以最后用STM32计算后,要乘以这两个系数。
设计滤波器系数之后,我们来看STM32的IIR滤波器函数:
主要介绍下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)
参数:
*S points to an instance of the floating-point Biquad cascade structure.
*pSrc points to the block of input data.
*pDst points to the block of output data.
blockSize number of samples to process per call.
介绍下结构体arm_biquad_casd_df1_inst_f32
typedef struct
{
//< number of 2nd order stages in the filter. Overall order is 2*numStages.
uint32_t numStages;
//< Points to the array of state coefficients. The array is of length 4*numStages. float32_t *pState;
//< Points to the array of coefficients. The array is of length 5*numStages.
float32_t *pCoeffs;
} arm_biquad_casd_df1_inst_f32;
注意下:pState指向的数组长度是4倍numStages长度
pCoeffs指向的数组长度是5倍numStages长度,a0默认为1,不需要放入
numStages表示biquad个数;
好,接下来我们就可以使用这个函数了
#define numStages 2
#define TEST_LENGTH_SAMPLES 1024
float32_t testInput_f32[TEST_LENGTH_SAMPLES];
float32_t testOutput[TEST_LENGTH_SAMPLES];
float32_t IIRStateF32[4*numStages];
const float32_t IIRCoeffs32LP[5*numStages] =
{
1.0f, 2.0f, 1.0f, 1.32091343081942f, -0.63273879288527657f,
1.0f, 2.0f, 1.0f, 1.0485995763626117f, -0.29614035756166951f
};
void arm_iir_f32_lp(void)
{
uint32_t i;
arm_biquad_casd_df1_inst_f32 S;
float32_t ScaleValue;
for(i=0;i testInput_f32[i]=1.2f*arm_sin_f32(2*PI*50*i/1000)+arm_sin_f32(2*PI*250*i/1000)+1; printf("%frn", testInput_f32[i]); } arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t *)&IIRStateF32[0]); arm_biquad_cascade_df1_f32(&S, testInput_f32, testOutput, TEST_LENGTH_SAMPLES); ScaleValue = 0.0779563405162552f * 0.0618851952997481f; for(i=0; i printf("%frn", testOutput[i]*ScaleValue); } } 把原始信号和过滤后信号打印出来,导入到matlab,用下面程序处理: Fs=1000; N=1024; n=0:1:N-1; f=Fs*n/N; t=0:1/Fs:(N-1)/Fs; subplot(2,2,1); plot(t(1:150),data1(1:150)); xlabel('时间/s'); ylabel('幅度/v'); title('原始信号波形图'); h1=fft(data1,N); subplot(2,2,2); plot(t(1:150),data2(1:150)); xlabel('时间/s'); ylabel('幅度/v'); title('过滤后信号波形图'); subplot(2,2,3); plot(f,abs(h1)); xlabel('频率/Hz'); ylabel('幅度'); title('原始信号频谱图'); subplot(2,2,4); h2=fft(data2,N); plot(f,abs(h2)); xlabel('频率/Hz'); ylabel('幅度'); title('过滤后信号频谱图'); 运行结果: 可以看出STM32的IIR滤波器的计算结果还是令人满意的。