> 技术文档 > STM32-HAL库-fir 数字滤波_stm32 fir滤波器

STM32-HAL库-fir 数字滤波_stm32 fir滤波器


STM32-HAL库-fir 数字滤波

目录

STM32-HAL库-fir 数字滤波

前言:

FIR - IIR滤波器介绍:

正文:

一、获取滤波系数(MATLAB)

二、cubemx配置

三、代码示例

四、效果展示

结语:


前言:

        数字滤波器在信号处理领域具有广泛应用,主要用于从信号中去除噪声、调节频率特性等(重点还可以对ADC采集到的数据进行数字滤波)。常见的数字滤波器有有限脉冲响应(FIR)滤波器和无限脉冲响应(IIR)滤波器。本文将介绍如何使用HAL库,配合cubemx、keil5 和 MATLAB 在STM32上实现FIR数字滤波,并简要介绍FIR和IIR滤波器。

FIR - IIR滤波器介绍:

         FIR滤波器是有限冲激响应滤波器,意味着它的输出只取决于输入信号当前及前一段的输入值,并且当输入信号为零时,输出在有限时间内也会变为零。IIR滤波器是无限冲激响应滤波器,意味着其输出不仅依赖于当前及过去的输入信号,还依赖于过去的输出信号。这使得IIR滤波器能够用较少的滤波器阶数实现比FIR更为锐利的频率响应。

正文:

        由于本人能力有限,FIR - IIR滤波器的原理具体原理就不多阐述啦,下面主要介绍FIR数字滤波的使用和配置方法。原理可以看这位大佬的博客 《如何通俗易懂地理解FIR/IIR滤波器?》

        具体思路如下:先使用 MATLAB 中的 filterDesigner 插件获得数字滤波系数(.h文件),再使用ARM - stm32 DSP库中的 arm_fir_f32 函数进行数据处理,从而实现数字滤波功能。

一、获取滤波系数(MATLAB)

在MATLAB命令行窗口输入filterDesigner,打开数字滤波器插件。

 功能强大,有低通,高通,带通,带阻四种基本滤波器,还有陷阱滤波。(自行探索咯)

下面就以低通滤波器为例,生成.h文件。用记事本打开可以发现是一串系数。

二、cubemx配置

cubemx只要配置好ADC采样这些就好,具体的就不介绍了哈,可以看这篇博客。(放两张图)

————《stm32-HAL adc-tim-dma》

ADC:

TIM:

三、代码示例

先把生成的系数复制到main.c中。BL等于滤波器阶数加一,blockSize等于ADC采样数据个数。有点变化喔。

 uint16_t BL = 81;  //阶数+1 float TB[81] = { 0.0003733215541084,0.0005597595370856,0.0007032089937438,0.0007816223748768, 0.0007635302134055,0.0006133961927279,0.0003022834564525,-0.0001782455046338, -0.0008024840959284,-0.001501390200575,-0.002161792273028,-0.002636652511951, -0.002766891154709,-0.002412621521802,-0.001489016209688,1.698583283118e-18, 0.001937937076719, 0.004088948056519, 0.006113084319233, 0.007605175111664, 0.008154634004285, 0.007419115287379, 0.005201275366043, 0.001515703490696, -0.003367061280949,-0.008910368904051, -0.01434181123384, -0.01872486116841, -0.02106594816792, -0.02044482358268, -0.01615118061781, -0.00780793036515, 0.0045381188435, 0.02037404317152, 0.03873684202824, 0.05828960081546, 0.07745101436865, 0.0945634952261, 0.1080789628966, 0.1167381725366, 0.1197196677432, 0.1167381725366, 0.1080789628966, 0.0945634952261, 0.07745101436865, 0.05828960081546, 0.03873684202824, 0.02037404317152, 0.0045381188435, -0.00780793036515, -0.01615118061781, -0.02044482358268, -0.02106594816792, -0.01872486116841, -0.01434181123384,-0.008910368904051, -0.003367061280949, 0.001515703490696, 0.005201275366043, 0.007419115287379, 0.008154634004285, 0.007605175111664, 0.006113084319233, 0.004088948056519, 0.001937937076719,1.698583283118e-18,-0.001489016209688,-0.002412621521802, -0.002766891154709,-0.002636652511951,-0.002161792273028,-0.001501390200575, -0.0008024840959284,-0.0001782455046338,0.0003022834564525,0.0006133961927279, 0.0007635302134055,0.0007816223748768,0.0007032089937438,0.0005597595370856, 0.0003733215541084};  //滤波器系数 float32_t pState[1104]={0.0f}; //FIR滤波器状态变量暂存:数组的大小=BL+blocksize-1 uint32_t blockSize = 1024; //块处理大小,即ADC采样的数据个数

关于ADC采样的代码还是和上面那个博客中的一致,按照自己的需求配置和编写。

/* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */#define FFT_LENGTH 1024#define ADC1_DMA_Size 1024 //ADC采样个数#define SAM_FRE 500000 //采样率 float fft_outputbuf_win[FFT_LENGTH]; float fir_inputbuf[FFT_LENGTH]={0}; float fir_outputbuf[FFT_LENGTH]={0}; uint32_t ADC1_ConvertedValue[ ADC1_DMA_Size ];/* USER CODE END PD */

先使用arm_fir_instance_f32 *S函数实例化结构体 S ,再用malloc开辟内存空间,待ADC数据采集完成后传入fir待处理数组中,最后使用 arm_fir_init_f32 ; arm_fir_f32 函数进行数据处理。(里面的flag是判断ADC是否采集完成)

 arm_fir_instance_f32 *S;//FIR实例化结构体 HAL_TIM_Base_Start(&htim3); HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,ADC1_DMA_Size); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */while(1){if(flag==1){flag=0; //HAL_Delay(1000);S = (arm_fir_instance_f32 *)malloc(sizeof(arm_fir_instance_f32)); //开辟一个空间Sif (S == NULL) //如果开辟失败则报错{ printf(\"error\\r\\n\"); } for(i=0;i<FFT_LENGTH;i++) { fir_inputbuf[i]=(float)ADC1_ConvertedValue[ i ]*3.3/4096; //将ADC采样数据化为真实值传入fir_inputbuf中等待处理 } arm_fir_init_f32(S,BL,TB,pState,blockSize); arm_fir_f32(S,fir_inputbuf,fir_outputbuf,blockSize); free(S); // 释放内存 S = NULL; // 将指针设置为 NULL,以避免悬挂指针 for(i=0;i<FFT_LENGTH;i++) {printf(\"%f,%f\\r\\n\",(float)ADC1_ConvertedValue[i]*3.3/4096,fir_outputbuf[ i ]); } }HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,ADC1_DMA_Size); } /* USER CODE END WHILE */

四、效果展示

由于没在实验室,于是我使用了stm32 的 ADC 和 DAC 配合进行了验证。代码设计了一个30K的低通滤波器,当 DAC 输出一个50K频率的正弦波时,采样数据经过滤波后衰减,如下图。(红色为采样数据,绿色为滤波后的数据)

当 DAC 输出一个25K频率的正弦波时,采样数据经过滤波处理后幅度基本不变(看图有一些衰减,是由于25K与30K较近,根据幅频特性图像显示,会有稍微衰减,正常现象),如下图。(红色为采样数据,绿色为滤波后的数据)

 但是经过实验发现,fir处理过后的数据,前面会有一段异常(很少),为避免影响,可以令blockSize 大于ADC采样个数,然后舍弃前面几个数据。

结语:

        利用 FIR 数字滤波,可以快速方便地对采样数据进行处理,滤除高频噪声信号等等。在信号处理中,可以代替硬件完成低通-高通等滤波任务。更多的使用方法还需要大家自己探索。希望本次分享对大家有所帮助,如果有建议或错误,欢迎大家私聊或留言。有需要完整代码欢迎私信。