37.6 FIR带阻滤波器设计
37.6.1 fdatool获取带阻滤波器系数 设计一个如下的例子: 信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个带阻滤波器,截止频率125Hz和300Hz,采样320个数据,采用函数fir1进行设计(注意这个函数是基于窗口的方法设计FIR滤波,默认是hamming窗),滤波器阶数设置为28。fadtool的配置如下:
配置好带阻滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。
37.6.2 带阻滤波器实现 通过工具箱fdatool获得带阻滤波器系数后在开发板上运行函数arm_fir_f32 来测试带通滤波器的效果。
- #define TEST_LENGTH_SAMPLES 320 /* 采样点数 */
- #define BLOCK_SIZE 32 /* 调用一次arm_fir_f32处理的采样点个数 */
- #define NUM_TAPS 29 /* 滤波器系数个数 */
-
- uint32_t blockSize = BLOCK_SIZE;
- uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE; /* 需要调用arm_fir_f32的次数 */
-
- static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
- static float32_t testOutput[TEST_LENGTH_SAMPLES]; /* 滤波后的输出 */
- static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1]; /* 状态缓存,大小numTaps + blockSize - 1*/
-
- /* 带阻滤波器系数 通过fadtool获取*/
- const float32_t firCoeffs32BPCheb[NUM_TAPS] = {
- 0.01801843569f, 0.0007182828849f, -0.004868913442f, 0.002710500965f, -0.01462193858f,
- -0.03147283196f, 0.01435638033f, 0.04055848345f, 0.00197162549f, 0.03706155345f,
- 0.06650412083f, -0.1269270927f, -0.2418768406f, 0.07591249049f, 0.3445736468f,
- 0.07591249049f, -0.2418768406f, -0.1269270927f, 0.06650412083f, 0.03706155345f,
- 0.00197162549f, 0.04055848345f, 0.01435638033f, -0.03147283196f, -0.01462193858f,
- 0.002710500965f, -0.004868913442f, 0.0007182828849f, 0.01801843569f
- };*/
- const float32_t firCoeffs32BS[NUM_TAPS] = {
- -0.003560454352f, -0.0002683042258f, 0.001964005642f, -0.001277366537f, 0.008085897192f,
- 0.02002927102f, -0.01026879996f, -0.03190089762f, -0.001673383522f, -0.0334023945f,
- -0.06278027594f, 0.1240097657f, 0.2419839799f, -0.07700803876f, 0.6521340013f,
- -0.07700803876f, 0.2419839799f, 0.1240097657f, -0.06278027594f, -0.0334023945f,
- -0.001673383522f, -0.03190089762f, -0.01026879996f, 0.02002927102f, 0.008085897192f,
- -0.001277366537f, 0.001964005642f, -0.0002683042258f, -0.003560454352f
- };
-
- /*
- *********************************************************************************************************
- * 函 数 名: arm_fir_f32_bs
- * 功能说明: 调用函数arm_fir_f32_bs实现带阻滤波器
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void arm_fir_f32_bs(void)
- {
- uint32_t i;
- arm_fir_instance_f32 S;
- float32_t *inputF32, *outputF32;
-
- /* 初始化输入输出缓存指针 */
- inputF32 = &testInput_f32_50Hz_200Hz[0];
- outputF32 = &testOutput[0];
-
- /* 初始化结构体S */
- arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32BS[0], &firStateF32[0], blockSize);
-
- /* 实现FIR滤波 */
- for(i=0; i < numBlocks; i++)
- {
- arm_fir_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize), blockSize);
- }
-
- /* 打印滤波后结果 */
- for(i=0; i
- {
- printf("%frn", testOutput[i]);
- }
- }
复制代码
运行如上函数可以通过串口打印出函数arm_fir_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。 对比前需要先将串口打印出的一组数据加载到Matlab中, arm_fir_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
- %****************************************************************************************
- % FIR带阻滤波器设计
- %***************************************************************************************
- fs=1000; %设置采样频率 1K
- N=320; %采样点数
- n=0:N-1;
- t=n/fs; %时间序列
- f=n*fs/N; %频率序列
-
- x=sin(2*pi*50*t)+sin(2*pi*200*t); %50Hz和200Hz正弦波混合
- b=fir1(28, [125/500 300/500], 'stop'); %获得滤波器系数,截止频率125Hz和300,带阻滤波。
- y=filter(b, 1, x); %获得滤波后的波形
- subplot(211);
- plot(t, y);
- title('Matlab FIR滤波后的实际波形');
- grid on;
-
- subplot(212);
- plot(t, sampledata); %绘制ARM官方库滤波后的波形。
- title('ARM官方库滤波后的实际波形');
- grid on;
复制代码
Matlab运行结果如下:
从上面的波形对比来看,matlab和函数arm_fir_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
- %****************************************************************************************
- % FIR带阻滤波器设计
- %***************************************************************************************
- fs=1000; %设置采样频率 1K
- N=320; %采样点数
- n=0:N-1;
- t=n/fs; %时间序列
- f=n*fs/N; %频率序列
-
- x=sin(2*pi*50*t)+sin(2*pi*200*t); %50Hz和200Hz正弦波混合
- subplot(221);
- plot(t, x); %绘制信号x的波形
- xlabel('时间');
- ylabel('幅值');
- title('原始信号');
- grid on;
-
- subplot(222);
- y=fft(x, N); %对信号x做FFT
- plot(f,abs(y));
- xlabel('频率/Hz');
- ylabel('振幅');
- title('原始信号FFT');
- grid on;
-
- y3=fft(sampledata, N); %经过FIR滤波器后得到的信号做FFT
- subplot(223);
- plot(f,abs(y3));
- xlabel('频率/Hz');
- ylabel('振幅');
- title('滤波后信号FFT');
- grid on;
-
- b=fir1(28, [125/500 300/500], 'stop'); %获得滤波器系数,截止频率125Hz和300Hz,带阻滤波。
- [H,F]=freqz(b,1,160); %通过fir1设计的FIR系统的频率响应
- subplot(224);
- plot(F/pi,abs(H)); %绘制幅频响应
- xlabel('归一化频率');
- title(['Order=',int2str(28)]);
- grid on;
复制代码
Matlab运行效果如下:
上面波形变换前的FFT和变换后FFT可以看出,200Hz的正弦波基本被滤除。
|