C语言
结构体 枚举体 头文件 预处理指令 函数指针
C语言中文网 http://c.biancheng.net/view/2031.html
代码风格
工程 缩进 注释 vscode
通信 uart iic spi
硬件协议,模拟协议
写数据,写命令,读数据
串口发送,接收,中断
非阻塞延时
int timecnt=-1;
......
{
if(something && timecnt==-1)
timecnt=1000;
if(timecnt==0)
{
timecnt=-1;
somefun();
}
}
......
timer_irq_handle()
{
if(timecnt>0)
timecnt--;
......
}
顺序执行程序思路
int process[5];
......
if(something_start && !process[1])
{
if(!process[0])
{
initfun0();
process[0]=1;
}
somefun0();
}
if(something1 && process[0] && !process[2])
{
if(!process[1])
{
initfun1();
process[0]=0;
process[1]=1;
}
somefun1();
}
if(something2 && process[1] && !process[3])
{
if(!process[2])
{
initfun2();
process[1]=0;
process[2]=1;
}
somefun2();
}
......
if(something_end && processX)
{
memset(process,0,sizeof(process));
}
滤波
软件滤波在嵌入式的数据采集和处理中有着很重要的作用。 以下几种软件滤波方法参考“匠人的百宝箱”,下文为根据自己的理解修改整理,对原作者表示感谢。
原文章来源不明,百度 十种常见的滤波方法
1.算术平均滤波
A、方法: 连续取N个采样值进行算术平均运算 N值较大时:信号平滑度较高,但灵敏度较低 N值较小时:信号平滑度较低,但灵敏度较高 N值的选取:一般流量,N=12;压力:N=4 B、优点: 适用于对一般具有随机干扰的信号进行滤波 这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动 C、缺点: 对于测量速度较慢或要求数据计算速度较快的实时控制不适用
float filter(int 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)
{
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];
}
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;
value_buf[0] = get_value();
for(int i=N-1; i>=1; i--)
{
value_buf[i] = value_buf[i-1];
sum += value_buf[i-1];
}
return (float)(sum/(N-1));
}
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;
}
|