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.

TMS320F280049C: How to update PWM duty cycle in TMS320F280049C

Part Number: TMS320F280049C
Other Parts Discussed in Thread: C2000WARE

I am trying to modify the code C:\ti\c2000\C2000Ware_4_00_00_00\driverlib\f28004x\examples\epwm\epwm_ex3_synchronization.c

My objective is to slowly increase the PWM duty cycle from 1% to 50%. Currently I dont have any setpoint or ADC input. I just want to update the duty cycle gradually.

I would appreciate help if possible.

Ashik

  • Hi,

    You can issue an interrupt at regular events based out of your PWM rising / falling edge. In the interrupt service routine, you can choose to gradually update the EPWM duty cycle using the CMPA/B.
    We do have a sample example in C2000Ware which you can refer - epwm_ex2_updown_aq

    Thanks,
    Aditya

  • Thanks for the information. I will need 2 set of PWM for now. What I am trying to do is giving the phase shift between PWM 1 and 2. Initially both PWM 1 and 2 will start from 0%/1% duty cycle. At this time phase shift will be zero. With the increasing phase shift the duty cycle will increase and it will go maximum 50%. I am trying to synchronize the PWM duty cycle with the increment of phase shift which seems very difficult. Any help will be appreciated.

  • Hi,

    I am not sure whether I have an exact example available in C2000Ware for you. The example that you were initially working with - epwm_ex3_synchronization is the closest that I can see to your application. You can merge example 2 and 3 which will come very closely to your requirement.


    Aditya

  • Hello Aditya,

    I am now using the code, epwm_ex13_up_aq.c .I have attached the code here.  I can now vary the duty cycle upto 50%. I can also put phase shift using the variable "Ph" in watch dog. But to change "Ph", I need to make the AshikFlag and loop_counter==2900 in watchdog. But I want to make the code independent of these two variables (AshikFlag and loop_counter). When the PWM hit 50% duty cycle, I want to change the Phase of variable from watchdog. But I am not aware how to write the condition while the PWM reaches the 50% duty cycle. If you can help with this that would be helpful. Thanks

    //###########################################################################
    //
    // FILE:   epwm_ex13_up_aq.c
    //
    // TITLE:  Action Qualifier Module - Using up count.
    //
    //! \addtogroup driver_example_list
    //! <h1> EPWM Action Qualifier (epwm_up_aq)</h1>
    //!
    //! This example configures ePWM1, ePWM2, ePWM3 to produce an
    //! waveform with independent modulation on EPWMxA and
    //! EPWMxB.
    //!
    //! The compare values CMPA and CMPB are modified within the ePWM's ISR.
    //!
    //! The TB counter is in up count mode for this example.
    //!
    //! View the EPWM1A/B(GPIO0 & GPIO1), EPWM2A/B(GPIO2 & GPIO3)
    //! and EPWM3A/B(GPIO4 & GPIO5) waveforms via an oscilloscope.
    //!
    //
    //###########################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 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 "driverlib.h"
    #include "device.h"
    #include "board.h"
    //
    // Defines
    //
    #define EPWM1_TIMER_TBPRD  2000  // Period register
    #define EPWM1_MAX_CMPA     1000
    #define EPWM1_MIN_CMPA       0
    #define EPWM1_MAX_CMPB     1000
    #define EPWM1_MIN_CMPB       0
    
    #define EPWM2_TIMER_TBPRD  2000  // Period register
    #define EPWM2_MAX_CMPA     1000  //1950
    #define EPWM2_MIN_CMPA       0   //50
    #define EPWM2_MAX_CMPB     1000  //1950
    #define EPWM2_MIN_CMPB       0   //50
    
    #define EPWM3_TIMER_TBPRD  2000  // Period register
    #define EPWM3_MAX_CMPA      950
    #define EPWM3_MIN_CMPA       50
    #define EPWM3_MAX_CMPB     1950
    #define EPWM3_MIN_CMPB     1050
    
    #define EPWM_CMP_UP           1
    #define EPWM_CMP_DOWN         0
    
    //
    // Globals
    //
    typedef struct
    {
        uint32_t epwmModule;
        uint16_t epwmCompADirection;
        uint16_t epwmCompBDirection;
        uint16_t epwmTimerIntCount;
        uint16_t ePWMDone;
        uint16_t epwmMaxCompA;
        uint16_t epwmMinCompA;
        uint16_t epwmMaxCompB;
        uint16_t epwmMinCompB;
    } epwmInfo;
    
    epwmInfo epwm1Info;
    epwmInfo epwm2Info;
    epwmInfo epwm3Info;
    uint16_t AshikFlag = 0 ; //Ashik Added
    uint16_t Ph = 0 ; //Ashik Added
    uint16_t loop_counter = 0 ; //Ashik Added
    
    volatile uint16_t compAVal, compBVal;
    
    //
    //  Function Prototypes
    //
    void initEPWM1(void);
    void initEPWM2(void);
    void initEPWM3(void);
    __interrupt void epwm1ISR(void);
    __interrupt void epwm2ISR(void);
    __interrupt void epwm3ISR(void);
    void updateCompare(epwmInfo*);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pull-ups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
        //
        Board_init();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        Interrupt_register(INT_EPWM1, &epwm1ISR);
        Interrupt_register(INT_EPWM2, &epwm2ISR);
        Interrupt_register(INT_EPWM3, &epwm3ISR);
    
        //
        // Disable sync(Freeze clock to PWM as well)
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // Initialize PWM1 without phase shift as master
        initEPWM1();
    
        // Initialize PWM2 with phase shift of X
        initEPWM2();
        //EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
        //EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
       // EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        initEPWM3();
    
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    
        //
        // ePWM2 uses the ePWM 1 SYNCO as its SYNCIN.
        // ePWM2 SYNCO is generated from its SYNCIN, which is ePWM1 SYNCO
        //
        EPWM_setSyncOutPulseMode(myEPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
    
        //
        // ePWM4 uses the ePWM 1 SYNCO as its SYNCIN.
        //
        //SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM4, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT);
        //
        // Enable all phase shifts.
        //
        EPWM_enablePhaseShiftLoad(myEPWM2_BASE);
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Enable interrupts required for this example
        //
        Interrupt_enable(INT_EPWM1);
        Interrupt_enable(INT_EPWM2);
        Interrupt_enable(INT_EPWM3);
    
        //
        // Enable global Interrupts and higher priority real-time debug events:
        //
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
        //
        // IDLE loop. Just sit and loop forever (optional):
        //
        for(;;)
        {
            asm ("  NOP");
        }
    }
    
    //
    // epwm1ISR - EPWM1 ISR to update compare values
    //
    __interrupt void epwm1ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        updateCompare(&epwm1Info);
    
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // epwm2ISR - EPWM2 ISR to update compare values
    //
    __interrupt void epwm2ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        if (loop_counter!=AshikFlag)
        {
        updateCompare(&epwm2Info);
        }
        else
        {
    
            //Ph=300;
            EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
            EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
            EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        }
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // epwm3ISR - EPWM3 ISR to update compare values
    //
    __interrupt void epwm3ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        updateCompare(&epwm3Info);
    
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM3_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // initEPWM1 - Initialize EPWM1 values
    //
    void initEPWM1()
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM1_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM1_BASE, EPWM1_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM1_BASE);
        EPWM_setPhaseShift(myEPWM1_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM1_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM1_BASE,
                               EPWM_CLOCK_DIVIDER_2,
                               EPWM_HSCLOCK_DIVIDER_2);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM1_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM1_MIN_CMPB);
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Set PWM1A on Zero
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        // Clear PWM1A on event A, up count
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Set PWM1B on Zero
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        // Clear PWM1B on event B, up count
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    //    // Set PWM1B on Zero
    //    EPWM_setActionQualifierAction(myEPWM1_BASE,
    //                                  EPWM_AQ_OUTPUT_B,
    //                                  EPWM_AQ_OUTPUT_HIGH,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    //    // Clear PWM1B on event B, up count
    //    EPWM_setActionQualifierAction(myEPWM1_BASE,
    //                                  EPWM_AQ_OUTPUT_B,
    //                                  EPWM_AQ_OUTPUT_LOW,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM1_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM1_BASE);
        EPWM_setInterruptEventCount(myEPWM1_BASE, 3U);
    
       //
       // Information this example uses to keep track
       // of the direction the CMPA/CMPB values are
       // moving, the min and max allowed values and
       // a pointer to the correct ePWM registers
       //
    
        // Start by increasing CMPA & CMPB
        epwm1Info.epwmCompADirection = EPWM_CMP_UP;
        epwm1Info.epwmCompBDirection = EPWM_CMP_UP;
    
        // Clear interrupt counter
        epwm1Info.epwmTimerIntCount = 0;
        epwm1Info.ePWMDone = 0;
    
        // Set base as ePWM1
        epwm1Info.epwmModule = myEPWM1_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm1Info.epwmMaxCompA = EPWM1_MAX_CMPA;
        epwm1Info.epwmMinCompA = EPWM1_MIN_CMPA;
        epwm1Info.epwmMaxCompB = EPWM1_MAX_CMPB;
        epwm1Info.epwmMinCompB = EPWM1_MIN_CMPB;
    }
    
    //
    // initEPWM2 - Initialize EPWM2 values
    //
    void initEPWM2()
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM2_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM2_BASE, EPWM2_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM2_BASE);
        EPWM_setPhaseShift(myEPWM2_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM2_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM2_BASE,
                               EPWM_CLOCK_DIVIDER_2,
                               EPWM_HSCLOCK_DIVIDER_2);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM2_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM2_MIN_CMPB); //EPWM2_MAX_CMPB
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Clear PWM2A on period and set on event A, up-count
    //    EPWM_setActionQualifierAction(myEPWM2_BASE,
    //                                  EPWM_AQ_OUTPUT_A,
    //                                  EPWM_AQ_OUTPUT_LOW,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    //    EPWM_setActionQualifierAction(myEPWM2_BASE,
    //                                  EPWM_AQ_OUTPUT_A,
    //                                  EPWM_AQ_OUTPUT_HIGH,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Clear PWM2A on period and set on event A, up-count
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Clear PWM2B on Period & set on event B, up-count
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM2_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM2_BASE);
        EPWM_setInterruptEventCount(myEPWM2_BASE, 3U);
    
        //
        // Information this example uses to keep track
        // of the direction the CMPA/CMPB values are
        // moving, the min and max allowed values and
        // a pointer to the correct ePWM registers
        //
    
        // Start by increasing CMPA & decreasing CMPB
        epwm2Info.epwmCompADirection = EPWM_CMP_UP;
        epwm2Info.epwmCompBDirection = EPWM_CMP_DOWN;
    
        // Clear interrupt counter
        epwm2Info.epwmTimerIntCount = 0;
    
        // Set base as ePWM2
        epwm2Info.epwmModule = myEPWM2_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm2Info.epwmMaxCompA = EPWM2_MAX_CMPA;
        epwm2Info.epwmMinCompA = EPWM2_MIN_CMPA;
        epwm2Info.epwmMaxCompB = EPWM2_MAX_CMPB;
        epwm2Info.epwmMinCompB = EPWM2_MIN_CMPB;
    }
    
    //
    // initEPWM3 - Initialize EPWM3 values
    //
    void initEPWM3(void)
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM3_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM3_BASE, EPWM3_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM3_BASE);
        EPWM_setPhaseShift(myEPWM3_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM3_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM3_BASE,
                               EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM3_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM3_MAX_CMPB);
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Set PWM3A on event B, up-count & clear on event B, up-count
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        // Toggle EPWM3B on counter = zero
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_TOGGLE,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM3_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM3_BASE);
        EPWM_setInterruptEventCount(myEPWM3_BASE, 3U);
    
       //
       // Information this example uses to keep track
       // of the direction the CMPA/CMPB values are
       // moving, the min and max allowed values and
       // a pointer to the correct ePWM registers
       //
    
        // Start by increasing CMPA & decreasing CMPB
        epwm3Info.epwmCompADirection = EPWM_CMP_UP;
        epwm3Info.epwmCompBDirection = EPWM_CMP_UP;
    
        // Start the count at 0
        epwm3Info.epwmTimerIntCount = 0;
    
        // Set base as ePWM1
        epwm3Info.epwmModule = myEPWM3_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm3Info.epwmMaxCompA = EPWM3_MAX_CMPA;
        epwm3Info.epwmMinCompA = EPWM3_MIN_CMPA;
        epwm3Info.epwmMaxCompB = EPWM3_MAX_CMPB;
        epwm3Info.epwmMinCompB = EPWM3_MIN_CMPB;
    }
    
    //
    // updateCompare - Update the compare values for the specified EPWM
    //
    void updateCompare(epwmInfo *epwm_info)
    {
       //
       // Every 10'th interrupt, change the CMPA/CMPB values
       //
       if(epwm_info->epwmTimerIntCount == 10)
       {
           epwm_info->epwmTimerIntCount = 0;
           compAVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                                  EPWM_COUNTER_COMPARE_A);
           compBVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                                  EPWM_COUNTER_COMPARE_B);
    //       if (compAVal==epwm_info->epwmMaxCompA) {epwm1Info.ePWMDone = 1;}
           //
           // If we were increasing CMPA, check to see if
           // we reached the max value.  If not, increase CMPA
           // else, change directions and decrease CMPA
           //
           if(epwm_info->epwmCompADirection == EPWM_CMP_UP)
           {
               if(compAVal < epwm_info->epwmMaxCompA)
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, ++compAVal);
                   AshikFlag = AshikFlag+1;
               }
               else
               {
    //               epwm_info->epwmCompADirection = EPWM_CMP_DOWN;
    //               EPWM_setCounterCompareValue(epwm_info->epwmModule,
    //                                           EPWM_COUNTER_COMPARE_A, --compAVal);
    //               epwm1Info.ePWMDone = 1;
    
               }
    
           }
    
           //
           // If we were decreasing CMPA, check to see if
           // we reached the min value.  If not, decrease CMPA
           // else, change directions and increase CMPA
           //
           else
           {
               if(compAVal == epwm_info->epwmMinCompA)
               {
                   epwm_info->epwmCompADirection = EPWM_CMP_UP;
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, ++compAVal);
    
               }
               else
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, --compAVal);
               }
           }
    
           //
           // If we were increasing CMPB, check to see if
           // we reached the max value.  If not, increase CMPB
           // else, change directions and decrease CMPB
           //
           if(epwm_info->epwmCompBDirection == EPWM_CMP_UP)
           {
               if(compBVal < epwm_info->epwmMaxCompB)
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, ++compBVal);
               }
               else
               {
    //               epwm_info->epwmCompBDirection = EPWM_CMP_DOWN;
    //               EPWM_setCounterCompareValue(epwm_info->epwmModule,
    //                                           EPWM_COUNTER_COMPARE_B, --compBVal);
    
               }
           }
    
           //
           // If we were decreasing CMPB, check to see if
           // we reached the min value.  If not, decrease CMPB
           // else, change directions and increase CMPB
           //
           else
           {
               if(compBVal == epwm_info->epwmMinCompB)
               {
                   epwm_info->epwmCompBDirection = EPWM_CMP_UP;
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, ++compBVal);
               }
               else
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, --compBVal);
               }
           }
       }
    
       //
       // Increment interrupt count if < 10
       //
       else
       {
          epwm_info->epwmTimerIntCount++;
       }
    
       return;
    
    }
    //
    // End of file
    //
    

  • Hello Ashik,

    Glad that you're able to get the required duty cycle. For your phase requirements, you can add a check within the interrupt sub-routine of the PWM which would check for the duty cycle whether it has reached 50%. Once it reaches 50%, you can choose to change the value of the phase value.

    The current method is actually fine, if it is not bothering your timing calculations.

    For a more generic approach, you can read the Comparator value within the ISR and check whether it has reached 50%, based on which you can choose to update the phase value.

    Thanks,

    Aditya

  • Thanks Aditya,

    Can you let me know apart from changing the TBPRD value, how can I change the switching frequency? Currently the EPWM_Timer_TBPRD value is 2000 and it gives 12.5 kHz. I want 100 kHz switching frequency.

  • //###########################################################################
    //
    // FILE:   epwm_ex13_up_aq.c
    //
    // TITLE:  Action Qualifier Module - Using up count.
    //
    //! \addtogroup driver_example_list
    //! <h1> EPWM Action Qualifier (epwm_up_aq)</h1>
    //!
    //! This example configures ePWM1, ePWM2, ePWM3 to produce an
    //! waveform with independent modulation on EPWMxA and
    //! EPWMxB.
    //!
    //! The compare values CMPA and CMPB are modified within the ePWM's ISR.
    //!
    //! The TB counter is in up count mode for this example.
    //!
    //! View the EPWM1A/B(GPIO0 & GPIO1), EPWM2A/B(GPIO2 & GPIO3)
    //! and EPWM3A/B(GPIO4 & GPIO5) waveforms via an oscilloscope.
    //!
    //
    //###########################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 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 "driverlib.h"
    #include "device.h"
    #include "board.h"
    //
    // Defines
    //
    #define EPWM1_TIMER_TBPRD  100  // Period register //2000
    #define EPWM1_MAX_CMPA     50   //1000
    #define EPWM1_MIN_CMPA       0
    #define EPWM1_MAX_CMPB     50     //1000
    #define EPWM1_MIN_CMPB       0
    
    #define EPWM2_TIMER_TBPRD  100  // Period register
    #define EPWM2_MAX_CMPA     50  //1950
    #define EPWM2_MIN_CMPA      0   //50
    #define EPWM2_MAX_CMPB     50  //1950
    #define EPWM2_MIN_CMPB      0   //50
    
    #define EPWM3_TIMER_TBPRD  100  // Period register
    #define EPWM3_MAX_CMPA      50
    #define EPWM3_MIN_CMPA       0
    #define EPWM3_MAX_CMPB      50
    #define EPWM3_MIN_CMPB       0
    
    #define EPWM_CMP_UP           1
    #define EPWM_CMP_DOWN         0
    
    //
    // Globals
    //
    typedef struct
    {
        uint32_t epwmModule;
        uint16_t epwmCompADirection;
        uint16_t epwmCompBDirection;
        uint16_t epwmTimerIntCount;
        uint16_t ePWMDone;
        uint16_t epwmMaxCompA;
        uint16_t epwmMinCompA;
        uint16_t epwmMaxCompB;
        uint16_t epwmMinCompB;
    } epwmInfo;
    
    epwmInfo epwm1Info;
    epwmInfo epwm2Info;
    epwmInfo epwm3Info;
    uint16_t AshikFlag = 0 ; //Ashik Added
    uint16_t Ph = 0 ; //Ashik Added
    uint16_t loop_counter = 0 ; //Ashik Added
    
    volatile uint16_t compAVal, compBVal;
    
    //
    //  Function Prototypes
    //
    void initEPWM1(void);
    void initEPWM2(void);
    void initEPWM3(void);
    __interrupt void epwm1ISR(void);
    __interrupt void epwm2ISR(void);
    __interrupt void epwm3ISR(void);
    void updateCompare(epwmInfo*);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pull-ups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
        //
        Board_init();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        Interrupt_register(INT_EPWM1, &epwm1ISR);
        Interrupt_register(INT_EPWM2, &epwm2ISR);
        Interrupt_register(INT_EPWM3, &epwm3ISR);
    
        //
        // Disable sync(Freeze clock to PWM as well)
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // Initialize PWM1 without phase shift as master
        initEPWM1();
    
        // Initialize PWM2 with phase shift of X
        initEPWM2();
        //EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
        //EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
       // EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        initEPWM3();
    
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    
        //
        // ePWM2 uses the ePWM 1 SYNCO as its SYNCIN.
        // ePWM2 SYNCO is generated from its SYNCIN, which is ePWM1 SYNCO
        //
        EPWM_setSyncOutPulseMode(myEPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
    
        //
        // ePWM4 uses the ePWM 1 SYNCO as its SYNCIN.
        //
        //SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM4, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT);
        //
        // Enable all phase shifts.
        //
        EPWM_enablePhaseShiftLoad(myEPWM2_BASE);
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Enable interrupts required for this example
        //
        Interrupt_enable(INT_EPWM1);
        Interrupt_enable(INT_EPWM2);
        Interrupt_enable(INT_EPWM3);
    
        //
        // Enable global Interrupts and higher priority real-time debug events:
        //
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
        //
        // IDLE loop. Just sit and loop forever (optional):
        //
        for(;;)
        {
            asm ("  NOP");
        }
    }
    
    //
    // epwm1ISR - EPWM1 ISR to update compare values
    //
    __interrupt void epwm1ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        updateCompare(&epwm1Info);
    
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // epwm2ISR - EPWM2 ISR to update compare values
    //
    __interrupt void epwm2ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        if (loop_counter!=AshikFlag)
        {
        updateCompare(&epwm2Info);
        }
        else
        {
    
            //Ph=300;
            EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
            EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
            EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        }
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // epwm3ISR - EPWM3 ISR to update compare values
    //
    __interrupt void epwm3ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        updateCompare(&epwm3Info);
    
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM3_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // initEPWM1 - Initialize EPWM1 values
    //
    void initEPWM1()
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM1_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM1_BASE, EPWM1_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM1_BASE);
        EPWM_setPhaseShift(myEPWM1_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM1_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM1_BASE,
                               EPWM_CLOCK_DIVIDER_2,
                               EPWM_HSCLOCK_DIVIDER_2);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM1_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM1_MIN_CMPB);
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Set PWM1A on Zero
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        // Clear PWM1A on event A, up count
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Set PWM1B on Zero
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        // Clear PWM1B on event B, up count
        EPWM_setActionQualifierAction(myEPWM1_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    //    // Set PWM1B on Zero
    //    EPWM_setActionQualifierAction(myEPWM1_BASE,
    //                                  EPWM_AQ_OUTPUT_B,
    //                                  EPWM_AQ_OUTPUT_HIGH,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    //    // Clear PWM1B on event B, up count
    //    EPWM_setActionQualifierAction(myEPWM1_BASE,
    //                                  EPWM_AQ_OUTPUT_B,
    //                                  EPWM_AQ_OUTPUT_LOW,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM1_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM1_BASE);
        EPWM_setInterruptEventCount(myEPWM1_BASE, 3U);
    
       //
       // Information this example uses to keep track
       // of the direction the CMPA/CMPB values are
       // moving, the min and max allowed values and
       // a pointer to the correct ePWM registers
       //
    
        // Start by increasing CMPA & CMPB
        epwm1Info.epwmCompADirection = EPWM_CMP_UP;
        epwm1Info.epwmCompBDirection = EPWM_CMP_UP;
    
        // Clear interrupt counter
        epwm1Info.epwmTimerIntCount = 0;
        epwm1Info.ePWMDone = 0;
    
        // Set base as ePWM1
        epwm1Info.epwmModule = myEPWM1_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm1Info.epwmMaxCompA = EPWM1_MAX_CMPA;
        epwm1Info.epwmMinCompA = EPWM1_MIN_CMPA;
        epwm1Info.epwmMaxCompB = EPWM1_MAX_CMPB;
        epwm1Info.epwmMinCompB = EPWM1_MIN_CMPB;
    }
    
    //
    // initEPWM2 - Initialize EPWM2 values
    //
    void initEPWM2()
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM2_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM2_BASE, EPWM2_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM2_BASE);
        EPWM_setPhaseShift(myEPWM2_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM2_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM2_BASE,
                               EPWM_CLOCK_DIVIDER_2,
                               EPWM_HSCLOCK_DIVIDER_2);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM2_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM2_MIN_CMPB); //EPWM2_MAX_CMPB
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Clear PWM2A on period and set on event A, up-count
    //    EPWM_setActionQualifierAction(myEPWM2_BASE,
    //                                  EPWM_AQ_OUTPUT_A,
    //                                  EPWM_AQ_OUTPUT_LOW,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    //    EPWM_setActionQualifierAction(myEPWM2_BASE,
    //                                  EPWM_AQ_OUTPUT_A,
    //                                  EPWM_AQ_OUTPUT_HIGH,
    //                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Clear PWM2A on period and set on event A, up-count
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        // Clear PWM2B on Period & set on event B, up-count
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
        EPWM_setActionQualifierAction(myEPWM2_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM2_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM2_BASE);
        EPWM_setInterruptEventCount(myEPWM2_BASE, 3U);
    
        //
        // Information this example uses to keep track
        // of the direction the CMPA/CMPB values are
        // moving, the min and max allowed values and
        // a pointer to the correct ePWM registers
        //
    
        // Start by increasing CMPA & decreasing CMPB
        epwm2Info.epwmCompADirection = EPWM_CMP_UP;
        epwm2Info.epwmCompBDirection = EPWM_CMP_DOWN;
    
        // Clear interrupt counter
        epwm2Info.epwmTimerIntCount = 0;
    
        // Set base as ePWM2
        epwm2Info.epwmModule = myEPWM2_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm2Info.epwmMaxCompA = EPWM2_MAX_CMPA;
        epwm2Info.epwmMinCompA = EPWM2_MIN_CMPA;
        epwm2Info.epwmMaxCompB = EPWM2_MAX_CMPB;
        epwm2Info.epwmMinCompB = EPWM2_MIN_CMPB;
    }
    
    //
    // initEPWM3 - Initialize EPWM3 values
    //
    void initEPWM3(void)
    {
        //
        // Setup TBCLK
        //
        EPWM_setTimeBaseCounterMode(myEPWM3_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(myEPWM3_BASE, EPWM3_TIMER_TBPRD);
        EPWM_disablePhaseShiftLoad(myEPWM3_BASE);
        EPWM_setPhaseShift(myEPWM3_BASE, 0U);
        EPWM_setTimeBaseCounter(myEPWM3_BASE, 0U);
    
        //
        // Set ePWM clock pre-scaler
        //
        EPWM_setClockPrescaler(myEPWM3_BASE,
                               EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Setup shadow register load on ZERO
        //
        EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                    EPWM3_MIN_CMPA);
        EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_B,
                                    EPWM3_MAX_CMPB);
    
        //
        // Set actions for ePWM1A & ePWM1B
        //
        // Set PWM3A on event B, up-count & clear on event B, up-count
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
        // Toggle EPWM3B on counter = zero
        EPWM_setActionQualifierAction(myEPWM3_BASE,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_TOGGLE,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        //
        // Interrupt where we will change the Compare Values
        //
        EPWM_setInterruptSource(myEPWM3_BASE, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(myEPWM3_BASE);
        EPWM_setInterruptEventCount(myEPWM3_BASE, 3U);
    
       //
       // Information this example uses to keep track
       // of the direction the CMPA/CMPB values are
       // moving, the min and max allowed values and
       // a pointer to the correct ePWM registers
       //
    
        // Start by increasing CMPA & decreasing CMPB
        epwm3Info.epwmCompADirection = EPWM_CMP_UP;
        epwm3Info.epwmCompBDirection = EPWM_CMP_UP;
    
        // Start the count at 0
        epwm3Info.epwmTimerIntCount = 0;
    
        // Set base as ePWM1
        epwm3Info.epwmModule = myEPWM3_BASE;
    
        // Setup min/max CMPA/CMP values
        epwm3Info.epwmMaxCompA = EPWM3_MAX_CMPA;
        epwm3Info.epwmMinCompA = EPWM3_MIN_CMPA;
        epwm3Info.epwmMaxCompB = EPWM3_MAX_CMPB;
        epwm3Info.epwmMinCompB = EPWM3_MIN_CMPB;
    }
    
    //
    // updateCompare - Update the compare values for the specified EPWM
    //
    void updateCompare(epwmInfo *epwm_info)
    {
       //
       // Every 10'th interrupt, change the CMPA/CMPB values
       //
       if(epwm_info->epwmTimerIntCount == 10)
       {
           epwm_info->epwmTimerIntCount = 0;
           compAVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                                  EPWM_COUNTER_COMPARE_A);
           compBVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                                  EPWM_COUNTER_COMPARE_B);
    //       if (compAVal==epwm_info->epwmMaxCompA) {epwm1Info.ePWMDone = 1;}
           //
           // If we were increasing CMPA, check to see if
           // we reached the max value.  If not, increase CMPA
           // else, change directions and decrease CMPA
           //
           if(epwm_info->epwmCompADirection == EPWM_CMP_UP)
           {
               if(compAVal < epwm_info->epwmMaxCompA)
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, ++compAVal);
                   AshikFlag = AshikFlag+1;
               }
               else
               {
    //               epwm_info->epwmCompADirection = EPWM_CMP_DOWN;
    //               EPWM_setCounterCompareValue(epwm_info->epwmModule,
    //                                           EPWM_COUNTER_COMPARE_A, --compAVal);
    //               epwm1Info.ePWMDone = 1;
    
               }
    
           }
    
           //
           // If we were decreasing CMPA, check to see if
           // we reached the min value.  If not, decrease CMPA
           // else, change directions and increase CMPA
           //
           else
           {
               if(compAVal == epwm_info->epwmMinCompA)
               {
                   epwm_info->epwmCompADirection = EPWM_CMP_UP;
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, ++compAVal);
    
               }
               else
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_A, --compAVal);
               }
           }
    
           //
           // If we were increasing CMPB, check to see if
           // we reached the max value.  If not, increase CMPB
           // else, change directions and decrease CMPB
           //
           if(epwm_info->epwmCompBDirection == EPWM_CMP_UP)
           {
               if(compBVal < epwm_info->epwmMaxCompB)
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, ++compBVal);
               }
               else
               {
    //               epwm_info->epwmCompBDirection = EPWM_CMP_DOWN;
    //               EPWM_setCounterCompareValue(epwm_info->epwmModule,
    //                                           EPWM_COUNTER_COMPARE_B, --compBVal);
    
               }
           }
    
           //
           // If we were decreasing CMPB, check to see if
           // we reached the min value.  If not, decrease CMPB
           // else, change directions and increase CMPB
           //
           else
           {
               if(compBVal == epwm_info->epwmMinCompB)
               {
                   epwm_info->epwmCompBDirection = EPWM_CMP_UP;
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, ++compBVal);
               }
               else
               {
                   EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                               EPWM_COUNTER_COMPARE_B, --compBVal);
               }
           }
       }
    
       //
       // Increment interrupt count if < 10
       //
       else
       {
          epwm_info->epwmTimerIntCount++;
       }
    
       return;
    
    }
    //
    // End of file
    //

    Hi Aditya,

    I have now a PWM frequency of 250 kHz. But when I make the AshikFlag and loop_counter==150; the EPWM2 becomes unstable. I can change the phase but it the PWM is unstable. Any insight on this can be helpful.

    Ashik

  • Can you let me know apart from changing the TBPRD value, how can I change the switching frequency? Currently the EPWM_Timer_TBPRD value is 2000 and it gives 12.5 kHz. I want 100 kHz switching frequency.

    1. You can change your TBPRD to get the desired switching frequency. In your case, I believe the required value as per the current config would be 250.

    2. You can choose to update the HSPCLKDIV and CLKDIV bits incase it is not currently the max value, i.e. if it is not already /1

    Thanks,

    Aditya