这是我用28027launchPad测的AD结果,但是误差都有点大啊!这些数据是用LaunchPad的3.3V和GND之间串联15个阻值为100K的电阻(无校正),通过电阻分压测得的结果。
校正之后结果也不好, 不知道大家的AD结果怎么样?怎么解决的?
Eric Ma:
楼主你好,
能否将你的ADC初始化代码贴上来?
piccolo ADC有个errata是每一次采样的第一个采样结果要舍弃,另外某些采样窗的值也不可以使用。
通过增大采样窗,降低AD时钟,offset校准后可以提高采样精度。
Eric
这是我用28027launchPad测的AD结果,但是误差都有点大啊!这些数据是用LaunchPad的3.3V和GND之间串联15个阻值为100K的电阻(无校正),通过电阻分压测得的结果。
校正之后结果也不好, 不知道大家的AD结果怎么样?怎么解决的?
重新开始:
回复 Eric Ma:
//###########################################################################// $TI Release: 2802x Header Files V1.27 $// $Release Date: June 28, 2010 $//两路参考电压分别接到ADCINA1和ADCINB1上,本实验参考电压为0.5V和2.504V
//############################################################################include "DSP28x_Project.h" // Device Headerfile and Examples Include File
// Prototype statements for functions found within this file.// Global variables used in this example:Uint16 ConversionCount=0;Uint16 Voltage2[10];Uint16 Y1[10];Uint16 Y2[10];float temp,sum=0;float temp1,temp2,ma,offset,t1,t2;
#define X1 0.5#define X2 2.504
main(){
int a,b=0,i=0,j=0; float sum1=0,sum2=0; InitSysCtrl();
DINT;
InitPieCtrl();
IER = 0x0000; IFR = 0x0000;
InitPieVectTable();
// EALLOW; // This is needed to write to EALLOW protected register// PieVectTable.ADCINT1 = &adc_isr;// EDIS; // This is needed to disable write to EALLOW protected registers
InitAdc(); // For this example, init the ADC
EALLOW; AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1; //AD时钟30M EDIS;
EALLOW; AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN2 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN4 = 1; AdcRegs.ADCSOC0CTL.bit.CHSEL = 1; //Set SOC0/1 channel select to ADCINA1 AdcRegs.ADCSOC2CTL.bit.CHSEL = 1; //Set SOC2/3 channel select to ADCINA1 AdcRegs.ADCSOC4CTL.bit.CHSEL = 3; //Set SOC4/5 channel select to ADCINA1
AdcRegs.ADCSOC0CTL.bit.ACQPS = 63; //Set SOC0 acquisition period to 7 ADCCLK AdcRegs.ADCSOC1CTL.bit.ACQPS = 63; //Set SOC1 acquisition period to 7 ADCCLK AdcRegs.ADCSOC2CTL.bit.ACQPS = 63; //Set SOC2 acquisition period to 7 ADCCLK AdcRegs.ADCSOC3CTL.bit.ACQPS = 63; //Set SOC3 acquisition period to 7 ADCCLK AdcRegs.ADCSOC4CTL.bit.ACQPS = 63; //Set SOC4 acquisition period to 7 ADCCLK AdcRegs.ADCSOC5CTL.bit.ACQPS = 63; //Set SOC5 acquisition period to 7 ADCCLK
AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1 AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode AdcRegs.INTSEL1N2.bit.INT1SEL = 4; //setup EOC4 to trigger ADCINT1 to fire
EDIS;
for(;;) {
for(a=0;a<10;a++) //测得10组数据 { //Force start of conversion on SOC0 and SOC2,SOC4 AdcRegs.ADCSOCFRC1.all = 0x15;
//Wait for end of conversion. while( (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0)){} //Wait for ADCINT1 AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 //Get sample result from SOC2/3 Y1[a] = AdcResult.ADCRESULT2; //用于校正 Y2[a] = AdcResult.ADCRESULT3; //用于校正 Voltage2[a] = AdcResult.ADCRESULT4; }
for(i=0; i<9; i++) //排序中值滤波 { for(j=i+1; j<10; j++) { if(Y1[j]<Y1[i]) { b=Y1[i]; Y1[i]=Y1[j]; Y1[j]=b; } } }
for(i=3;i<7;i++) { sum1 =sum1 + Y1[i]; }
// temp1=((sum1/4)/4096)*3300; temp1=sum1/4; sum1=0; t1=((temp1)/4096)*3283; //3283mV电压表测得板子电源电压 for(i=0; i<9; i++) { for(j=i+1; j<10; j++) { if(Y2[j]<Y2[i]) { b=Y2[i]; Y2[i]=Y2[j]; Y2[j]=b; } } }
for(i=3;i<7;i++) { sum2 =sum2 + Y2[i]; }
// temp2=((sum2/4)/4096)*3300; temp2=sum2/4; sum2=0; t2=((temp2)/4096)*3283; //3283mV电压表测得板子电源电压
ma=(temp2-temp1)/(X2-X1); //计算增益误差 offset=(X2*temp1-X1*temp2)/(X2-X1); //计算零点漂移误差
for(i=0;i<10;i++) { sum=sum+Voltage2[i]; }// temp=((sum/10)/4096)*3283; // 无校正A3的结果 temp=1000*(sum/10-offset)/ma; // 经过校正A3的结果 sum=0; }}
这是我根据TI提供的例程改的程序。InitAdc(); 函数就是TI库里提供的F2802X_Adc.c里定义的。SOC0默认的优先级高于SOC2,SOC4所以SOC0的结果舍去了。采样窗口是64,AD的时钟也降低了。由于各个采样通道误差情况不一样所以上述程序中用的A1,B1通道来校正其他通道得到的结果也不是很好。文档里的触发方式我都有试过,结果都差不多。
这是我用28027launchPad测的AD结果,但是误差都有点大啊!这些数据是用LaunchPad的3.3V和GND之间串联15个阻值为100K的电阻(无校正),通过电阻分压测得的结果。
校正之后结果也不好, 不知道大家的AD结果怎么样?怎么解决的?
Eric Ma:
回复 重新开始:
建议楼主在初始化完ADC后,调用void AdcOffsetSelfCal()进行偏置校准。
Eric