【MM32F5270开发板试用】使用CMSIS DSP库实现自适应滤波器
本篇文章来自极术社区与灵动组织的MM32F5270开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:this is王小川
MM32F5270使用CMSIS DSP库实现自适应滤波器
首先感谢极术社区和灵动微电子给的开发板试用机会,本次开发环境为win+keil v5.37+cmsis5.7。 先开箱看看开发板的颜值,可以看到开发板的外设还是很丰富的。
一、mindsdk使用
首先登录mindsdk,网址为https://mindsdk.mindmotion.co…,首次登录需要先注册。
接着选择对应的工具链和开发板。
接着下载生成的工程压缩包。
解压后可以看到文件夹内部的结构,大致包括demo例程,hal库,外设应用,启动文件等。
二、cmsis dsp库使用
Common Microcontroller Software Interface Standard (CMSIS) 是一个独立于供应商的抽象层,适用于基于 Arm Cortex 处理器的微控制器。其下包括许多组件,dsp包就是其中一个,包括常规的数字信号处理函数,支持dsp硬件。
由于最新的cmsis进行了改版,新版本中的dsp库没有预编译的lib,使用起来暂时比较麻烦,这次使用v5.7版本进行演示。在keil中首先打开pack install 安装5.7版本的cmsis。
在工程管理中加入以下文件,包括Lib中的arm_ARMv8MMLldfsp_math.lib和Include中包括arm_math.h所有文件,我的路径如下。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBUEk8Zq-1666318589844)(https://pic3.zhimg.com/80/v2-5187c802f9ce63f73e262887f833dfa6_1440w.webp)]
三、LMS 最小均方自适应滤波器实现
LMS 最小均方自适应滤波器能够"学习"未知的传输特性。 LMS 滤波器使用梯度下降方法,根据瞬时错误信号更新滤波系数。自适应滤波器常用于通信系统、均衡器和降噪。
自适应滤波器的主要通过下面两个函数实现,支持逐点实时滤波。
函数 arm_lms_norm_init_f32:此函数用于自适应滤波器初始化。
void arm_lms_norm_init_f32(arm_lms_norm_instance_f32 * S,uint16_t numTaps,float32_t * pCoeffs,float32_t * pState,float32_t mu,uint32_t blockSize);
函数 arm_lms_norm_f32:此函数用于自适应滤波器实时滤波。
void arm_lms_norm_f32(arm_lms_norm_instance_f32 * S,const float32_t * pSrc,float32_t * pRef,float32_t * pOut,float32_t * pErr,uint32_t blockSize);
我们直接使用plus-f5270_mdk\demo_apps\basic\hello_world的例程进行开发,main.c更改如下:
#include "board_init.h"#include "arm_math.h"#include "arm_const_structs.h"#define TEST_LENGTH_SAMPLES 2048 #define BLOCK_SIZE 2048 #define NUM_TAPS 20 uint32_t blockSize = BLOCK_SIZE; uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE; static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]={0}; static float32_t testInput_f32_REF[TEST_LENGTH_SAMPLES]={0}; static float32_t test_f32_ERR[TEST_LENGTH_SAMPLES]={0}; static float32_t testOutput[TEST_LENGTH_SAMPLES]={0};static float32_t lmsStateF32[BLOCK_SIZE + NUM_TAPS - 1]={0}; static float32_t lmsCoeffs32[NUM_TAPS] = {0}; float32_t testInput50Hz_200Hz;float32_t testOutput1;void arm_lms_f32_test1(void){ uint32_t i; float32_t *inputF32, *outputF32, *inputREF, *outputERR; arm_lms_norm_instance_f32 lmsS={0}; for(i=0; i<TEST_LENGTH_SAMPLES; i++) { testInput_f32_50Hz_200Hz[i] = arm_sin_f32(2*3.1415926f*50*i/1000) + arm_sin_f32(2*3.1415926f*200*i/1000); testInput_f32_REF[i] = arm_sin_f32(2*3.1415926f*50*i/1000); } memset(lmsCoeffs32,0,sizeof(lmsCoeffs32)); memset(lmsStateF32,0,sizeof(lmsStateF32)); inputF32 = (float32_t *)&testInput_f32_50Hz_200Hz[0]; outputF32 = (float32_t *)&testOutput[0]; inputREF = (float32_t *)&testInput_f32_REF[0]; outputERR = (float32_t *)&test_f32_ERR[0]; arm_lms_norm_init_f32 (&lmsS, NUM_TAPS, (float32_t *)&lmsCoeffs32[0], &lmsStateF32[0],0.1, blockSize); /* ʵÏÖLMS×ÔÊÊÓ¦Â˲¨£¬ÕâÀïÿ´Î´¦Àí1¸öµã */ for(i=0; i < numBlocks; i++) { arm_lms_norm_f32(&lmsS, /* LMS½á¹¹Ìå */ inputF32 + (i * blockSize), inputREF + (i * blockSize), outputF32 + (i * blockSize), outputERR + (i * blockSize), blockSize); } printf("y1=["); for(i=0; i<TEST_LENGTH_SAMPLES; i++) { printf("%f ", testInput_f32_50Hz_200Hz[i]); testInput50Hz_200Hz = testInput_f32_50Hz_200Hz[i]; } printf("]\r\n"); printf("=========================================\r\n"); printf("y2=["); for(i=0; i<TEST_LENGTH_SAMPLES; i++) { printf("%f ", outputF32[i]); } printf("]\r\n"); printf("=========================================\r\n"); printf("y3=["); for(i=0; i<TEST_LENGTH_SAMPLES; i++) { printf("%f ", test_f32_ERR[i]); } printf("]\r\n"); printf("=========================================\r\n"); }int main(void){ uint8_t ch; BOARD_Init(); printf("hello, world!!\r\n"); while (1) { getchar(); arm_lms_f32_test1(); }}
这里输入的原始波形 200Hz + 50Hz 正弦波,滤除 200Hz 正弦波,通过串口打印数据,使用matlab画出波形。