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.

Question about the "coupling" of ADC

Hello,

I need to convert 8 channels simultaneously with F28377D development tools.

Reference to http://e2e.ti.com/support/microcontrollers/c2000/f/171/p/355638/1253304.aspx#1253304

I learned that I can only sampling 4 channels at one time, so I samples A0, B0, C4, D0 as the 1st group with SOC0; samples A2, B2, C2, D2 as the 2nd group with SOC1. The end of SOC1 will trigger an interrupt to read ADCRESULT0 and ADCRESULT1 in one function. Sampling rate is 50KHz.

The problem to me, is the 1st group has coupling with the 2nd group -- like that if I input a high voltage to A0(the ADCRESULT0 read around 3900), and do not connect A2, there will be some large values in ADCRESULT1(should be 0, but read around 3000); then if I ground A2 (A0 still is high), there will be some small values in ADCRESULT1(should be 0, but read around 15).


following is a part of my codes:

-----------------------------------

//Write ADC configurations and power up the ADC for ADC A B C and D
void ConfigureADC(void)
{
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6;             // set ADCCLK divider to /4
    AdcaRegs.ADCCTL2.bit.RESOLUTION = 0;         // 12-bit resolution
    AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0;         // single-ended channel conversions (12-bit mode only)
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;        // Set pulse positions to late
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;            // power up the ADC
        AdcbRegs.ADCCTL2.bit.PRESCALE = 6;             // set ADCCLK divider to /4
        AdcbRegs.ADCCTL2.bit.RESOLUTION = 0;         // 12-bit resolution
        AdcbRegs.ADCCTL2.bit.SIGNALMODE = 0;         // single-ended channel conversions (12-bit mode only)
        AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;        // Set pulse positions to late
        AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;          // power up the ADC
            AdccRegs.ADCCTL2.bit.PRESCALE = 6;          // set ADCCLK divider to /4
            AdccRegs.ADCCTL2.bit.RESOLUTION = 0;        // 12-bit resolution
            AdccRegs.ADCCTL2.bit.SIGNALMODE = 0;        // single-ended channel conversions (12-bit mode only)
            AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;       // Set pulse positions to late
            AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;          // power up the ADC
                AdcdRegs.ADCCTL2.bit.PRESCALE = 6;          // set ADCCLK divider to /4
                AdcdRegs.ADCCTL2.bit.RESOLUTION = 0;        // 12-bit resolution
                AdcdRegs.ADCCTL2.bit.SIGNALMODE = 0;        // single-ended channel conversions (12-bit mode only)
                AdcdRegs.ADCCTL1.bit.INTPULSEPOS = 1;       // Set pulse positions to late
                AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1;          // power up the ADC
    DELAY_US(1000);                                // delay for 1ms to allow ADC time to power up
    EDIS;
}

void SetupADCEpwm(void)
{
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;          // SOC0 will convert pin A0
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 7;         // trigger on ePWM2 SOCA/C
        AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;          // SOC0 will convert pin B0
        AdcbRegs.ADCSOC0CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
        AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 7;         // trigger on ePWM2 SOCA/C
            AdccRegs.ADCSOC0CTL.bit.CHSEL = 4;          // SOC0 will convert pin C4
            AdccRegs.ADCSOC0CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
            AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
                AdcdRegs.ADCSOC0CTL.bit.CHSEL = 0;          // SOC0 will convert pin D0
                AdcdRegs.ADCSOC0CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
                AdcdRegs.ADCSOC0CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
//    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0;      // 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
    // stage 2
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 2;          // SOC1 will convert pin A2
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
        AdcbRegs.ADCSOC1CTL.bit.CHSEL = 2;          // SOC1 will convert pin B2
        AdcbRegs.ADCSOC1CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
        AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
            AdccRegs.ADCSOC1CTL.bit.CHSEL = 2;          // SOC1 will convert pin C2
            AdccRegs.ADCSOC1CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
            AdccRegs.ADCSOC1CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
                AdcdRegs.ADCSOC1CTL.bit.CHSEL = 2;          // SOC1 will convert pin D2
                AdcdRegs.ADCSOC1CTL.bit.ACQPS = 14;         // sample window is 15 SYSCLK cycles
                AdcdRegs.ADCSOC1CTL.bit.TRIGSEL = 7;        // trigger on ePWM2 SOCA/C
    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1;      // end of SOC1 will set INT1 flag.
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;        // enable INT1 flag
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;      // make sure INT1 flag is cleared
    EDIS;
}

interrupt void adca1_isr(void)
{
    // Read the ADC result and store in circular buffer

    // results of 1st group, copy to AdcA
    AdcaResults[resultsIndex++] = AdcaResultRegs.ADCRESULT0;
    AdcaResults[resultsIndex++] = AdcbResultRegs.ADCRESULT0;
    AdcaResults[resultsIndex++] = AdccResultRegs.ADCRESULT0;
    AdcaResults[resultsIndex++] = AdcdResultRegs.ADCRESULT0;

   // results of 2nd group, copy to AdcB
    resultsIndex = resultsIndex-4;
    AdcbResults[resultsIndex++] = AdcaResultRegs.ADCRESULT1;
    AdcbResults[resultsIndex++] = AdcbResultRegs.ADCRESULT1;
    AdcbResults[resultsIndex++] = AdccResultRegs.ADCRESULT1;
    AdcbResults[resultsIndex++] = AdcdResultRegs.ADCRESULT1;

    if(RESULTS_BUFFER_SIZE <= resultsIndex)
    {
        resultsIndex = 0;
    }

.....

}

------------

Thanks.

  • Try increasing ACQPS to a large value, say 99, and the repeat the experiment.  

    If this fixes the issue, you can experimentally reduce ACQPS to get the smallest value that has no coupling (with some margin).  If the effective sampling time with the increased ACQPS is not acceptable, you may need to do some work with the signal conditioning circuitry to reduce the source impedance.     

  • Hi Devin,


    Thanks for your advice, and your so quickly response.

    I got the reason why I had small value of coupling -- I was using square wave as input to group 1(the input signal's ground was connected with the board's ground), and the low level of the square wave is lower than 0 volt, so at that time the input of group 2 (connected with the board's ground) is higher than group 1.

    When I put a DC offset to the square wave, to let the low level is higher than 0 volt, the grounded group 2 has no coupling anymore.

    The large coupling while group 2 is suspended will not be a big deal (in real case those pins will not be suspended).

  • Hello Devin,

    Looks like you are the master of F28377D, at least about the ADC part. I have another question, that is how to configure the DMA to get a interrupt from ADC.

    Now what I have done: set the ADC with SOC; at the end of SOC, the EOC will trigger the ADC_INT1. This part is working perfect.

    However, I don't know what's the problem about my configure of DMA part.::

    -----------

    DINT;
        InitPieCtrl();
        IER = 0x0000;
        IFR = 0x0000;
        InitPieVectTable();
    
        // Map ISR functions
        EALLOW;
        PieVectTable.DMA_CH1_INT = &local_DMACH1_ISR; //function for DMA interrupt 1
        EDIS;
        // Enable global Interrupts and higher priority real-time debug events:
    	IER |= M_INT1;
        IER |= M_INT7;          // Enable group 1 interrupts
        EnableInterrupts();
    
       // Configure the ADC and power it up
        ConfigureADC();
    
        // Configure the ePWM
        ConfigureEPWM();
    
        // Setup the ADC for ePWM triggered conversions on channel 0
        SetupADCEpwm();
    
    
        DMA_configure();
    
    
        // Initialize results buffer
        for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
        {
            AdcaResults[resultsIndex] = 0;
            AdcbResults[resultsIndex] = 0;
            DMABuf1[i] = 0;
        }
        resultsIndex = 0;
    
        // enable PIE interrupt
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1;      // interrupt of ADC
        PieCtrlRegs.PIEIER7.bit.INTx1 = 1;      // interrupt of DMA
    
        // Sync ePWM
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
        // Start ePWM
        EPwm2Regs.TBCTL.bit.CTRMODE = 0;            // un-freeze and enter up-count mode
    

    --------------

    and:

    -------------------

    void DMA_configure(void)
    {
        EALLOW;
        CpuSysRegs.SECMSEL.bit.VBUS32_1 = 1;
        EDIS;
    
        DMAInitialize();
    
        DMA1Source = &AdcaResultRegs.ADCRESULT0;
        DMA1Dest = &DMABuf1[0]; //DMA destination;
        DMACH1AddrConfig(DMA1Dest,DMA1Source);
    
            DMACH1BurstConfig(1,1,10);
            DMACH1TransferConfig(9,1,0);
            DMACH1WrapConfig(1,0,0,1);
            DMACH1ModeConfig(DMA_ADCAINT1,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,
                             OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
    
    
        StartDMACH1();
    
    }
    
    
    __interrupt void local_DMACH1_ISR(void)
    {
        DMA_Done = 0x0001;
        EALLOW;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
        EDIS;
        ESTOP0;
    }
    
    

    -----------------------------

    Could you help me figure out how to modify my code, or just give me an example of how to configure DMA for an ADC interrupt?

    I worked on this part a few days, but no result at all. If you were not familiar about the DMA part, could you notice someone who can do help?

    I posted a thread, a good guy tried to do help, but not very helpful.

    http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/366913.aspx

    I appreciate. Have a good weekend.

  • In case any confuse about the interrupt of DMA, here is the function of DMACH1ModeConfig():


    ----------

    void DMACH1ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte)
    {
        EALLOW;
    
        // Set up MODE Register:
        DmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH1 = persel; // Source select
        DmaRegs.CH1.MODE.bit.PERINTSEL = 1;             // Should be hard coded to channel, above now selects source
        DmaRegs.CH1.MODE.bit.PERINTE = perinte;         // Peripheral interrupt enable
        DmaRegs.CH1.MODE.bit.ONESHOT = oneshot;         // Oneshot enable
        DmaRegs.CH1.MODE.bit.CONTINUOUS = cont;         // Continous enable
        DmaRegs.CH1.MODE.bit.SYNCE = synce;             // Peripheral sync enable/disable
        DmaRegs.CH1.MODE.bit.SYNCSEL = syncsel;         // Sync effects source or destination
        DmaRegs.CH1.MODE.bit.OVRINTE = ovrinte;         // Enable/disable the overflow interrupt
        DmaRegs.CH1.MODE.bit.DATASIZE = datasize;       // 16-bit/32-bit data size transfers
        DmaRegs.CH1.MODE.bit.CHINTMODE = chintmode;     // Generate interrupt to CPU at beginning/end of transfer
        DmaRegs.CH1.MODE.bit.CHINTE = chinte;           // Channel Interrupt to CPU enable
    
        // Clear any spurious flags:
        DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;          // Clear any spurious interrupt flags
        DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1;            // Clear any spurious sync flags
        DmaRegs.CH1.CONTROL.bit.ERRCLR = 1;             // Clear any spurious sync error flags
    
        // Initialize PIE vector for CPU interrupt:
        PieCtrlRegs.PIEIER7.bit.INTx1 = 1;              // Enable DMA CH1 interrupt in PIE
        // Enable CPU INT7 interrupts are enabled
        IER |= M_INT7;
        EDIS;
    }

    Thanks again.

  • Hi King Kong,

    I am actually not an expert on the DMA.  The need for an DMA example using ADC for F2837xD devices is certainly noted.  I am actually out of office next week, but Mark should be able to help you out.

  • Hi Devin,

    Thank you for your help. Wish you are happy this week.

    The problem is solved with the help from Frank.

    http://e2e.ti.com/support/microcontrollers/c2000/f/171/p/367558/1294011.aspx#1294011

    Regards,

    King