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.

LAUNCHXL-F280039C: problem of reading multiple adc values at a same time

Part Number: LAUNCHXL-F280039C

Tool/software:

I'm using the "adc ex1" example of f28003x and try to use the same epwm trigger to trigger another ADC(A1).

(means: Configuring multiple SOCs to use the same trigger allows the trigger to generate a sequence of conversions. )

The test results show that the ADC(A1) pin has voltage value even when no power is added. (ADC(A0) has 3.3V at the same time)

I would like to know which line of program setting this is caused by, or is it caused by not adding program setting?

Please help me experts, thanks.

The code:

//
// Included Files
//
#include "f28x_project.h"

//
// Defines
//
#define RESULTS_BUFFER_SIZE 256

//
// Globals
//
uint16_t adcAResults[RESULTS_BUFFER_SIZE]; // Buffer for results
uint16_t index; // Index into result buffer
volatile uint16_t bufferFull; // Flag to indicate buffer is full
unsigned int ADC_A1;
float ADC_A1_Voltage;
unsigned int ADC_A2;
float ADC_A2_Voltage;
//
// Function Prototypes
//
void initADC(void);
void initEPWM1(void);
void initADCSOC(void);
__interrupt void adcA1ISR(void);

//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
InitSysCtrl();

//
// Initialize GPIO
//
InitGpio();
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO20=0; // Disable pull-up res. on GPIO0
GpioCtrlRegs.GPAMUX2.bit.GPIO20=0;
GpioCtrlRegs.GPADIR.bit.GPIO20=1; // Configure GPIO20 direction
EDIS;

//
// 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.
//
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).
//
InitPieVectTable();

//
// Map ISR functions
//
EALLOW;
PieVectTable.ADCA1_INT = &adcA1ISR; // Function for ADCA interrupt 1
EDIS;

//
// Configure the ADC and power it up
//
initADC();

//
// Configure the ePWM
//
initEPWM1();

//
// Setup the ADC for ePWM triggered conversions on channel 1
//
initADCSOC();

//
// Enable global Interrupts and higher priority real-time debug events:
//
IER |= M_INT1; // Enable group 1 interrupts

EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

for(index = 0; index < RESULTS_BUFFER_SIZE; index++)
{
adcAResults[index] = 0;
}
index = 0;
bufferFull = 0;
//
// Enable PIE interrupt
//
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

//
// Sync ePWM
//
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;

//
// Take conversions indefinitely in loop
//
while(1){
}
}

//
// initADC - Function to configure and power up ADCA.
//
void initADC(void){
//
// Setup VREF as internal
//
SetVREF(ADC_ADCA, ADC_INTERNAL, ADC_VREF3P3);

EALLOW;

//
// Set ADCCLK divider to /4
//
AdcaRegs.ADCCTL2.bit.PRESCALE = 6;

//
// Set pulse positions to late
//
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;

//
// Power up the ADC and then delay for 1 ms
//
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
EDIS;

DELAY_US(1000);
}

//
// initEPWM - Function to configure ePWM1 to generate the SOC.
//
void initEPWM1(void){
EALLOW;
/// ---------------------------------------- EPWM1 ---------------------------------------- ///

// Setup GPIO ----------------------------------------------------------------------------- ///
GpioCtrlRegs.GPAPUD.bit.GPIO0=1; // Disable pull-up res. on GPIO0
GpioCtrlRegs.GPAMUX1.bit.GPIO0=1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAPUD.bit.GPIO1=1; // Disable pull-up res. on GPIO1
GpioCtrlRegs.GPAMUX1.bit.GPIO1=1; // Configure GPIO1 as EPWM1B

// Setup Time-Base(TB) Submodule ---------------------------------------------------------- ///
// Config for the frequency and duty cycle of the EPWM1
EPwm1Regs.TBPRD = 1200; // Set period counts
EPwm1Regs.CMPA.bit.CMPA = 0; // Setup compare value

// Setup TBCLK
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Set TBCLKSYNC = 1
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // Enable ePWM module clocks in the PCLKCRx register
// TBCLK = EPWMCLK / (HSPCLKDIV * CLKDIV)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
EPwm1Regs.TBCTL.bit.CLKDIV = 0;

// Counter mode
EPwm1Regs.TBCTL.bit.CTRMODE = 2; // (2)Count up-down

// ePWM Phase setting
EPwm1Regs.TBCTL.bit.PHSEN = 0; // (0)Disable phase loading
EPwm1Regs.TBPHS.bit.TBPHS = 0; // Phase is 0

CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;

EPwm1Regs.TBCTR = 0;
//EPwm1Regs.EPWMSYNCOUTEN.bit.ZEROEN = 1;

// Setup Counter-Compare(CC) Submodule ---------------------------------------------------- ///
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0; // Load registers every ZERO
EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0;
EPwm1Regs.CMPCTL.bit.LOADAMODE = 0;
EPwm1Regs.CMPCTL.bit.LOADBMODE = 0;

// Setup Action-Qualifier(AQ) Submodule --------------------------------------------------- ///
EPwm1Regs.AQCTLA.bit.CAU = 2; // Action when TBCTR = 0; 2: force EPWM1A output high.
EPwm1Regs.AQCTLA.bit.CAD = 1; // Action when TBCTR = CMPA on Up-count; 1: force EPWM1A output low.
EPwm1Regs.AQCTLA.bit.CBU = 1; // Action when TBCTR = CMPA on Up-count; 2: force EPWM1B output high.
EPwm1Regs.AQCTLA.bit.CBD = 2; // Action when TBCTR = CMPA on Up-count; 1: force EPWM1B output low.

// Event Trigger and Interrupt(ET) Submodule:
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOCA
EPwm1Regs.ETSEL.bit.SOCASEL = 1; // 001: Enable event time-base counter equal to zero
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EDIS;
}

//
// initADCSOC - Function to configure ADCA's SOC0 to be triggered by ePWM1.
//
void initADCSOC(void){
//
// Select the channels to convert and the end of conversion flag
//
EALLOW;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0 will convert pin A0
// 0:A0 1:A1 2:A2 3:A3
// 4:A4 5:A5 6:A6 7:A7
// 8:A8 9:A9 A:A10 B:A11
// C:A12 D:A13 E:A14 F:A15
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 9; // Sample window is 10 SYSCLK cycles
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // Trigger on ePWM1 SOCA

AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; // SOC0 will convert pin A1
// 0:A0 1:A1 2:A2 3:A3
// 4:A4 5:A5 6:A6 7:A7
// 8:A8 9:A9 A:A10 B:A11
// C:A12 D:A13 E:A14 F:A15
AdcaRegs.ADCSOC1CTL.bit.ACQPS = 9; // Sample window is 10 SYSCLK cycles
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5; // Trigger on ePWM1 SOCA

AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // End of SOC0 will set INT1 flag
//AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; // End of SOC0 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // Enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Make sure INT1 flag is cleared

EDIS;
}

//
// adcA1ISR - ADC A Interrupt 1 ISR
//
__interrupt void adcA1ISR(void){
//
// Add the latest result to the buffer
// ADCRESULT0 is the result register of SOC0
GpioDataRegs.GPATOGGLE.bit.GPIO20 = 1;

DacaRegs.DACVALS.bit.DACVALS = 4095;

//
// Set the bufferFull flag if the buffer is full
//
ADC_A1 = AdcaResultRegs.ADCRESULT0;
ADC_A1_Voltage = (float)(ADC_A1/4095.0)*3.3;

ADC_A2 = AdcaResultRegs.ADCRESULT1;
ADC_A2_Voltage = (float)(ADC_A2/4095.0)*3.3;


AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge the interrupt
}

//
// End of File
//

  • Hi Yi-Hsuan Tsai,

    Thanks for posting the Query. 

    By looking at the code I see you are configuring DAC

    DacaRegs.DACVALS.bit.DACVALS = 4095;

    The output of DACA comes on A0. Can you try removing this and checking again for A0 input. 

    Also May I know what hardware are you using to test this, Launch Pad or a custom made hardware ?

    Thanks,

    Nilesh

  • InitGpio();
    EALLOW;
    GpioCtrlRegs.GPAPUD.bit.GPIO20=0; // Disable pull-up res. on GPIO0
    GpioCtrlRegs.GPAMUX2.bit.GPIO20=0;
    GpioCtrlRegs.GPADIR.bit.GPIO20=1; // Configure GPIO20 direction
    EDIS;

    Where are ADC pins (A1, A2) analog GPIO inputs being configured? Note we can configure ADC input priority for round Robin or High priority sampling.

        // set priority of SOCs ADC-SOC 11,12,13's
        ADC_setSOCPriority(obj->adcHandle[0], ADC_PRI_ALL_ROUND_ROBIN); //ADCA: ADC_PRI_ALL_HIPRI ADC_PRI_SOC11_HIPRI
        ADC_setSOCPriority(obj->adcHandle[1], ADC_PRI_ALL_ROUND_ROBIN); //ADCA: ADC_PRI_ALL_HIPRI ADC_PRI_SOC13_HIPRI
        ADC_setSOCPriority(obj->adcHandle[2], ADC_PRI_ALL_ROUND_ROBIN); //ADCB: ADC_PRI_ALL_HIPRI ADC_PRI_SOC12_HIPRI

  • Hi Genatco,

    Thank you for replying me.

    Sorry, I can't understand some of the things you told me.

    The program you copied above is what I use to show whether the ADC interrupt is working properly.  (for showing waveform of oscilloscope)

    1. The things that I know is don't need to configure GPIOs before configuring ADCs. (Please correct me if I'm wrong.   or I misunderstood...)

    2. I try to configure the ADC priority into the program, but the result is not right.

    Best Regards.

    Yi-Hsuan Tsai

  • Hi Nilesh,

    Thank you for replying me.

    1. The program "DacaRegs.DACVALS.bit.DACVALS = 4095;" might not  necessary.

        I  did  remove it and try again, but the result value is not right. (ADC_A2_Voltage should be 0)

    2. I trying to test the same trigger(ex: PWM1) for triggering the sequence of SOCs(ex: SOC0、SOC1).

        But the testing result is the value after SOC0 is correct, but the value after the following SOC1 is worng.

        I really want  to know where the problem is.

        

    The "adc_ex10_multiple soc_epwm" is the function that I want, but the representation of program is not what I want and I also can't work on the board.

     

    Best Regards.

    Yi-Hsuan Tsai

  • 1. The things that I know is don't need to configure GPIOs before configuring ADCs. (Please correct me if I'm wrong.   or I misunderstood...)

    You are correct, the analog MUX (check x39c TRM) ADC inputs relate to the GPIO on booster header to SOC for correct ADC channel. SOC configuration has to indicate the input channel number that relates to the booster header pin. Check the launch pad pin mux card and schematic to be sure of the signal is properly routed for the ADC input.

    I think C2000 TRM states all GPIO's default on POR as inputs. Then there are switches on launch pads that redirect some GPIO booter header pins to specific peripherals. You may have to add a pulldown resistor on one of the ADC inputs if voltage dividers are not used on the inputs and some ADC inputs on the same ADCx may float 3v3.

    I don't find the SOC interrupt source for the ADC channel in your code only the interrupt handler is configured. The interrupt handler must clear the interrupt source at the top and clear ACK the group prior exiting the function.

    ADC_setInterruptSource(ADC_INT_BASE, ADC_INT_NUM, ADC_INT_SOC);

  • Nelish, above pointed out DACA output in the interrupt hander contends with ADC A0 input. The analog subsystem table may be different x39c TRM.

  • Hi Genatco,

     

    1. The things you told me about "You may have to add a pulldown resistor on one of the ADC inputs if voltage dividers are not used on the inputs and some ADC inputs on the same ADCx may float 3v3." is  right !!!

    I feel embarrassed that I forgot something so important and simple.

    After I using the pulldown resistor, the value of the ADCs are correct.

    2. And this "ADC_setInterruptSource(ADC_INT_BASE, ADC_INT_NUM, ADC_INT_SOC);"

    is corresponding to the three lines of my program above :

    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // End of SOC0 will set INT1 flag
    //AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; // End of SOC0 will set INT1 flag
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // Enable INT1 flag
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Make sure INT1 flag is cleared

    Modify:

    the value have to change to 1 because the SOCs is ended at  SOC1

    SOC1AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; 

    Thank you for helping me to solve the problem.

    Best Regards.

    Yi-Hsuan Tsai