1、电流检测AD采样值处理的高效方法
在电机控制软件的编写过程中,经常要处理由AD采样回来的电流值。由于电流有正有负,电流传感器输出地电压也是以0为中点,而一般AD的输入只能为正电压,所以电流传感器出来的电压量需要通过加减运算电路加上一个偏移值再送入AD,以保证进入AD的值恒为正。
这里AD以TI的2812的片内AD为例,其输入范围是0~3V,电流传感器以LEM的LA25NP为例,量程25A,通常采用的电路是将LEM传感器的输出经过一个100欧的电阻接到地,获得一个以0为中点的电压信号,然后在送入比例运算电路,在比例运算电路的另一个输入端加入1.5V的偏移量,这样在满量程范围内使输入AD的电压信号始终保持在0~3V之内。电流为0的时候送入AD的电压是1.5V
在程序中进行电流运算时,一般要把AD采样结果取回来,然后再减去1.5V的偏移值,这样的到一个有符号数,然后再进行运算。
今天在阅读TI提供的电机驱动库代码时,发现里边使用了一种高效的处理方法,代码很简单,是这样的:
DatQ15 = AdcRegs.ADCRESULT0^0x8000;
2812的AD是12位的,AD采样结果存储在高12位。因此当AD满量程时,ADCRESULT0中的值是0xfff0。
这段代码仅仅通过一个按位异或运算就将AD的值减去了1.5V的偏移,并变成了有符号数。
至于具体为什么,举例说明,当电压为3V时,采样值是0xfff0,异或运算后高位的1变成了0,其余位不变,其结果是7ff0,如果将最高位看做符号位,那么有效位是11位。
2、AD转换N次采样去最大最小求平均算法
- #include "STC15.H"
- #include "delay.h"
- #include "STCAD.H"
- #include "IO.C"
void AD_Init() //AD初始化
{
P1M1=0xF0; //设置相应的I/O口为高阻 P1.4-P1.5-P1.6-P1.7
P1M0=0x00;
ADC_RES=0; //
ADC_RESL=0; //ADC转换结果寄存器清0
P1ASF=0xF0; //设置相应的I/O口为ADC模拟通道 P1.4-P1.5-P1.6-P1.7
ADC_CONTR |= ADC_POWER; //打开AD转换电源
ADC_CONTR |= ADC_SPEEDH; //设置AD转换速度
delay(1);
}
uint ADC_result(uchar x) //AD转换结果
{
uint result;
ADC_CONTR &= 0xF8; //清通道
ADC_CONTR |= x; //切换通道,x为通道,如x=5,就是P1.5
delay_us(30); //切换通道延时
ADC_CONTR |= ADC_START; //开启AD转换
delay_us(4); //
while(!(ADC_CONTR & ADC_FLAG)); //等待AD转换结束
ADC_CONTR &= ~ADC_FLAG; //清除AD转换结束标志位
result = ADC_RES << 2; //ADC高8位结果左移2位
result = result | ADC_RESL; //合成10位转换结果
return result; //返回转换结果
}
uint U(uchar x) //测量电压40次去除最大最小求平均
{
uint U[40],min,max,S;
uchar i;
for(i=0;i<40;i++)
{
U[i]=ADC_result(x); //获取x通道ADC结果
}
for(i=1,min=U[0];i<=39;i++)
{
if(U[i]
}
for(i=1,max=U[0];i<=39;i++)
{
if(U[i]>max) max=U[i];
} //求最大值
for(i=0,S=0;i<=39;i++) S+=U[i];
S=S-min-max;
S /= 38 ; //减去最大最小求平均
return S; //返回计算结果
}