STM32利用arm-dsp库进行FIR低通滤波【详细】

avatar
作者
筋斗云
阅读量:0

arm-dsp库官方已经封装好了,使用的时候需要把dsp库移植到工程里面,具体怎么移植网上可以找到教程

这里直接说怎么用FIR的流程:

一、Matlab里面生成所配置的阶数和系数

1、在Matlab命令窗口输入fdatool,回车,会弹出一个新窗口

1c8fcbb9ef9f44afbf4a1ee88837be8e.png

2、在新窗口中的响应类型选择【低通】,设计方法选择【 FIR里面的最平坦】,滤波器阶数选择【指定阶 80】(这里以80举例),频率设置选择【Hz,Fs3200,Fc200】(同样也是举例,后面自己按照需求改动),选择完后点击设计滤波器,并在上方【编辑】中点击【转换结构】选择【Direct-Form FIR】在点击确认

2f435abc56524f63a350a6e74a89396e.png

 5b765e952e0d430fbab72bc29760f216.png

3、在上方选择【目标】中的【生成C的头文件】 ,改变导出类型为【单精度浮点】,然后点击生成保存到文件夹中

209ab19dd5d64efba1d9f235d88e80fb.png

0fe9dd0262dd42e1af967eed6960493b.png

二、在keil 写相关程序

主要是用到了dsp库里面这两个函数

b82722abcadb451a8e5bb7a50b9e4ba6.png

我们先把要处理的数据放进一个数组,我自己使用的ADC采集信号发生器发出的基频为100Hz的信号。

将ADC采集的数据转换为电压存入一个数组中

uint32_t i=0; for(i=0;i<256;i++) {     inbuf[i]=(float)(ADC1_ConvertedValue[i]*3.3/4096); }

接下来就要配置上面用的函数了

//FIR实例化结构体  arm_fir_instance_f32 * S;

 还记得刚刚Matlab生成的文件吗?打开这个文件,复制这些到工程里面去。

585be2016d5b4e29ba00f9cc0de68074.png

//FIR滤波器系数个数 uint16_t numTaps=81;
//FIR滤波器系数 float32_t  pCoeffs[81]={   3.671998324e-22,2.631265729e-20,9.278031016e-19, 2.14557019e-17,3.659253801e-16,   4.907191783e-15,5.387333849e-14, 4.97747839e-13,3.948472625e-12,2.730093235e-11,   1.664632598e-10,9.033196413e-10,4.394613118e-09,1.927893756e-08,7.661567736e-08,   2.767831404e-07,9.112107477e-07,2.737595878e-06,7.507435839e-06,1.876901842e-05,   4.263511073e-05,8.741336933e-05,0.0001597262308,0.0002535805688,0.0003294369671,   0.0002852701291,-6.710144226e-05,-0.0009913889226,-0.002741852077, -0.00537379086,    -0.00846511405, -0.01084412821, -0.01049835142,-0.004857060499, 0.008461467922,     0.03057124838,   0.0603001751,  0.09375944734,   0.1249034405,   0.1470876038,      0.1551340818,   0.1470876038,   0.1249034405,  0.09375944734,   0.0603001751,     0.03057124838, 0.008461467922,-0.004857060499, -0.01049835142, -0.01084412821,    -0.00846511405, -0.00537379086,-0.002741852077,-0.0009913889226,-6.710144226e-05,   0.0002852701291,0.0003294369671,0.0002535805688,0.0001597262308,8.741336933e-05,   4.263511073e-05,1.876901842e-05,7.507435839e-06,2.737595878e-06,9.112107477e-07,   2.767831404e-07,7.661567736e-08,1.927893756e-08,4.394613118e-09,9.033196413e-10,   1.664632598e-10,2.730093235e-11,3.948472625e-12, 4.97747839e-13,5.387333849e-14,   4.907191783e-15,3.659253801e-16, 2.14557019e-17,9.278031016e-19,2.631265729e-20,   3.671998324e-22 };
//FIR滤波器状态变量暂存:数组的大小=numTaps+blocksize-1 float32_t  pState[336]={0.0f};
//块处理大小 uint32_t blockSize=256;
//输入数据 float32_t inbuf[256]={0};  //输出数据 float32_t outbuf[256]=	{0};

 接下来就要调用上面说的函数了,不过我们先要为arm_fir_instance_f32这个结构体开辟一个空间

// 为FIR实例分配内存   S = (arm_fir_instance_f32 *)malloc(sizeof(arm_fir_instance_f32));   if (S == NULL)  {     // 内存分配失败,处理错误       return;   }

malloc和free这两个函数需要包含#include <stdlib.h>这个头文件,不然会报错

这行代码 S = (arm_fir_instance_f32 *)malloc(sizeof(arm_fir_instance_f32)); 是C语言中动态内存分配的一个常见用法。这行代码做了以下几件事情:

  1. sizeof(arm_fir_instance_f32):计算arm_fir_instance_f32结构体类型所占用的字节数。
  2. malloc(sizeof(arm_fir_instance_f32)):调用malloc函数,请求分配足够存储一个arm_fir_instance_f32结构体的内存空间。malloc返回的是一个指向所分配内存区域的void指针。
  3. (arm_fir_instance_f32 *):将void指针强制类型转换为arm_fir_instance_f32指针。这是因为malloc返回的是void指针,而我们需要一个指向arm_fir_instance_f32的指针来操作分配的内存。
  4. S = ...:将转换后的指针赋值给S,这样S现在就指向了一块新分配的内存,这块内存足够存储一个arm_fir_instance_f32实例。

重要的是要注意,在使用malloc分配内存之后,你有责任在不再需要这块内存时使用free函数来释放它,以避免内存泄漏。

另外,务必检查malloc的返回值是否为NULL。如果malloc无法分配所需的内存(例如,由于内存不足),它将返回NULL。在这种情况下,你应该处理这个错误情况,而不是尝试使用NULL指针,因为这会导致程序崩溃。

现在再调用那两个函数

arm_fir_init_f32(S,numTaps,pCoeffs,pState,blockSize); arm_fir_f32(S,inbuf,outbuf,blockSize);

 这样在outbuf数组中就是低通滤波后的数据了

最后我们使用free函数释放内存,避免内存泄漏

free(S);      // 释放内存  S = NULL; // 将指针设置为 NULL,以避免悬挂指针

OK,用串口打印出来看看效果

56edeb278e2c40b8aec7594fe80a0322.png

 蓝色的方波是原始信号,橙色的正弦波是经过低通滤波的信号,效果还是ok的

到此,就完成了软件滤波

 

 

 

 

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!