1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转dsp系列教程
本章节讲解FIR滤波器的低通,高通,带通和带阻滤波器的实现。 37.1 FIR滤波器介绍 37.2 matlab工具箱生成C头文件 37.3 FIR低通滤波器设计 37.4 FIR高通滤波器设计 37.5 FIR带通滤波器设计 37.6 FIR带阻滤波器设计 37.7 切比雪夫窗口设计带通滤波器 37.8 FIR滤波后的群延迟 37.9 总结 37.1 FIR滤波器介绍 ARM官方提供的FIR库支持Q7,Q15,Q31和浮点四种数据类型。其中Q15和Q31提供了快速算法版本。 FIR滤波器的基本算法是一种乘法-累加(MAC)运行,输出表达式如下: y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1] 结构图如下: 这种网络结构就是在35.2.1小节所讲的直接型结构。 |
|
相关推荐
|
|
37.2 Matlab工具箱fdatool生成C头文件
下面我们讲解下如何通过fdatool工具生成C头文件,也就是生成滤波器系数。首先在matlab的命 窗口输入fadtool就能打开这个工具箱: fadtool界面打开效果如下: |
|
|
|
|
|
FIR滤波器的低通,高通,带通,带阻滤波的设置会在下面一一讲解,这里说一下设置后相应参数后如何生成滤波器系数。参数设置好以后点击如下按钮:
点击Design Filter按钮以后就生成了所需的滤波器系数,生成滤波器系数以后点击fadtool界面上的菜单Targets->Generate C header ,打开后显示如下界面: |
|
|
|
|
|
再点击保存,并打开fdatool.h文件,可以看到生成的系数:
复制代码 /* * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool * * Generated by MATLAB(R) 7.14 and the Signal Processing Toolbox 6.17. * * Generated on: 22-Dec-2014 21:34:29 * */ /* * Discrete-Time FIR Filter (real) * ------------------------------- * Filter Structure : Direct-Form FIR * Filter Length : 51 * Stable : Yes * Linear Phase : Yes (Type 1) */ /* General type conversion for MATLAB generated C-code */ #include "tmwtypes.h" /* * Expected path to tmwtypes.h * C:Program FilesMATLABR2012aexternincludetmwtypes.h */ /* * Warning - Filter coefficients were truncated to fit specified data type. * The resulting response may not match generated theoretical response. * Use the Filter Design & Analysis Tool to design accurate * single-precision filter coefficients. */ const int BL = 51; const real32_T B[51] = { -0.0009190982091, -0.00271769613,-0.002486952813, 0.003661438357, 0.0136509249, 0.01735116541, 0.00766530633,-0.006554719061,-0.007696784101, 0.006105459295, 0.01387391612,0.0003508617228, -0.01690892503,-0.008905642666, 0.01744112931, 0.02074504457, -0.0122964941, -0.03424086422,-0.001034529647, 0.04779030383, 0.02736303769, -0.05937951803, -0.08230702579, 0.06718690693, 0.3100151718, 0.4300478697, 0.3100151718, 0.06718690693, -0.08230702579, -0.05937951803, 0.02736303769, 0.04779030383,-0.001034529647, -0.03424086422, -0.0122964941, 0.02074504457, 0.01744112931,-0.008905642666, -0.01690892503,0.0003508617228, 0.01387391612, 0.006105459295,-0.007696784101,-0.006554719061, 0.00766530633, 0.01735116541, 0.0136509249, 0.003661438357,-0.002486952813, -0.00271769613, -0.0009190982091 }; 上面数组B[51]中的数据就是滤波器系数。下面小节讲解如何使用fdatool配置FIR低通,高通,带通和带阻滤波。关于fdatool的其它用法, 大家可以在matlab命令窗口中输入help fadtool打开帮助文档进行学习。 |
|
|
|
|
|
37.3 FIR低通滤波器设计
本章使用的FIR滤波器函数是arm_fir_f32。下面使用此函数设计FIR低通,高通,带通和带阻滤波器。 37.3.1 函数arm_fir_f32说明 函数定义如下: void arm_fir_f32( const arm_fir_instance_f32 * S, float32_t * pSrc, float32_t * pDst, uint32_t blockSize) 参数定义: [in] *S points to an instance of the floating-point FIR filter structure. [in] *pSrc points to the block of input data. [out] *pDst points to the block of output data. [in] blockSize number of samples to process per call. return none. 注意事项: 结构arm_fir_instance_f32的定义如下(在文件arm_math.h文件): typedef struct { uint16_t numTaps; /**< number of filter coefficients in the filter. */ float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ } arm_fir_instance_f32; 1. 参数pCoeffs指向滤波因数,滤波因数数组长度为numTaps。但要注意pCoeffs指向的滤波因数应该按照如下的逆序进行排列: {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]} 但满足线性相位特性的FIR滤波器具有奇对称或者偶对称的系数,偶对称时逆序排列还是他本身。 2. pState指向状态变量数组,这个数组用于函数内部计算数据的缓存。 3. blockSize 这个参数的大小没有特殊要求,用户只需保证大于1小于等于采样点个数即可。 |
|
|
|
|
|
37.3.2 fdatool获取低通滤波器系数
设计一个如下的例子: 信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个低通滤波器,截止频率125Hz,采样320个数据,采用函数fir1进行设计(注意这个函数是基于窗口的方法设计FIR滤波,默认是hamming窗),滤波器阶数设置为28。fadtool的配置如下: 配置好低通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。 |
|
|
|
|
|
37.3.3 低通滤波器实现
通过工具箱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 firCoeffs32LP[NUM_TAPS] = { -0.001822523074f, -0.001587929321f, 1.226008847e-18f, 0.003697750857f, 0.008075430058f, 0.008530221879f, -4.273456581e-18f, -0.01739769801f, -0.03414586186f, -0.03335915506f, 8.073562366e-18f, 0.06763084233f, 0.1522061825f, 0.2229246944f, 0.2504960895f, 0.2229246944f, 0.1522061825f, 0.06763084233f, 8.073562366e-18f, -0.03335915506f, -0.03414586186f, -0.01739769801f, -4.273456581e-18f, 0.008530221879f, 0.008075430058f, 0.003697750857f, 1.226008847e-18f, -0.001587929321f, -0.001822523074f }; /* ********************************************************************************************************* * 函 数 名: arm_fir_f32_lp * 功能说明: 调用函数arm_fir_f32_lp实现低通滤波器 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ static void arm_fir_f32_lp(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 *)&firCoeffs32LP[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, 0.25); y=filter(b, 1, x); subplot(211); plot(t, y); title('Matlab FIR滤波后的波形'); grid on; subplot(212); plot(t, sampledata); title('ARM官方库滤波后的波形'); grid on; |
|
|
|
|
|
从上面的波形对比来看,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); %绘制信号Mix_Signal的波形 xlabel('时间'); ylabel('幅值'); title('原始信号'); grid on; subplot(222); y=fft(x, N); %对信号 Mix_Signal做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, 0.25); %28阶FIR低通滤波器,截止频率125Hz [H,F]=freqz(b,1,512); %通过fir1设计的FIR系统的频率响应 subplot(224); plot(F/pi,abs(H)); %绘制幅频响应 xlabel('归一化频率'); title(['Order=',int2str(30)]); grid on; |
|
|
|
|
|
37.4 FIR高通滤波器设计
37.4.1 fdatool获取高通滤波器系数 设计一个如下的例子: 信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个高通滤波器,截止频率125Hz,采样320个数据,采用函数fir1进行设计(注意这个函数是基于窗口的方法设计FIR滤波,默认是hamming窗),滤波器阶数设置为28。fadtool的配置如下: 配置好高通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。 |
|
|
|
|
|
37.4.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 firCoeffs32HP[NUM_TAPS] = { 0.0018157335f, 0.001582013792f, -6.107207639e-18f, -0.003683975432f, -0.008045346476f, -0.008498443291f, -1.277260999e-17f, 0.01733288541f, 0.03401865438f, 0.0332348831f, -4.021742543e-17f, -0.06737889349f, -0.1516391635f, -0.2220942229f, 0.7486887574f, -0.2220942229f, -0.1516391635f, -0.06737889349f, -4.021742543e-17f, 0.0332348831f, 0.03401865438f, 0.01733288541f, -1.277260999e-17f, -0.008498443291f, -0.008045346476f, -0.003683975432f, -6.107207639e-18f, 0.001582013792f, 0.0018157335f }; /* ********************************************************************************************************* * 函 数 名: arm_fir_f32_hp * 功能说明: 调用函数arm_fir_f32_hp实现高通滤波器 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ static void arm_fir_f32_hp(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 *)&firCoeffs32HP[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, 'high'); %获得滤波器系数,截止频率125Hz,高通滤波。 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和函数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, 'high'); %获得滤波器系数,截止频率125Hz,高通滤波。 [H,F]=freqz(b,1,512); %通过fir1设计的FIR系统的频率响应 subplot(224); plot(F/pi,abs(H)); %绘制幅频响应 xlabel('归一化频率'); title(['Order=',int2str(30)]); grid on; |
|
|
|
|
|
37.5 FIR带通滤波器设计
37.5.1 fdatool获取带通滤波器系数 设计一个如下的例子: 信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个带通滤波器,截止频率125Hz和300Hz,采样320个数据,采用函数fir1进行设计(注意这个函数是基于窗口的方法设计FIR滤波,默认是hamming窗),滤波器阶数设置为28。fadtool的配置如下: 配置好带通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。 |
|
|
|
|
|
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
770 浏览 0 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
544 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
677 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
904 浏览 2 评论
649 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11990 浏览 31 评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 16:53 , Processed in 1.275238 second(s), Total 70, Slave 63 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号