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.

ADC in TMS320F28055 Controller

Other Parts Discussed in Thread: TMS320F28055

Hello folks,


I have a question about the ADC on the TMS320F28055 controller. I connected a 100 kiloohm potentiometer (3.3V) to the ADC. For testing purposes I took the example from TI. I wanted to trigger my ADC on a timer interrupt, so I set the BIT AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 1, 1 is the timer 0 if I run the program as in the example, I can also see in debug mode that the ADCRESULT0 value changes. Does anyone know why the value changes even though I haven't initialized Timer0? Another question would be how can my ADC interrupt be triggered? I saw in debug mode that the interrupt is not called at all, but the ADCRESULT0 value changes. When I turn my potentiometer all the way up I only see a value of 3796 does that mean the ADC was calibrated incorrectly? Sorry for the many questions, but this is the first time I've used an ADC with the TI controller.


thank you for your help

// Included Files
//
#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

//
// Function Prototypes
//
__interrupt void adc_isr(void);


//
// Global variables
//
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 Voltage1[10] = {0,0,0,0,0,0,0,0,0,0};
Uint16 Voltage2[10];

main()
{
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2805x_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2805x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
    // 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.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2805x_PieCtrl.c file.
    //
    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
    // Service Routines (ISR).
    // This will populate the entire table, even if the __interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2805x_DefaultIsr.c.
    // This function is found in F2805x_PieVect.c.
    //
    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.ADCINT1 = &adc_isr;
    EDIS;    // This is needed to disable write to EALLOW protected registers

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

    //
    // Step 5. User specific code, enable __interrupts:
    //
    // Enable ADCINT1 in PIE
    //
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;   // Enable INT 1.1 in the PIE
    IER |= M_INT1;                       // Enable CPU Interrupt 1
    EINT;                                // Enable Global __interrupt INTM
    ERTM;                            // Enable Global realtime __interrupt DBGM

    LoopCount = 0;
    ConversionCount = 0;

    //
    // Configure ADC
    // Notes:
    // Channel ADCINA4  will be double sampled to workaround the ADC 1st
    // sample issue for rev0 silicon errata.
    // Due to round-robin, SOC0 converts first, then SOC1, then SOC2
    //

    EALLOW;
    AdcRegs.ADCCTL1.bit.INTPULSEPOS= 1; //ADCINT1 trips after AdcResults latch
    AdcRegs.INTSEL1N2.bit.INT1E    = 1; //Enabled ADCINT1
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
    AdcRegs.INTSEL1N2.bit.INT1SEL  = 2; //setup EOC2 to trigger ADCINT1
    AdcRegs.ADCSOC0CTL.bit.CHSEL   = 4; //set SOC0 channel select to ADCINA4
//    AdcRegs.ADCSOC1CTL.bit.CHSEL   = 4; //set SOC1 channel select to ADCINA4
//    AdcRegs.ADCSOC2CTL.bit.CHSEL   = 2; //set SOC2 channel select to ADCINA2
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 1;  //TIMER0 //set SOC0 start trigger on EPWM1A
//    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; //set SOC1 start trigger on EPWM1A
//    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5; //set SOC2 start trigger on EPWM1A
    AdcRegs.ADCSOC0CTL.bit.ACQPS   = 9; //SOC0 S/H Window = 10 (9+1) Clk Cycles     SAMPLE Size
//    AdcRegs.ADCSOC1CTL.bit.ACQPS   = 9; //SOC0 S/H Window = 10 (9+1) Clk Cycles
//    AdcRegs.ADCSOC2CTL.bit.ACQPS   = 9; //SOC0 S/H Window = 10 (9+1) Clk Cycles
    EDIS;


    //
    // Wait for ADC __interrupt
    //
    for(;;)
    {
      LoopCount++;
    }
}



__interrupt void  adc_isr(void)
{
    //
    //Discard ADCRESULT0 as part of the workaround to rev0's 1st sample errata
    //
    Voltage1[ConversionCount] = AdcResult.ADCRESULT0;
//    Voltage2[ConversionCount] = AdcResult.ADCRESULT2;

    //
    // If 10 conversions have been logged, start over
    //
    if(ConversionCount == 9)
    {
        ConversionCount = 0;
    }
    else
    {
        ConversionCount++;
    }

    //
    // Clear ADCINT1 flag reinitialize for next SOC
    //

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge __interrupt to PIE

    return;

}

  • Hi Markus,

    I'll transfer this question over to the ADC expert for support. Have you taken a look at the ADC training within our C2000 Academy resource (https://dev.ti.com/tirex/global?id=c2000Academy)? We also have an ADC video training series which can be found here (https://training.ti.com/analog-digital-converter-adc-training-c2000-mcus).

    Regards,

    Peter

  • Hi Markus,

    Does anyone know why the value changes even though I haven't initialized Timer0?

    In what range are the values that you are observing?

    When I turn my potentiometer all the way up I only see a value of 3796 does that mean the ADC was calibrated incorrectly?

    Have you confirmed the actual voltage on the ADC pin?

    Best Regards,

    Marlyn

  • Hi Marlyn,

    At 0 volts I get a value for the ADCRESULT 0 and at approx. 3.3V 3800. I measured the voltages with a multimeter. What I still don't understand is why my ADC is triggering. I have set Timer0 as the trigger source even though I haven't initialized a Timer0 at all. How can that be? And how is the ADC interrupt called.

  • Thank you i will take a look

  • Hi Markus,

    At 0 volts I get a value for the ADCRESULT 0 and at approx. 3.3V 3800. I measured the voltages with a multimeter. What I still don't understand is why my ADC is triggering. I have set Timer0 as the trigger source even though I haven't initialized a Timer0 at all. How can that be? And how is the ADC interrupt called.

    Before continuing to debug the different trigger options, I'd like to clarify if you can get the correct ADC readings with the example as-is. If you import the example without making any software changes and you connect your input to ADCINA4 do you see the correct results in Voltage 1?

    Best Regards,

    Marlyn

  • hello marlyn,

    I imported the example without making any software changes. I only changed the triggersource to TIMER0 because I don't use a PWM output. I can see that the ADC converts to ADCRESULT0. What I don't understand why the ADC interrupt is not called. As far as I know, the ADC interrupt is always called after an AD conversion. I see it is converted but the ADC interrupt is not called because Voltage1 is not filled.

    I noticed that I don't need an ADC interrupt because I only want to set a SETPOINT with a POTI, but it would still be interesting to know why the interrupt is not called.

  • Hi Markus,

    What I still don't understand is why my ADC is triggering. I have set Timer0 as the trigger source even though I haven't initialized a Timer0 at all. How can that be? And how is the ADC interrupt called.

    The TSS (Timer stop status) bit of the TIMER0TCR register is set to 0 by default (CPU-Timer is running) and since you didn't configure the CPU Timer, the period value is 0. This is causing the timer to consistently cause triggers for the ADC. If you configure the timer with a period value you should see the correct cadence of triggering. Additionally, if you were to set the TSS bit to 1 then you will notice a stop in the ADC conversions.

    The ADC interrupt (ADCINT1) is mapped to the ADC ISR. With the following line of code, the end of conversion for SOC2 is what is is causing the interrupt to occur. Since the example uses SOC0, SOC1, and SOC2, it is logical to want to store the results after all 3 are complete. 

    //
    // setup EOC2 to trigger ADCINT1 to fire
    //
    AdcRegs.INTSEL1N2.bit.INT1SEL = 2;

    Best Regards,

    Marlyn