STM32-HAL库-fir 数字滤波
目录
前言:
数字滤波器在信号处理领域具有广泛应用,主要用于从信号中去除噪声、调节频率特性等(重点还可以对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采样这些就好,具体的就不介绍了哈,可以看这篇博客。(放两张图)
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 数字滤波,可以快速方便地对采样数据进行处理,滤除高频噪声信号等等。在信号处理中,可以代替硬件完成低通-高通等滤波任务。更多的使用方法还需要大家自己探索。希望本次分享对大家有所帮助,如果有建议或错误,欢迎大家私聊或留言。有需要完整代码欢迎私信。