STM32-HAL库-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));  //开辟一个空间S
		if (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 数字滤波,可以快速方便地对采样数据进行处理,滤除高频噪声信号等等。在信号处理中,可以代替硬件完成低通-高通等滤波任务。更多的使用方法还需要大家自己探索。希望本次分享对大家有所帮助,如果有建议或错误,欢迎大家私聊或留言。有需要完整代码欢迎私信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值