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

1-17 修改了顺序执行程序和滑动平均滤波的错误

C语言

结构体
枚举体
头文件
预处理指令
函数指针

C语言中文网 http://c.biancheng.net/view/2031.html

代码风格

工程
缩进
注释
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<N;i++)//此处为连续采样,或者改为定时采样
	{
		value += get_value();
	}
	return value/N;
}

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 = 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 = 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 = 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<N;count++)//采集数据
   {
      value_buf[count] = get_value();
      delay();
   }

   for (int j=0;j<N-1;j++)//冒泡排序
   {
      for (int i=0;i<N-j;i++)
      {
         if(value_buf[i] > 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<N-1;i++)
	{
		sum += value_buf[i]//遍历求和
	}
   	return (float)(sum/N);
}

6.互补滤波

A、方法:
对通过两种途径得到的采集值进行加权融合
本次滤波结果 = a * 方法A的采集值 + (1-a) * 方法B的采集值
B、优点
融合两种方案的结果,取长补短
C、缺点:
灵敏度低,不适应频率较高的数据

float  filter(float a)
{
	float value_a, value_b, value;

	value_a = get_a();
	value_b = get_b();
	value = a * (value_a -value_b) + value_b;
	return value;
}

你可能感兴趣的:(C语言,c语言,嵌入式)