历史上的今天
返回首页

历史上的今天

今天是:2025年08月01日(星期五)

正在发生

2019年08月01日 | STM32实战七 数字滤波

2019-08-01 来源:eefocus

数字滤波是数据处理是常用、灵活、有效的方法。前面的按键程序已经用到了滤波,属于开关量滤波,这里要讨论的是模拟量滤波程序,包括最常用的两种方法,中值滤波和平均值滤波。


中值滤波的原理是,每次取最近几个数的中间值作为输出数据,每个波形的最高和最低几个数被滤掉,优点是基本保留原有数据,能有效抑制大幅值低频尖峰干扰,俗称椒盐噪声。


平均值滤波,就是对最近一些数求平均,是最常用最简单的方法,对高频低幅值随机噪声有效,缺点是会损失原始数据中的高频分量,对高幅值干扰会扩大影响。下面的程序中应用了移位平均算法,效率高,且不受求平均的数据数目大小的影响。两种滤波方式都有一定延时。


AverageFilter.h


#ifndef __AVERAGEFILTER__

#define __AVERAGEFILTER__

 

extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段

#pragma diag_remark 368 //消除 warning:  #368-D: class "" defines no constructor to initialize the following:

 

#include "stm32f10x.h"

 

#pragma diag_default 368 // 恢复368号警告

}

 

#define AF_MAXWINDOW 150 // 最大窗宽150

 

class AverageFilter

{

// Construction

public:

AverageFilter( s32 ini, u16 nNum );

 

// Properties

public:

u16 m_number; // 指定平均的个数,最多150

u16 m_seek; // 游标

s32 m_summation; // 指定数组的总和

s32 m_input[AF_MAXWINDOW]; // 数据缓存

 

private:

 

// Methods

public:

s32 filter( s32 vi ); // 滤波算法

// Overwrite

public:

};

 

#endif

AverageFilter.cpp


/**

  ******************************************************************************

  * @file AverageFilter.cpp

  * @author Mr. Hu

  * @version V1.0.0 STM32F103VET6

  * @date 06/06/2019

  * @brief 均值滤波

  ******************************************************************************

  * @remarks

  * 采用移位平均法,大大提高效率,不受数据数量的影响

  */ 

 

/* Includes ------------------------------------------------------------------*/

extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段

#pragma diag_remark 368 //消除 warning:  #368-D: class "" defines no constructor to initialize the following:

 

#pragma diag_default 368 // 恢复368号警告

}

 

#include "AverageFilter.h"

 

/**

  * @date 06/06/2019

  * @brief  均值滤波

  * @param ini 初始值,避免前几个输出数偏差太大

  * @param nNum 滤波数量,最大150,越大效果越好,但延时较多

  * @retval None

*/

AverageFilter::AverageFilter( s32 ini, u16 nNum )

: m_number(nNum)

, m_seek(0)

, m_summation(0)

{

if( m_number > AF_MAXWINDOW ) // 控制在数组范围内

m_number = AF_MAXWINDOW;

// 初始化数组

for( int i = 0; i < AF_MAXWINDOW; i++ )

{

m_input[i] = ini;

}

// 初始化总和

m_summation = ini * m_number;

}

 

/**

  * @date 06/06/2019

  * @brief  滤波算法,采用移位算法,减去第一个,加上最后一个。

  * @param vi 输入数据

  * @retval 滤波后输出数据

*/

s32 AverageFilter::filter( s32 vi )

{

m_summation += ( vi - m_input[m_seek] ); // 总和中减去最早的数,加上新数

// 用循环方法记录输入数据

assert_param(m_number <= AF_MAXWINDOW);

m_input[m_seek] = vi;

if (++m_seek >= m_number)

m_seek = 0;

// 返回平均值

return m_summation / m_number;

}

MedianFilter.h


#ifndef __MEDIANFILTER__

#define __MEDIANFILTER__

 

extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段

#pragma diag_remark 368 //消除 warning:  #368-D: class "" defines no constructor to initialize the following:

 

#include "stm32f10x.h"

 

#pragma diag_default 368 // 恢复368号警告

}

 

#define DF_MAXWINDOW 21 // 最大窗宽,奇数,太大了反而不好

 

class MedianFilter

{

// Construction

public:

MedianFilter( s32 ini, u16 nNum );

 

// Properties

public:

u16 m_dfMedian; // 半窗宽,最大10

u16 m_seek; // 输入数据指针

s32 m_input[DF_MAXWINDOW]; // 输入数据,循环使用,不用移位,提高效率

s32 m_sort[DF_MAXWINDOW]; // 排序数据,最近输入的数据排序,取中间值输出

 

private:

 

// Methods

public:

s32 filter( s32 vi ); // 滤波算法

// Overwrite

public:

};

 

#endif

MedianFilter.cpp


/**

  ******************************************************************************

  * @file MedianFilter.cpp

  * @author Mr. Hu

  * @version V1.0.0 STM32F103VET6

  * @date 06/05/2019

  * @brief 中值滤波

  ******************************************************************************

  * @remarks

  * 中值滤波的原理是,每次取最近几个数的中间值作为输出数据,每个波形的最高和最低

  * 几个数被滤掉,优点是基本保留原有数据,相当于去掉几个最高数,去掉几个最低数,能有

  * 效抑制大幅值低频尖峰干扰,俗称椒盐噪声。

  */ 

 

/* Includes ------------------------------------------------------------------*/

extern "C" { // 兼容C,按C语言编译,Keil5中的包含文件已经加入了C++兼容,不用再加这一段

#pragma diag_remark 368 //消除 warning:  #368-D: class "" defines no constructor to initialize the following:

 

#pragma diag_default 368 // 恢复368号警告

}

 

#include "MedianFilter.h"

 

/**

  * @date 06/05/2019

  * @brief  中值滤波

  * @param ini 初始值,前几个输出数都是这个值

  * @param nNum 滤波数,最大10,越大效果越好,但延时较多

  * @retval None

*/

MedianFilter::MedianFilter( s32 ini, u16 nNum )

: m_dfMedian(nNum)

, m_seek(0)

{

if( m_dfMedian > (DF_MAXWINDOW - 1) / 2 ) // 中值限制在数组范围内

m_dfMedian = (DF_MAXWINDOW - 1) / 2;

// 初始化两个数组

for( int i = 0; i < DF_MAXWINDOW; i++ )

{

m_input[i] = ini;

m_sort[i] = ini;

}

}

 

/**

  * @date 06/05/2019

  * @brief  滤波算法

  * @param vi 输入数据

  * @retval 滤波后输出数据

*/

s32 MedianFilter::filter( s32 vi )

{

u8 w1 = m_dfMedian * 2; // 窗宽-1

assert_param(w1 < DF_MAXWINDOW);

// 计算将要移除的值在排序数组中的位置

u8 j = 0;

for (; j <= w1 && m_input[m_seek] != m_sort[j]; j++);

 

// 移除最早的数据并把新数据插入到适当的位置

// 如果新数据在较小半段,数据后移,否则数据前移,实现排序

// 只处理大于和小于情况,等于时不动

if (vi < m_input[m_seek])

{ // 向前移

while (j > 0 && vi < m_sort[j-1])

{

j--;

m_sort[j + 1] = m_sort[j];

}

}

else if (vi > m_input[m_seek])

{ // 向后移

while (j < w1 && vi > m_sort[j+1])

{

j++;

m_sort[j - 1] = m_sort[j];

}

}

 

// 加入新值

assert_param(j >= 0 && j < w);

m_sort[j] = vi;

 

// 用循环方法记录输入数据,高效

m_input[m_seek] = vi;

if (++m_seek > w1)

m_seek = 0;

 

// 返回中间值

return m_sort[m_dfMedian];

}

推荐阅读

史海拾趣

Empro Technology Corp公司的发展小趣事

为了进一步提升市场竞争力,Empro Technology Corp开始实施国际化战略,积极开拓海外市场。公司设立了多个海外分支机构,与当地企业建立了合作关系,共同开拓市场。同时,公司还积极参加国际电子展等交流活动,与国际同行进行深入交流与合作。

请注意,以上故事均为虚构内容,不代表Empro Technology Corp公司的实际发展情况。如需了解该公司的真实信息,请查阅相关公开资料或联系公司官方渠道。

Arctic Silicon Devices公司的发展小趣事

面对全球电子市场的竞争压力,Arctic Silicon Devices制定了国际化发展战略。公司积极拓展海外市场,通过设立分支机构、与当地企业合作等方式,将产品和技术推向全球。同时,公司还加大了对国际人才的引进力度,提升了自身的研发实力和市场竞争力。这一战略的成功实施,使Arctic Silicon Devices在全球电子行业中占据了重要地位。

FTDI [Future Technology Devices International Ltd.]公司的发展小趣事

随着市场需求的变化,FTDI并未满足于初期的成就,而是积极拓展产品线。他们推出了如MM232R和USB-COM232-PLUS1等接口产品,这些产品在连接性和兼容性上展现了公司强大的技术实力和创新精神。同时,FTDI还涉足USB和其他通信协议的转换领域,满足了多样化的市场需求,进一步巩固了其在电子行业中的地位。

EPIGAP公司的发展小趣事

EPIGAP公司非常重视创新文化的建设。公司鼓励员工提出新的想法和创意,并为员工提供充分的支持和资源。此外,EPIGAP还积极引进和培养人才,建立了一支高素质、专业化的研发团队。这支团队在公司的发展历程中发挥了至关重要的作用,不断推动公司产品的升级换代和技术创新。

启珑(CHIPLON)公司的发展小趣事

EPIGAP公司的创始人李先生在半导体领域拥有深厚的技术背景。在公司初创时期,他带领研发团队成功研发出一种新型的高性能芯片,该芯片在功耗和性能上均达到了行业领先水平。这一技术突破使得EPIGAP公司在激烈的市场竞争中脱颖而出,迅速获得了众多客户的青睐。凭借这一产品,EPIGAP成功打开了市场,为后续的发展奠定了坚实的基础。

Belden Wire and Cable公司的发展小趣事

1902年,Joseph C. Belden在美国伊利诺伊州芝加哥创立了Belden公司。在创立初期,公司主要生产电线和电缆产品,并逐渐在行业内崭露头角。1905年,经过大量的实验和研究,Belden公司成功研发出“Beldenamel”绝缘材料,这种灵活的搪瓷绝缘材料极大地提升了线缆的性能和可靠性,为公司的早期发展奠定了坚实的基础。

问答坊 | AI 解惑

Xilinx通过ISO/TS 16949汽车行业标准认证

赛灵思公司(Xilinx)今天宣布获得汽车行业质量标准ISO/TS 16949认证。ISO/TS 16949标准使赛灵思公司能够为整个汽车供应链提供质量和可靠性最高的电子元器件。赛灵思公司在此之前已经满足了其它世界级质量标准的严格要求,包括ISO 9 ...…

查看全部问答>

单片机C51典型应用设计代码

所有代码均在Keil C51 7.0以上版本编译通过。只需要能够运行Windows 98 以上版本的操作系统、并能够安装Keil C51 7.0以上版本的软件即可。…

查看全部问答>

搞通信的:硬件和软件哪个发展前景更大?

请大家谈谈自己相关领域的状况。…

查看全部问答>

请教!请教!

请问一下,三星笔记本管理员密码忘记了,开不了机怎么办?…

查看全部问答>

那里能找到高通qsd8x50片子的资料

我们用到高通这样一个片子,可是没有芯片资料,据高通说还没有发布,不知各位大爷有没有找得到的。 给个网址、 …

查看全部问答>

关于 飞思卡尔(freescale)i.MX51

1、阅读了一下i.MX51  ARM Cortex A8的datasheet,对于IOMUX还是不清楚, 2、还有一些缩写如:PAD、ALTn(n=0, 1, 2...)等等很多,配置一个引脚做很多工作。 3、感觉freescale的比较难理解,以前做三星的一看寄存器就知道是干什么的。 ...…

查看全部问答>

定制系统时加入了微软拼音中文输入法

定制系统时加入了微软拼音中文输入法,结果运行时,只出声母,不出韵母,打不出中文来,请问有人遇到过没,怎么解决? 1、设置了环境变量SET LOCALE=0804; 2.在platform settings中选择了中文(中国),英文(美国),默认语言设为中文; 3.在P ...…

查看全部问答>

关于驱动的调试release和debug

不知道大家对于调试的看法怎么样。一般你在调试的时候是release还是debug的。我每次都基本上时release的。因为是经理教的。只有在调试一些流层性,我们不知道架构的东西我才用debug。反正基本上不用。。用过几次也很懊恼。。点个屏漫天的打印信息。 ...…

查看全部问答>

求助:如何测量白石灰料位?

求助:料仓里的白石灰粉,当放料后,形成如图(四周高,中间低的料位情况)。 这时候测量仪表无法准确测了料位高度。 求助解决方法:如何能让料仓里的料位处于相对水平状态;或者采用什么样的仪表才能够做到精确测量?…

查看全部问答>