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.

TMS320F28379D: ADC aquisition timing

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Hi 

I am using PWM of Up-down count mode.

I want to confirm how to get ADC at attached file's arrow timing.

Do ePWM register setting, ETSEL register setting and ADCSOC0CTL register setting correct in attached file? 

Please let me know if I make a mistake or if there is anything else I should be aware of.

Best regards

Naoki

question about ADC aquisition timing.pdf

  • Naoki,

    There is also an SOCA Enable(bit 11) in the ETSEL register that must be set to "1" to allow the trigger to pass to the ADC.  Other than this your attachment is correct.

    We have an example in C2000Ware that sets up the ePWM to trigger the ADC, but on 1st event rather than 0 count.  I've attached the main C file, but the full example is in the path

    C:\ti\c2000\C2000Ware_4_00_00_00\device_support\f2837xd\examples\cpu1\adc_soc_epwm\cpu01

    Best,

    Matthew

    //###########################################################################
    //
    // FILE:   adc_soc_epwm_cpu01.c
    //
    // TITLE:  ADC triggering via epwm for F2837xD.
    //
    //! \addtogroup cpu01_example_list
    //! <h1> ADC ePWM Triggering (adc_soc_epwm)</h1>
    //!
    //! This example sets up the ePWM to periodically trigger the ADC.
    //!
    //! After the program runs, the memory will contain:\n
    //! - \b AdcaResults \b: A sequence of analog-to-digital conversion samples from
    //! pin A0. The time between samples is determined based on the period
    //! of the ePWM timer.
    //
    //###########################################################################
    //
    // $Release Date: 10-06-2021 $
    // $Copyright:
    // Copyright (C) 2013-2021 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"
    
    //
    // Function Prototypes
    //
    void ConfigureADC(void);
    void ConfigureEPWM(void);
    void SetupADCEpwm(Uint16 channel);
    interrupt void adca1_isr(void);
    
    //
    // Defines
    //
    #define RESULTS_BUFFER_SIZE 256
    
    //
    // Globals
    //
    Uint16 AdcaResults[RESULTS_BUFFER_SIZE];
    Uint16 resultsIndex;
    volatile Uint16 bufferFull;
    
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
        InitSysCtrl();
    
    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xD_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 F2837xD_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 F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    //
        InitPieVectTable();
    
    //
    // Map ISR functions
    //
        EALLOW;
        PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1
        EDIS;
    
    //
    // Configure the ADC and power it up
    //
        ConfigureADC();
    
    //
    // Configure the ePWM
    //
        ConfigureEPWM();
    
    //
    // Setup the ADC for ePWM triggered conversions on channel 0
    //
        SetupADCEpwm(0);
    
    //
    // 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
    
    //
    // Initialize results buffer
    //
        for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
        {
            AdcaResults[resultsIndex] = 0;
        }
        resultsIndex = 0;
        bufferFull = 0;
    
    //
    // enable PIE interrupt
    //
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
    
    //
    // sync ePWM
    //
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    
    //
    //take conversions indefinitely in loop
    //
        do
        {
            //
            //start ePWM
            //
            EPwm1Regs.ETSEL.bit.SOCAEN = 1;  //enable SOCA
            EPwm1Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode
    
            //
            //wait while ePWM causes ADC conversions, which then cause interrupts,
            //which fill the results buffer, eventually setting the bufferFull
            //flag
            //
            while(!bufferFull);
            bufferFull = 0; //clear the buffer full flag
    
            //
            //stop ePWM
            //
            EPwm1Regs.ETSEL.bit.SOCAEN = 0;  //disable SOCA
            EPwm1Regs.TBCTL.bit.CTRMODE = 3; //freeze counter
    
            //
            //at this point, AdcaResults[] contains a sequence of conversions
            //from the selected channel
            //
    
            //
            //software breakpoint, hit run again to get updated conversions
            //
            asm("   ESTOP0");
        }while(1);
    }
    
    //
    // ConfigureADC - Write ADC configurations and power up the ADC for both
    //                ADC A and ADC B
    //
    void ConfigureADC(void)
    {
        EALLOW;
    
        //
        //write configurations
        //
        AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /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;
    }
    
    //
    // ConfigureEPWM - Configure EPWM SOC and compare values
    //
    void ConfigureEPWM(void)
    {
        EALLOW;
        // Assumes ePWM clock is already enabled
        EPwm1Regs.ETSEL.bit.SOCAEN    = 0;    // Disable SOC on A group
        EPwm1Regs.ETSEL.bit.SOCASEL    = 4;   // Select SOC on up-count
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;       // Generate pulse on 1st event
        EPwm1Regs.CMPA.bit.CMPA = 0x0800;     // Set compare A value to 2048 counts
        EPwm1Regs.TBPRD = 0x1000;             // Set period to 4096 counts
        EPwm1Regs.TBCTL.bit.CTRMODE = 3;      // freeze counter
        EDIS;
    }
    
    //
    // SetupADCEpwm - Setup ADC EPWM acquisition window
    //
    void SetupADCEpwm(Uint16 channel)
    {
        Uint16 acqps;
    
        //
        // Determine minimum acquisition window (in SYSCLKS) based on resolution
        //
        if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
        {
            acqps = 14; //75ns
        }
        else //resolution is 16-bit
        {
            acqps = 63; //320ns
        }
    
        //
        //Select the channels to convert and end of conversion flag
        //
        EALLOW;
        AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel;  //SOC0 will convert pin A0
        AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
        AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 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
        EDIS;
    }
    
    //
    // adca1_isr - Read ADC Buffer in ISR
    //
    interrupt void adca1_isr(void)
    {
        AdcaResults[resultsIndex++] = AdcaResultRegs.ADCRESULT0;
        if(RESULTS_BUFFER_SIZE <= resultsIndex)
        {
            resultsIndex = 0;
            bufferFull = 1;
        }
    
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
    
        //
        // Check if overflow has occurred
        //
        if(1 == AdcaRegs.ADCINTOVF.bit.ADCINT1)
        {
            AdcaRegs.ADCINTOVFCLR.bit.ADCINT1 = 1; //clear INT1 overflow flag
            AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
        }
    
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }
    
    //
    // End of file
    //
    

  • Hi 

    Thank you for answering my questions. I would like to ask you additional questions.

    Please check the attached file for our setting conditions.

    1, According to the sample code, this is using up count mode. Is there sample code using up-down count mode.

    2, I think that EPWM1A (interrupt handler) and other EPWM2,4,7(U,V,W signals) are needs to be synchronized.

        To synchronize each EPWM, we are setting following register for EPWM 2,4,7.(Written in attached file)  is this setting correct?

    3, Are there any constraint about count mode? For example, do synchronized EPWMs need to be in the same count mode?

    Question about ADC timing.pdf

    The background of the question is that the results of taking the motor current value with the ADC is vary.

    And the result does not change even if the ACQPS is changed, so I am wondering if the acquisition timing is correct of my setting.

    Best regards

    Naoki

  • Hi

    How about the answers to the above questions?

    Will it take a little longer?

    Best regards

    Naoki

  • Naoki,

    Thanks for your patience here, I will need to loop in the ePWM experts to help us further.  Please give us another day to respond.

    Best,
    Matthew

  • Hi Matthew,

    I understand. We look forward to your reply.

    Best regards

    Naoki

  • Hi Naoki,

    1, According to the sample code, this is using up count mode. Is there sample code using up-down count mode.

    There is not another version of this same example with the epwm in up-down count mode but you are correct in that all you would need to change is the CTRMODE bit of the TBCTL register to change the count mode direction.

    2, I think that EPWM1A (interrupt handler) and other EPWM2,4,7(U,V,W signals) are needs to be synchronized.

        To synchronize each EPWM, we are setting following register for EPWM 2,4,7.(Written in attached file)  is this setting correct?

    In order to synchronize the EPWM modules (assuming EPWM1 is providing the synchronization source):

    • Choose the synchronization output of EPWM1. This is done by setting SYNCOSEL of EPWM1 (Typically this is when CTR=Zero)
    • For EPWM2, yes SYNCO can be set as 0 (EPWMxSYNCI/SWFSYNC) and the PHSEN bit should be enabled.
    • For EPWM4 you need to make sure the EPWM4SYNCIN bit of the SYNCSELECT register is set to 0 (EPWM1SYNCOUT). This is the default setting. The PHSEN bit should also be enabled. 
    • For EPWM7 you need to make sure the EPWM7SYNCIN bit of the SYNCSELECT register is set to 0 (EPWM1SYNCOUT). This is the default setting. The PHSEN bit should also be enabled. 

    3, Are there any constraint about count mode? For example, do synchronized EPWMs need to be in the same count mode?

    Generally yes, when synchronization is done EPWM modules within the synchronization have the same count mode direction.

    Best Regards,

    Marlyn

  • Hi Marlyn

    Thank you for answering my questions.

    I was able to confirm that there was no problem in my register settings.

    Thank you !

    Best regards

    Naoki