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.

TMDSCNCD28379D: Using 14 ADCs with F28379D control card

Part Number: TMDSCNCD28379D
Other Parts Discussed in Thread: C2000WARE

I hope my question is not that naive. I want to use 14 different ADCs with my F28379D control card, for this matter I'm using ADCA, B, and C, and receive the trigger by EPWM6SOCA, to make sure that all ADC results are final I am using 6 ADCs from channel A, 5 from channel B and 3 from channel C and send the EOC trigger by SOC5. Since I am in the middle of coding I just wanted to make sure that I've understood the architecture correctly 

""

void ConfigureAdc(void) {
EALLOW;
//********
AdcaRegs.ADCCTL2.bit.PRESCALE = 14; //set ADCCLK divider to /8 ADCCLK = 25MHz
AdcbRegs.ADCCTL2.bit.PRESCALE = 14; //set ADCCLK divider to /8 ADCCLK = 25MHz
AdccRegs.ADCCTL2.bit.PRESCALE = 14; //set ADCCLK divider to /8 ADCCLK = 25MHz
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcSetMode(ADC_ADCC, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
//Set pulse positions to late
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//power up the ADC
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // Active low
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1; // Active low
AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1; // Active low
//********
EDIS;

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

EALLOW;
//********
// ADCA
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 will convert pin A1
AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2; //SOC2 will convert pin A2
AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcaRegs.ADCSOC3CTL.bit.CHSEL = 3; //SOC3 will convert pin A3
AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcaRegs.ADCSOC4CTL.bit.CHSEL = 4; //SOC4 will convert pin A4
AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcaRegs.ADCSOC5CTL.bit.CHSEL = 5; //SOC5 will convert pin A5
AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC

// ADCB
AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin B0
AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 will convert pin B1
AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2; //SOC2 will convert pin B2
AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3; //SOC3 will convert pin B3
AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcbRegs.ADCSOC3CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4; //SOC4 will convert pin B4
AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC

// ADCC
AdccRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin C0
AdccRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdccRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 will convert pin C1
AdccRegs.ADCSOC1CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdccRegs.ADCSOC1CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC
AdccRegs.ADCSOC2CTL.bit.CHSEL = 2; //SOC2 will convert pin C1
AdccRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample window is acqps+1 SYSCLK cycles
AdccRegs.ADCSOC2CTL.bit.TRIGSEL = 0xF; //ADCTRIG15 - ePWM6, ADCSOCA trigger the ADC


AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 5; //end of SOC5 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared

//********
EDIS;
}

// Configure ePWM6 for ADC start of conversion trigger
void ConfigureEpwm6ADC(void) {
// TB (Time Base) Setting
EPwm6Regs.TBPRD = switching_frequency; // 1999->50kHZ, set timer period, 10 bits resolution
EPwm6Regs.TBPHS.bit.TBPHS = 0x0000; // Set phase shift as ZERO
EPwm6Regs.TBCTR = 0x0000; // Clear counter
EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Enable phase loading, Slave mode
EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;

EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

EPwm6Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group (Will be enabled in main loop )
EPwm6Regs.ETSEL.bit.SOCASEL = 4; // Enable event time-base counter equal to CMPA when the timer is incrementing
EPwm6Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm6Regs.CMPA.bit.CMPA = EPwm6Regs.TBPRD >> 4; // Set compare A value to 2048 counts
EPwm6Regs.TBCTL.bit.CTRMODE = TB_FREEZE; // freeze counter

}

""

  • Siam,

    Couple of points:

    1. The ADC in F28379D can operate at a maximum frequency of 50MHz.  I noticed that you are configuring that at half the maximum rated speed.  You may want to Operate the ADC at its maximum frequency to maximize throughput.

    2. In your channel setting, CHSEL = SOC#.  Probably this was not your intention since ADCC SOC assignment also goes by the  order  CHSEL = SOC#.  F28379D do not have external channels ADCINC0 and ADCINC1 bonded out.  Note that ADC setup for this part goes by SOC.  F28379D has 16 SOC (0-15).  This different from the channel number.  Configuring the ADC is done through the SOC unit.  By default, conversion order starts from SOC0 to SOC15 if round robin mode is not used and if all the SOCs are set up.

    3. Each SOC can be programmed with a different external channel or a mix of channels.  For instance you can assign all SOCs to channel 2: 

         AdcaRegs.ADCSOC0CTL.bit.CHSEL = 2; //ADCINA2     

         AdcaRegs.ADCSOC1CTL.bit.CHSEL = 2; //ADCINA2

         :

         :

    4. Having all the ADCs trigger conversions from one source is the correct approach, like what you have set up.

    5. Set up for EOC to toggle ADCINT1 is correct, however on your settings, you need to configure the same for ADCB and ADCC so that each ADC will either have its own interrupt handler to read the completed conversions.  If you want the conversions to happen and complete at the same time then you should use the same number of SOCs, however reading the results have to be managed by individual ISRs for each ADC and will occur depending on the interrupt priority, essentially making this scheme serial.  If your intention is to have the results of all 3 ADCs dumped to a memory at the same time, you can choose the DMA option whose transfer can be triggered by the result of SOC conversion.  See ADC DMA example for reference.

    There are also several examples in C2000Ware that you can try out just to see how the SOC principle in C2000 ADCs work.

    Hope above pointers give you better understanding of the C2000 ADC operation.

    Regards,

    Joseph

  • Thanks so much for your informative answer, 

    Just for clarification, using the following 3 lines of code when I trigger ADC conversion using Epwm6ADCSOCA, all ADCs (ADCA,B and C) start the conversion simultaneously for each SOC number in the specified order of the round-robin wheel?

    ""

    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin A0

    AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin B0

    AdccRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC0 will convert pin C2

    ""



    I might misunderstood this part but, my idea was that I've used SOC0 to SOC5 (6 of them) for ADCA, 5 SOCs for ADCB, and 3 SOCs for ADCC. When I receive the EOC form adcaSOC5 all other conversions are finished and results are accessible through respective ADCRESULS.

  • Hi Sam,

    Good question.  All 3 ADCs will convert simultaneously.  On the figure that you captured above, you can add a line for ADC C and while we are on this topic of simultaneous conversion, I wanted to emphasize the importance of the figure you copied above.  This mode is when all the ADC modules are in sync so if you notice:

         - Trigger is only coming from one source, in your case EPWMSOCA for all 3 ADCs

         - SOC S+H (green phase - sampling time which is [ACQPS + 1]*SYSCLK) are aligned for all ADCs

         - SOC0 conversion (blue phase - quantization time, a function of ADCCLK) are aligned for all ADCs

    If any one of these phases overlap each other, then that would put the conversion operation in asynchronous mode where there will be internal noise coupling from the quantization phase if it falls into the sample and hold phase on any of the other ADCs that are also actively converting.  If you look at the specifications, some of the ADC parameters will have degraded specs or not supported at all as a result of asynchronous conversion.

    Best regards,

    Joseph

  • So if we are in sync mode, we can use just " AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 5; " and be sure that we got all the results, because the end of conversion for channel 5 of ADC_A is the last one in sequence.

    for ADC_A we are using 

    SOC0, SOC1, SOC2, SOC3, SOC4 and SOC5

    for ADC_B we are using 

    SOC0, SOC1, SOC2, SOC3 and SOC4

    for ADC_C we are using 

    SOC0, SOC1 and SOC2

    The trigger is coming from one source for all 3 ADCs and they all have the same ACQPS

  • Hi Sam,

    Yes, your assumption is correct.

    Regards,

    Joseph