C语言|C语言程序思路与几种常用的滤波

1-17 修改了顺序执行程序和滑动平均滤波的错误
C语言 结构体
枚举体
头文件
预处理指令
函数指针
C语言中文网 http://c.biancheng.net/view/2031.html
代码风格 【C语言|C语言程序思路与几种常用的滤波】工程
缩进
注释
vscode
通信 uart iic spi 硬件协议,模拟协议
写数据,写命令,读数据
串口发送,接收,中断
非阻塞延时

int timecnt=-1; //当前计数值(倒计时) ...... { if(something && timecnt==-1) { timecnt=1000; //1000ms倒计时 } if(timecnt==0)//倒计时结束 { timecnt=-1; //计时器复位 somefun(); //倒计时结束后执行的程序 } } ...... timer_irq_handle()//定时器中断函数,周期一般1ms { if(timecnt>0) timecnt--; ...... }

顺序执行程序思路
int process[5]; //5步 ......if(something_start && !process[1])//起始步 { if(!process[0]) { initfun0(); //初始化程序,可省略 process[0]=1; //置位本步标志位 } somefun0(); //持续执行程序 }if(something1 && process[0] && !process[2])//步1 { if(!process[1]) { initfun1(); //初始化程序 process[1]=1; //置位本步标志位 } somefun1(); //持续执行程序 } if(something2 && process[1] && !process[3])//步2 { if(!process[2]) { initfun2(); //初始化程序 process[2]=1; } somefun2(); //持续执行程序 } ......if(something_end && process[x])//结束步,process[x]是最后一步 { memset(process,0,sizeof(process)); //清零所有标志位 }

滤波 软件滤波在嵌入式的数据采集和处理中有着很重要的作用。
以下几种软件滤波方法参考“匠人的百宝箱”,下文为根据自己的理解修改整理,对原作者表示感谢。
原文章来源不明,百度 十种常见的滤波方法
1.算术平均滤波 A、方法:
连续取N个采样值进行算术平均运算
N值较大时:信号平滑度较高,但灵敏度较低
N值较小时:信号平滑度较低,但灵敏度较高
N值的选取:一般流量,N=12;压力:N=4
B、优点:
适用于对一般具有随机干扰的信号进行滤波
这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动
C、缺点:
对于测量速度较慢或要求数据计算速度较快的实时控制不适用
float filter(int N)//N为采样次数 { float value; for(int i=0; i

2.限幅滤波 A、方法:
根据经验判断,确定两次采样允许的最大偏差值(设为A),
每次检测到新值时判断:
如果本次值与上次值之差<=A,则本次值有效;
如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值
B、优点:
能有效克服因偶然因素引起的脉冲干扰
C、缺点
无法抑制周期性的干扰
平滑度差
#define ABS(x) (((x) > 0) ? (x) : (-(x)))//绝对值宏函数 float filter(float A) //A为允许偏差值 { static float new_value,last_value; //静态变量或全局变量 last_value = https://www.it610.com/article/new_value; new_value = get_value(); if ( ABS(new_value - last_value)> A ) return last_value; return new_value; }

另外,还有一种限幅滤波比较常用,如果超过上(下)限位,则本次值 = 上(下)限位
void filter(float *value, float min, float max) { if(*value>max) *value = https://www.it610.com/article/max; else if(*value < min) *value = min; } //以下为调用时 value = get_value(); filter(&value,min,max);

限幅滤波一般搭配其他滤波来用,如限幅平均滤波
3.一阶滞后滤波(低通) A、方法:
取a=0~1
本次滤波结果= a*本次采样值+(1-a)*上次滤波结果
B、优点:
对周期性干扰具有良好的抑制作用
适用于波动频率较高的场合
C、缺点:
相位滞后,灵敏度低
滞后程度取决于a值大小
不能消除滤波频率高于采样频率的1/2的干扰信号
float filter( float a) { static float new_value,last_value; //静态变量或全局变量 last_value = https://www.it610.com/article/new_value; new_value = get_value(); new_value = a * (new_value - last_value) + last_value; return new_value; }

4.中位值滤波 A、方法:
连续采样N次(N取奇数)
把N次采样值按大小排列
取中间值为本次有效值
B、优点:
能有效克服因偶然因素引起的波动干扰
对温度、液位的变化缓慢的被测参数有良好的滤波效果
C、缺点:
对流量、速度等快速变化的参数不宜
#define N 100 float value_buf[N]; int filter() { float sum=0,temp; for(int count=0; count value_buf[i+1] ) { temp = value_buf[i]; value_buf[i] = value_buf[i+1]; value_buf[i+1] = temp; } } } return value_buf[(N-1)/2]; //中位值平均滤波 //for(int count = 1; count < N-1; count++) //sum += value[count]; //return (int)(sum/(N-2)); }

5.滑动平均滤波 A、方法:
把连续取N个采样值看成一个队列
队列的长度固定为N
每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)
把队列中的N个数据进行算术平均运算,就可获得新的滤波结果
N值的选取:流量,N=12;压力:N=4;液面,N=412;温度,N=14
B、优点:
对周期性干扰有良好的抑制作用,平滑度高
适用于高频振荡的系统
C、缺点:
灵敏度低
对偶然出现的脉冲性干扰的抑制作用较差
不易消除由于脉冲干扰所引起的采样值偏差
不适用于脉冲干扰比较严重的场合
#define N 12 int value_buf[N]; float filter() { float sum=0; for(int i=N-1; i>=1; i--) { value_buf[i] = value_buf[i-1]; //数据后移,高位被替换掉 } value_buf[0] = get_value(); //新值给第0个元素 for(int i=0; i

6.互补滤波 A、方法:
对通过两种途径得到的采集值进行加权融合
本次滤波结果 = a * 方法A的采集值 + (1-a) * 方法B的采集值
B、优点
融合两种方案的结果,取长补短
C、缺点:
灵敏度低,不适应频率较高的数据
floatfilter(float a) { float value_a, value_b, value; value_a = get_a(); value_b = get_b(); value = https://www.it610.com/article/a * (value_a -value_b) + value_b; return value; }

    推荐阅读