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.

TMS320F28377D: sequential conversions within the same adc module (ADC A)?

Part Number: TMS320F28377D

Hi There,

In my software I would like to achieve sequential conversion of the signals going into the adc A module, such that:

When the EPWM6 CTR = 0, I start converting the signals on ADC A2, ADC A3, ADC A4, ADC A5, and when all the previous conversions are completed the last one will generate an interrupt.

I have used the code below, for the Epwm configuration:


EPwm6Regs.ETSEL.bit.SOCAEN = 1; EPwm6Regs.ETSEL.bit.SOCASEL = 1; // generate SOCA pulse when TBCTR =0 EPwm6Regs.ETPS.bit.SOCAPRD = 1;

and for the ADC configuration:

void ConfigureADC_A(void)
{
	EALLOW;

	//write configurations
	AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // set ADCCLK divider to INPUT CLOCK /4
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);

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

	//power up the ADC
	AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;

	//delay for 1ms to allow ADC time to power up
	DELAY_US(1000);

	EDIS;
}

and configured each channel as:

void SetupADC_A()
{
Uint16 acqps;

//determine minimum acquisition window (in SYSCLKS) based on resolution (SYSCLK = 200MHz)
if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION){
acqps = 19; //(19+1)/200MHz = 100ns. The min is 75ns
}
else { //resolution is 16-bit
acqps = 63; //320ns ((63+1)*(1/200MHz))
}

//Select the channels to convert and end of conversion flag
EALLOW;

AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2;
AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample and hold window
AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 15; // 0Fh ADCTRIG15 - ePWM6, ADCSOCA

AdcaRegs.ADCSOC3CTL.bit.CHSEL = 3;
AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps; //sample and hold window
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 15; //0Fh ADCTRIG15 - ePWM6, ADCSOCA

AdcaRegs.ADCSOC4CTL.bit.CHSEL = 4;
AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps; //sample and hold window
AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = 15; //0Fh ADCTRIG15 - ePWM6, ADCSOCA

AdcaRegs.ADCSOC5CTL.bit.CHSEL = 5;
AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps; //sample and hold window
AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 15; // 0Fh ADCTRIG15 - ePWM6, ADCSOCA

AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 5; // EOC5 is trigger for ADCINT1
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
}

Now in my "main.c" I have enable interrupt ADC A1:

//Map ISR functions
EALLOW;

PieVectTable.ADCA1_INT = &adca1_isr;

EDIS;
//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

// Enable PIE interrupt (ref Table 2-2. PIE Channel Mapping, pag. 90)

PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // enable adc_int_A_1 // interrupt ADC A1

and the interrupt looks as follow:

interrupt void adca1_isr(void) {
	
	//********************************************
	//	Translate Adc measurements into double
	//********************************************




	AdcaResults2 = AdcaResultRegs.ADCRESULT2; //

	AdcaResults3 = AdcaResultRegs.ADCRESULT3; //

	AdcaResults4 = AdcaResultRegs.ADCRESULT4; //

	AdcaResults5 = AdcaResultRegs.ADCRESULT5; //


	i1_meas = (-0.004346) * ((double) (AdcaResults2)) + i1_meas_offset;

	i2_meas = (-0.01622) * ((double) (AdcaResults3)) + i2_meas_offset; 
	
	v1_meas = (double)(AdcaResults4) * (- 0.03948) + v1_meas_offset; 

	v2_meas = (-0.08432) * ((double) (AdcaResults5)) + v2_meas_offset;

//...
//... PI controller code execution + PWM CMP update
//...

//********************************************
//	Clearing the ADC interrupt
//********************************************

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

}

Is this the correct procedure to have the adc channels A2, A3, A4, A5 sampled in sequence? and is the interrupt "started" indeed after all the ADC conversion have been completed?

I am asking because I would like to be sure that inside the interrupt all the values sampled by the ADC are correct (and conversions are completed) in order to properly execute the control...

Your opinion would really help, 

Thank you so much,

Leo

  • Hello,
    I am writing to let you know that a C2000 team member has been assigned to this post and should be answering shortly.

    Regards
    Baskaran
  • Hi Leo,

    Yeah, that is conceptually correct and should work. ePWM triggers 4 SOCs and then the last SOC triggers an ISR.

    However, there is no need to match the channel number and the SOC number. Instead, you should probably use SOC0 = ch 2, SOC1 = ch3, SOC2 = ch4, SOC3 = ch5, and int generated by SOC 3. You can also re-arrange the channel sampling order as desired (e.g. SOC0 = ch5 if you want that channel to be sampled first). This won't make too much difference if you are only using ADCA and only doing one set of conversions, but it will simplify things quite a bit if you intend to use the other ADCs too or if you want multiple conversion sets on one ADC.
  • Hello Devin,

    Thank you very much for your answer. It is clear, no need to relate SOC# with the ADC channel #.

    Best Regards

    Leo