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.

28035 ADC calibration does not work

Hello,

I am designing with the 28035 and have problems with the calibration of the ADC.  I am using bootmode GetMode and
have the Device_Cal() routine included in the initialization code (at several places) but somehow the ADC does not get calibrated.
If I use the Menu Reset .gel command of CCS4 the ADC does get calibrated.  Has anyone had the same issue?


// ADC CALIBRATION 
//---------------------------------------------------
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable ADC peripheral clock
(*Device_cal)(); // Auto-calibrate from TI OTP
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; // Return ADC clock to original state

EALLOW;
SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 0; // Turn on XTALOSC
SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1; // Turn off XCLKIN
SysCtrlRegs.CLKCTL.bit.OSCCLKSRC2SEL = 0; // Switch to external clock
SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 1; // Switch from INTOSC1 to INTOSC2/ext clk
SysCtrlRegs.CLKCTL.bit.WDCLKSRCSEL = 1; // Switch Watchdog Clk Src to external clock
SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1; // Turn off INTOSC2
SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 1; // Turn off INTOSC1
EDIS;

/* Init PLL */
.....

adc init:

/* Enable ad clock */
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
EDIS;

EALLOW;
AdcRegs.ADCCTL1.all = ADC_RESET_FLAG;
asm(" NOP ");
asm(" NOP ");

(*Device_cal)();
asm(" NOP ");
asm(" NOP ");

AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; ///Power up bandgap

AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;/// 0= internal reference, 1= external reference
// AdcRegs.ADCCTL1.bit.VREFLOCONV = 0;
AdcRegs.ADCCTL1.bit.ADCREFPWD = 1;///Power up reference
AdcRegs.ADCCTL1.bit.ADCPWDN = 1;/// Power up rest of ADC
AdcRegs.ADCCTL1.bit.ADCENABLE = 1;///Enable ADC

asm(" RPT#100 || NOP");///

AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;///
AdcRegs.ADCCTL1.bit.TEMPCONV = 0;///

// DSP28x_usDelay(5000L);
(*Device_cal)();

// configure the Interrupt 1 and 2 Register
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // No further ADCINT1 pulses are generated until ADCINT1 flasg in ADCINTFLG register is cleared by user
AdcRegs.INTSEL1N2.bit.INT1E = 0; // Disable ADCINT1
AdcRegs.INTSEL1N2.bit.INT1SEL = 6; // EOC 6 is trigger for ADCINT1


//*************** CHANNEL SELECT ************

AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADC A0 -> Phase A current
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC0CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC1CTL.bit.CHSEL = 8; // ADC B0 -> Phase B current
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC1CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC2CTL.bit.CHSEL = 11; // ADC B3 -> Phase C current (nc)
AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC2CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC3CTL.bit.CHSEL = 2; // ADC A2 -> Phase voltage A
AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC3CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC4CTL.bit.CHSEL = 9; // ADC B1 -> Phase B voltage
AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC4CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC5CTL.bit.CHSEL = 3; // ADC A3 -> Phase voltage C
AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC5CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles

AdcRegs.ADCSOC6CTL.bit.CHSEL = 14; // ADC B6 -> I offset
AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 5; // set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC6CTL.bit.ACQPS = 7; // set SOC0 S/H window to 7 ADC clock cycles


/* interrupt setup */
AdcRegs.INTSEL1N2.bit.INT1E =1; //ADCINT1 is enabeld
PieVectTable.ADCINT1 = &adc_isr;
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
EDIS;

Thanks in advance,
Dan
  • Dan- a couple thoughts in case you are still having trouble:

    Daniel Engelbarts said:

    // ADC CALIBRATION

    //---------------------------------------------------
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable ADC peripheral clock
    (*Device_cal)(); // Auto-calibrate from TI OTP
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; // Return ADC clock to original state



    I do not believe this section will work behave properly since PCLKCR0 is EALLOW protected.
     

    Daniel Engelbarts said:
    
    
    adc init:
    
    
    /* Enable ad clock */
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
    EDIS;

    EALLOW;
    AdcRegs.ADCCTL1.all = ADC_RESET_FLAG;
    asm(" NOP ");
    asm(" NOP ");

    (*Device_cal)();
    asm(" NOP ");
    asm(" NOP ");



    Can you provide the value of ADC_RESET_FLAG? Depending on the value, this could be powering down the ADC or having some other unintended side effect.
  • Hi Joe,

    Thanks for your suggestions.

    I saw that the trim registers of the ADC actually were filled and is not resetted, so the Device_Cal() function works properly.

    The thing is I use 28035 rev 0 material and it looks that ADCREFTRIM register has another definition for a rev 0 device. 

    // Rev. 0 silicon - BG_FINE_TRIM = bits 3:0.
    // BG_COARSE_TRIM = bits : 8:4
    // Rev. A and beyond silicon = below register definition:
    struct ADCREFTRIM_BITS{ // bits description
    Uint16 BG_FINE_TRIM:5; // 4:0 Coarse trim for internal BG
    Uint16 BG_COARSE_TRIM:4; // 8:5 Fine trim for internal BG
    Uint16 EXTREF_FINE_TRIM:5; // 13:9 Fine trim for external reference
    Uint16 rsvd1:2; // 15:14 reserved
    
    
    The ADCREFTRIM register is filled by the Device_Cal() function with a value of 0x22AF = b0010 0010 1010 1111
    BG_FINE_TRIM: (4:0) = b01111
    BG_COARSE_TRIM: (8:5) =   b0101
    Do I need to change the structure ADCREFTRIM_BITS if I use rev 0 instead of rev A?
  • The register definition did change between rev0 and revA, however you do not need to change the structure since these are more or less internal registers which were documented.  The Device_cal() will populate the correct trim whether rev0 or revA.  The trim value you mention looks reasonable as well.

    Your original post stated the ADC_cal was not functioning and implied the Device_cal() was not executing during normal operation, is this now resolved, or does it still only work through the menu reset .gel?

  • Hello Joe,

    Thanks for your answer, the trimming works now. There was an issue with ISR timing: there was not enough time to do ADC sampling properly

    Regards