文章目录
前言
长风破浪会有时!直挂云帆济沧海!
一、实现Stm32中Dsp库的低通滤波实现(FIR)
在做心率血氧项目中直接采集到的信号十分毛刺(效果图1-1如下),然而频率在5Hz附近。决定使用低通滤波试试!!!
图片1-1(血氧初始信号)
实现步骤
1.要实现滤波,需要有参数实现,参数可以从Matlab中获取!!!
a.在命令窗口输入 filterDesigner(会弹出FIR设计工具)
b.函数原型需要的参数
c.实现步骤(matlab参数获取 )
d.实现步骤(matlab生成参数 )
以上步骤完成后…点击设计滤波器(截至频率选取50hz左右效果明显)–>点击目标–>选择导出为(我选的是单精度浮点数)–>点击生成 -->保存文件路径
2.实现滤波在stm32上的滤波器设计
a.直接上代码
#include "myFIR.h"
#include "arm_math.h"
#include "stdio.h"
uint32_t blockSize = BLOCK_SIZE;
uint32_t numBlocks = TEST_LENGTH_SAMPLES / BLOCK_SIZE; /* 需要调用arm_fir_f32的次数 */
float32_t testInput_f32_500Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
float32_t testOutput[TEST_LENGTH_SAMPLES]; /* 滤波后的输出 */
float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1]; /* 状态缓存,大小numTaps + blockSize - 1*/
/* 低通滤波器系数 通过fadtool获取*/
const float32_t firCoeffs32LP[29] =
{
-0.001647398574,-0.0008258497692, 0.001227202825, 0.004726920277, 0.007672414649,
0.005805777851,-0.004334676079, -0.02075286396, -0.03350708634, -0.02770185284,
0.008254308254, 0.0736207068, 0.1517520398, 0.2155939639, 0.2402327806,
0.2155939639, 0.1517520398, 0.0736207068, 0.008254308254, -0.02770185284,
-0.03350708634, -0.02075286396,-0.004334676079, 0.005805777851, 0.007672414649,
0.004726920277, 0.001227202825,-0.0008258497692,-0.001647398574
};
void arm_fir_f32_lp(void)
{
uint32_t i;
arm_fir_instance_f32 S;
float32_t* inputF32, *outputF32;
/* 初始化输入输出缓存指针 */
inputF32 = &(testInput_f32_500Hz[0]);
outputF32 = &(testOutput[0]);
/* 初始化结构体S */
arm_fir_init_f32(&S,
NUM_TAPS,
(float32_t*)&firCoeffs32LP[0],
&firStateF32[0],
blockSize);
/* 实现FIR滤波,这里每次处理1个点 */
for(i = 0; i < numBlocks; i++)
{
arm_fir_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize), blockSize);
}
}
#ifndef _MYFIR_H_
#define _MYFIR_H_
#include "main.h"
#include "arm_math.h"
#define TEST_LENGTH_SAMPLES 1024 /* 采样点数 */
#define BLOCK_SIZE 1 /* 调用一次arm_fir_f32处理的采样点个数 */
#define NUM_TAPS 29 /* 滤波器系数个数 */
extern float32_t testInput_f32_500Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
extern float32_t testOutput[TEST_LENGTH_SAMPLES]; /* 滤波后的输出 */
extern float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1]; /* 状态缓存,大小numTaps + blockSize - 1*/
void arm_fir_f32_lp(void);
#endif
b.上效果图可以看出毛刺减少了。截至频率选择更小的效果会更好!但是注意不要影响到原信号!!!
原信号
150hz
50hz
实现低通,高通,带阻滤波算法也和以上类似!但注意参数的更改!!!
完结撒花!!!(没有)
二、实现Stm32中Dsp库的中值滤波实现
以上的低通滤波对于该信号的平滑好像不是那么明显,效果不是很显著!!
那我们就拿出本节讲的中值滤波
来试试
1.什么是中值滤波(适用于噪声和脉冲的过滤)
2.在stm32上实现中值滤波算法(支持数据块和实时数据滤波)
注意:
3.实现代码
#define MidFilter_LENGTH_SAMPLES 2048 /* 采样点数 */
#define MidFilterOrder 16 /* 滤波阶数 */
#define ZeroSize MidFilterOrder
float32_t DstDate[MidFilter_LENGTH_SAMPLES]; /* 滤波后数据 */
float32_t SortData[MidFilterOrder]; /* 滤波排序 */
float32_t TempDate[ZeroSize + MidFilter_LENGTH_SAMPLES +ZeroSize] = {0}; /* 滤波阶段用到的临时变量 */
/*
*********************************************************************************************************
* 函 数 名: MidFilterBlock
* 功能说明: 中值滤波器,对一段数据的中值滤波。
* 形 参: pSrc 源数据地址。
* pDst 滤波后数据地址。
* blockSize 数据个数,至少为2。
* order 至少2阶。
* 返 回 值: 无
*********************************************************************************************************
*/
void MidFilterBlock(float32_t *pSrc, float32_t *pDst, uint32_t blockSize, uint32_t order)
{
arm_sort_instance_f32 S;
uint32_t N, i;
S.dir = ARM_SORT_ASCENDING;
S.alg = ARM_SORT_QUICK;
N = order / 2;
/* 数据幅值给临时缓冲 */
for(i =0; i < blockSize; i++)
{
TempDate[i + ZeroSize] = pSrc[i];
}
/* 求每个数据点的中值 */
for(i =0; i < blockSize; i++)
{
/* 排序 */
arm_sort_f32(&S, &TempDate[i + ZeroSize - N], &SortData[0], order);
/* 奇数 */
if(N)
{
pDst[i] = SortData[N];
}
/* 偶数 */
else
{
pDst[i] = (SortData[N] + SortData[N-1])/2;
}
}
}
/*
*********************************************************************************************************
* 函 数 名: MidFilterRT
* 功能说明: 中值滤波器,用于逐个数据实时滤波。
* 形 参: pSrc 源数据地址。
* pDst 滤波后数据地址。
* ucFlag 1表示首次滤波,后面继续滤波,需将其设置为0。
* order 至少2阶。
* 返 回 值: 无
*********************************************************************************************************
*/
void MidFilterRT(float32_t *pSrc, float32_t *pDst, uint8_t ucFlag, uint32_t order)
{
arm_sort_instance_f32 S;
uint32_t N, i;
static uint32_t CountFlag = 0;
S.dir = ARM_SORT_ASCENDING;
S.alg = ARM_SORT_QUICK;
N = order / 2;
/* 首次滤波先清零 */
if(ucFlag == 1)
{
CountFlag = 0;
}
/* 填充数据 */
if(CountFlag < order)
{
TempDate[CountFlag] = pSrc[0];
CountFlag++;
}
else
{
for(i =0; i < order - 1; i++)
{
TempDate[i] = TempDate[1 + i];
}
TempDate[order - 1] = pSrc[0];
}
/* 排序 */
arm_sort_f32(&S, &TempDate[0], &SortData[0], order);
/* 奇数 */
if(N)
{
pDst[0] = SortData[N];
}
/* 偶数 */
else
{
pDst[0] = (SortData[N] + SortData[N-1])/2;
}
}