一位
整型变量a
unsigned int a;
a | = (0x1<<3); //设置a的bit 3 置1
a & = ~ (0x1<<3); //设置a的bit 3 置0
a = (b & (1 << 1)) >> 1; //取b的 bit 1 数据值
a = (b & (1 << 3)) >> 3; //取b的 bit 3 数据值
if((readbuffer & 0x08) == 0x00) //Bit[3] 是否为 1
字符
求余、乘、除 (2,4,8,16.......)
a=a&7; // 求余运算 相当于 a=a%8;
a=a<<2; // 乘4 a=a*4;
a=(a<<3)+a // 乘9 a=a*9
b=b>>2; // 除4 b=b/4;
移位
uint8_t a,b;
uint16_t c;
c = ( (uint16_t) a << 8 ) | b ; //两个8位字符变为一个16位
函数封装:
赋值
memset()
是计算机中C/C++语言初始化函数。
作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 。
memset()函数原型是extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.
memcpy()
指的是C和C++使用的内存拷贝函数,
函数原型为void *memcpy(void *destin, void *source, unsigned n);
函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中。
函数原型
void *memcpy(void *destin, void *source, unsigned n);
参数
destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
source-- 指向要复制的数据源,类型强制转换为 void* 指针。
n-- 要被复制的字节数。
返回值
该函数返回一个指向目标存储区destin的指针。
功能
从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。
memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。
需要注意的是:
destin指针要分配足够的空间,也即大于等于 n 字节的空间。如果没有分配空间,会出现断错误。
destin和 source所指的内存空间不能重叠(如果发生了重叠,使用 memmove()会更加安全)。
所需头文件
C语言:#include<string.h>
C++:#include<cstring>
数据过滤:
中位值滤波
方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值
优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果
缺点:对流量,速度等快速变化的参数不宜
//中值滤波算法
int middleValueFilter(int N)
{
int value_buf[N];
int i,j,k,temp;
for( i = 0; i < N; ++i)
{
value_buf[i] = HAL_ADC_GetValue(&hadc1);
}
for(j = 0 ; j < N-1; ++j)
{
for(k = 0; k < N-j-1; ++k)
{
//从小到大排序,冒泡法排序
if(value_buf[k] > value_buf[k+1])
{
temp = value_buf[k];
value_buf[k] = value_buf[k+1];
value_buf[k+1] = temp;
}
}
}
return value_buf[(N-1)/2];
}
中值滤波对消除异常值和平稳化AD采样都具有十分有效的结果。
功能代码
PID
PID控制应该算是应用非常广泛的控制算法了。小到控制一个元件的温度,大到控制四轴飞行器的飞行姿态和飞行速度等等,都可以使用PID控制。这里我们从原理上来理解PID控制。PID(proportion integration differentiation)其实就是指比例,积分,微分控制。PID的公式和原理推导我就不多赘述了,大伙有兴趣的话可以去看看其他大佬们写的原理,这里只简单的说说给个参数的作用和如何调节三个参数!!!(重点)
P(比例系数):成比例的反应控制系统中输入与输出的偏差信号,只要偏差一旦产生,就立刻产生控制的作用来减少产生的误差。
I(Ti积分系数):在比例控制环节产生了静态误差,在积分环节中,主要作用就是消除静态误差来提高系统的稳定性。
D(Td微分系数):微分环节是反应系统偏差的一个变化趋势,可以在误差来临前提前引入一个有效的修正信号。
而常用的PID又分位置式PID和增量式PID:
位置式PID是一种非递推式算法,通过不断累加,可以直接控制执行机构(平衡小车),u(k)的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构中不带积分不见的对象中可以很好的应用。
增量式不需要不断累加,控制的增量△u(k)也只与最近3次的采样值有关。在速度闭环控制中有很好的实时性。
在进行PID控制时,位置式PID需要又积分限幅和输出限幅,而增量式PID只需要输出限幅。
重要的是PID参数的整定
这里我给大家推荐一个我常用的方法:一般调节法!!
一般调节法:在输出不振荡时,增大比例增益P。在输出不振荡时,减少积分常数Ti。
在输出不震荡时,增大微分时间常数Td。
1:确认比例增益P时,首先去掉PID中的积分Ti和微分Td,一般让Ti=0和Td=0,让其PID变为纯比例P调节。输入设定为系统允许的最大值的60%~70%,由0逐渐增大增益P,直到系统出现振荡;然后再反过来,逐渐将p减小,直至振荡消失,记录此时的比例增益P,设定为PID的比例增益P为当前的60%~70%,。
2:确定积分时间常数Ti:设定一个较大的积分时间常数Ti的初值,然后逐渐减小Ti,直至系统出现振荡,在翻过来逐渐加大Ti,直至系统振荡小时。记录此时的Ti,设定PID积分时间常数Ti为当前的150%~180%。
3:确认微分时间常数Td:积分时间常数Td一般不用设定,若要设定则与P和Ti方式相同,取不震荡的30%。
|