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.

DSP2808 ADC problem.

I have build a project (2808, CCS 5.5) for ADC based on a example project "Example_280xAdcSoc", key information are:

1. Dual-sequencer and Sequencing sampling mode, internal reference is activated.

2. CONV00~CONV04 five channels are used for conversion, corresponding regs ADCResult0~ADCResult5.

3. ePWM1 is set as the trigger for ADC conversion

4. connect the CONV00 to 3.3V and CONV01~CONV04 to GND.

The problem: I observed the data in ADCResult0~ADCResult4, and find that the values of ADCResult0 and ADCResult1 are same, and the values of ADCReslut2~ADCResult4 are same. This is very weird considering my connection (step 4). Moreover, ADCResult0 and ADCResult1 are 17872, ADCReslut2~ADCResult4 are 13880. Because I do not know the value of the internal reference (step 1), I do not know whether  the results is right or not. Maybe this is because of my codes, anyone can help me?

The customized codes are listed as follows:

#include "DSP280x_Device.h"       // DSP280x Headerfile Include File
#include "DSP280x_Examples.h"     // DSP280x Examples Include File
#include "Customized_Function.h"  // Customized Function

// Prototype statements for functions found within this file.
interrupt void adc_isr(void);

// Global variables used in this example:
int Voltage[5];
int Flag;

main()
{
// Step 1. Initialize System Control:
   InitSysCtrl();

// For this example, set HSPCLK to SYSCLKOUT / 8 (12.5Mhz assuming 100Mhz SYSCLKOUT or 7.5 MHz assuming 60 MHz SYSCLKOUT)
   EALLOW;
   SysCtrlRegs.HISPCP.all = 0x0000;  // HSPCLK = SYSCLKOUT/8
   EDIS;

// Step 2. Initialize GPIO:
// InitGpio();  // Skipped for this example

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize the PIE control registers to their default state.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
   EALLOW;  // This is needed to write to EALLOW protected register
   PieVectTable.ADCINT = &adc_isr;
   EDIS;    // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals: Not required for this example
   InitAdc();  // For this example, init the ADC

// Step 5. User specific code, enable interrupts:

// Enable ADCINT in PIE
   PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
   IER |= M_INT1; // Enable CPU Interrupt 1
   EINT;          // Enable Global interrupt INTM
   ERTM;          // Enable Global realtime interrupt DBGM

// Configure ADC
   AdcRegs.ADCTRL1.bit.SEQ_CASC=0;        //setDual-sequencer mode
   AdcRegs.ADCTRL3.bit.SMODE_SEL=0;       //set Sequencing sampling mode
   AdcRegs.ADCREFSEL.bit.REF_SEL=0x00;    //reference select bit, 00 is internal bandgap reference
   AdcRegs.ADCTRL3.bit.ADCBGRFDN=0x03;    //power up the bandgap reference
   AdcRegs.ADCMAXCONV.all = 0x0004;       // Setup 5 conversions on SEQ1
   AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA0 as 1st SEQ1 conv.
   AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup ADCINA1 as 2nd SEQ1 conv.
   AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2; // Setup ADCINA2 as 3rd SEQ1 conv.
   AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3; // Setup ADCINA3 as 4th SEQ1 conv.
   AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4; // Setup ADCINA4 as 5th SEQ1 conv.
   AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)

// Assumes ePWM1 clock is already enabled in InitSysCtrl();
   EPwm1Regs.ETSEL.bit.SOCAEN = 1;        // Enable SOC on A group, SOC means start of conversion
   EPwm1Regs.ETSEL.bit.SOCASEL = 4;       // Select SOC from CPMA on upcount
   EPwm1Regs.ETPS.bit.SOCAPRD = 1;        // Generate pulse on 1st event
   EPwm1Regs.CMPA.half.CMPA = 0x0000;	  // Set compare A value
   EPwm1Regs.TBPRD = 0x0001;              // Set period for ePWM1
   EPwm1Regs.TBCTL.bit.CTRMODE = 0;       // count up and start

// Wait for ADC interrupt

   for(;;)
   {
      if (FLAG==1)//customized codes
           {
      	      Customized_Function();//
             
              FLAG=0;

              // Reinitialize for next ADC sequence
              AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
              AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
              PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
           }
   }
}


interrupt void  adc_isr(void)
{
  Voltage[0] = (((int)(AdcRegs.ADCRESULT0 >>4))*3)/4095;
  Voltage[1] = (((int)(AdcRegs.ADCRESULT1 >>4))*3)/4095;
  Voltage[2] = (((int)(AdcRegs.ADCRESULT2 >>4))*3)/4095;
  Voltage[3] = (((int)(AdcRegs.ADCRESULT3 >>4))*3)/4095;
  Voltage[4]= (((int)(AdcRegs.ADCRESULT4 >>4))*3)/4095;

  // Conversion finished, start over
  FLAG=1;

  return;
}

 

  • Is your hardware custom or TI (i.e. control card or development kit)?  If custom, please review the Analog-to-Digital Converter section of the HW design guide or this analog interface user guide.  There is also the ADC reference guide in case you haven't seen it.

    A couple other points, while I wait for your response:

    1) The full scale voltage is always 3.0V regardless of the reference mode, so you don't need the internal reference voltage to calculate the expected code.

    2) The results registers are left justified so you will need to divide by 8 to determine the true 12b conversion code or use the "mirror" resisters (see section 2.8 of above mentioned reference guide).

    regards,

    Joe

  • I also just noticed your HISPCP is set to 0x0000.  Based on the System Control and Interrupts guide, that is setting ADCCLK equal to SYSCLK.  If you are running the system at 100MHz, you might be overclocking the ADC unless you are scaling it down in the InitAdc function.

  • Hi Joe,

    Thanks for your reply. Will check following your suggestion. My board is eZdspTMS320F2808 from Spectrum Digital Inc.

  • Hi Joe,

    Thanks a lot.
    My problem results from the frequency setting. Based on my code above, the SYSCLK is 100Mhz and ADCCLK is equal to SYSCLK. I check the ADC guide and find that the ADC maximum frequency for 2808 is 12.5Mhz. That is why I get the wrong result. Now I set the SYSCLK as 100/8=12.5Mhz. The ADC works well.
    Thank you again
  • Glad to hear you have it working! Thanks for letting me know.
    Regards,
    Joe
  • Thank you. And I have a better solution. I find that I can set ADCCLK by set the Register ADCCLKPS and CPS (ADCCLK=SYSCLK/(ADCCLKPS+CPS)). Therefore, I change the SYSCLK back to 100Mhz so that the DSP keeps a higher performance for my other codes. And the ADCCLK is set as 12.5Mhz.
    Now I have another question: Due to my ADC is triggered by the ePWM1, the frequency of ADC is ADCCLK (Fadc=12.5Mhz) as set by the related register or decided by the ePWM1 frequency (Fepwm)? or the smaller one?

  • The ADCCLK will be 12.5Mhz and that clock rate can be used to determine your S/H time (based on ACQPS), conversion time, and ultimately your throughput (MSPS).  The PWM only tells the ADC when to begin, not at what rate to convert.  If you haven't seen these resources, you may find them helpful!

    Regards,

    Joe

  • Thanks. Will go through it.