This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

问下28027的AD结果不准确误差大的问题

这是我用28027launchPad测的AD结果,但是误差都有点大啊!这些数据是用LaunchPad的3.3V和GND之间串联15个阻值为100K的电阻(无校正),通过电阻分压测得的结果。

校正之后结果也不好, 不知道大家的AD结果怎么样?怎么解决的?

  • 楼主你好,

    能否将你的ADC初始化代码贴上来?

    piccolo ADC有个errata是每一次采样的第一个采样结果要舍弃,另外某些采样窗的值也不可以使用。

    通过增大采样窗,降低AD时钟,offset校准后可以提高采样精度。

    Eric

  • //###########################################################################
    // $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通道来校正其他通道得到的结果也不是很好。文档里的触发方式我都有试过,结果都差不多。

  • 建议楼主在初始化完ADC后,调用void AdcOffsetSelfCal()进行偏置校准。

    Eric