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: Is there any relevant code of HRPWM application in TMS320F280049C?

Part Number: TMS320F280049C
Other Parts Discussed in Thread: TMS320F280049, C2000WARE

Hello All,

I am trying to apply HRPWM in my example code epwm_ex13_up_aq.c for TMS320F280049.

I have added the sample code here for your reference

//###########################################################################
//
// 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
uint16_t Per = 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 Ashik,

    The HRPWM examples are located driverlib/[DEVICE]/examples/hrpwm in C2000Ware. Apologies if you had trouble locating these.

    Let me know if you have issues understanding these examples.

    Thank you,

    Luke

  • Hi Luke,

    Thanks for your reply.

    For HRPWM I am using a template quote hrpwm_ex1_duty_sfo.c. 

    I am pretty new with HRPWM. My objective is to have PWM1 and PWM2 to start from zero and stop at 50% duty cycle. I am not considering PWM 3 and 4 now.

    After attaining 50% duty cycle PWM1 and PWM2 should get a phase shift of 10 degree. 

    I am facing problems to keep the duty cycle fix at 50%. In the existing code (attached) after reaching 50% it again goes to initial value.

    Can you suggest a smarter way to apply the phase shift in hrpwm_ex1_duty_sfo.c?

    //#############################################################################
    //
    // FILE:   hrpwm_ex1_duty_sfo.c
    //
    // TITLE:  HRPWM Duty Control with SFO.
    //
    //! \addtogroup driver_example_list
    //! <h1>HRPWM Duty Control with SFO</h1>
    //!
    //! This example modifies the MEP control registers to show edge displacement
    //! for high-resolution period with ePWM in Up count mode
    //! due to the HRPWM control extension of the respective ePWM module.
    //!
    //! This example calls the following TI's MEP Scale Factor Optimizer (SFO)
    //! software library V8 functions:
    //!
    //! \b int \b SFO(); \n
    //! - updates MEP_ScaleFactor dynamically when HRPWM is in use
    //! - updates HRMSTEP register (exists only in EPwm1Regs register space)
    //! with MEP_ScaleFactor value
    //! - returns 2 if error: MEP_ScaleFactor is greater than maximum value of 255
    //!   (Auto-conversion may not function properly under this condition)
    //! - returns 1 when complete for the specified channel
    //! - returns 0 if not complete for the specified channel
    //!
    //! This example is intended to explain the HRPWM capabilities. The code can be
    //! optimized for code efficiency. Refer to TI's Digital power application
    //! examples and TI Digital Power Supply software libraries for details.
    //!
    //! \b External \b Connections \n
    //!  - Monitor ePWM1/2/3/4 A/B pins on 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"
    #include "SFO_V8.h"
    
    #define EPWM_TIMER_TBPRD            100UL
    #define MIN_HRPWM_DUTY_PERCENT      4.0/((float32_t)EPWM_TIMER_TBPRD)*100.0
    //
    // Defines
    //
    #define LAST_EPWM_INDEX_FOR_EXAMPLE    5
    
    //
    // Globals
    //
    
    float32_t dutyFine = MIN_HRPWM_DUTY_PERCENT;
    uint16_t status;
    
    int MEP_ScaleFactor; // Global variable used by the SFO library
                         // Result can be used for all HRPWM channels
                         // This variable is also copied to HRMSTEP
                         // register by SFO() function.
    
    volatile uint32_t ePWM[] =
        {0, myEPWM1_BASE, myEPWM2_BASE, myEPWM3_BASE, myEPWM4_BASE};
    //
    // Function Prototypes
    //
    void initHRPWM(uint32_t period);
    void error(void);
    //__interrupt void epwm1ISR(void);
    //__interrupt void epwm2ISR(void);
    //__interrupt void epwm3ISR(void);
    //__interrupt void epwm4ISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        uint16_t i = 0;
    
        //
        // 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();
    
        //
        // Assign the interrupt service routines to ePWM interrupts
        //
        //Interrupt_register(INT_EPWM1, &epwm1ISR);
        //Interrupt_register(INT_EPWM2, &epwm2ISR);
        //Interrupt_register(INT_EPWM3, &epwm3ISR);
        //Interrupt_register(INT_EPWM4, &epwm4ISR);
    
        //
        // Initialize the EPWM GPIO Pins and change the XBAR inputs from using GPIO0
        //
        Board_init();
    
    
        //
        // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
        // HRMSTEP must be populated with a scale factor value prior to enabling
        // high resolution period control.
        //
        while(status == SFO_INCOMPLETE)
        {
            status = SFO();
            if(status == SFO_ERROR)
            {
                error();   // SFO function returns 2 if an error occurs & # of MEP
            }              // steps/coarse step exceeds maximum of 255.
        }
    
    
    
        //
        // Disable sync(Freeze clock to PWM as well)
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        initHRPWM(EPWM_TIMER_TBPRD);
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
    
        // Enable ePWM interrupts
        //
        //Interrupt_enable(INT_EPWM1);
        //Interrupt_enable(INT_EPWM2);
        //Interrupt_enable(INT_EPWM3);
        //Interrupt_enable(INT_EPWM4);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
    
        for(;;)
        {
             //
             // Sweep DutyFine
             //
             for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 50; dutyFine += 0.01)  //dutyFine < 99.9
             {
                 DEVICE_DELAY_US(1000);
                 for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
                 {
                     float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
                     uint32_t compCount = (count);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
                 }
    
                 //
                 // Call the scale factor optimizer lib function SFO()
                 // periodically to track for any change due to temp/voltage.
                 // This function generates MEP_ScaleFactor by running the
                 // MEP calibration module in the HRPWM logic. This scale
                 // factor can be used for all HRPWM channels. The SFO()
                 // function also updates the HRMSTEP register with the
                 // scale factor value.
                 //
                 status = SFO(); // in background, MEP calibration module
                                 // continuously updates MEP_ScaleFactor
    
                 if (status == SFO_ERROR)
                 {
                     error();   // SFO function returns 2 if an error occurs & #
                                // of MEP steps/coarse step
                 }              // exceeds maximum of 255.
             }
         }
    }
    
    //
    // epwm1ISR - ePWM 1 ISR
    //
    //__interrupt void epwm1ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm2ISR - ePWM 2 ISR
    //
    //__interrupt void epwm2ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm3ISR - ePWM 3 ISR
    //
    //__interrupt void epwm3ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm4ISR - ePWM 4 ISR
    //
    //__interrupt void epwm4ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM4_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    
    
    void initHRPWM(uint32_t period)
    {
    
        uint16_t j;
    
        //
        // ePWM channel register configuration with HRPWM
        // ePWMxA / ePWMxB toggle low/high with MEP control on Rising edge
        //
        for (j=1;j<LAST_EPWM_INDEX_FOR_EXAMPLE;j++)
        {
            EPWM_setEmulationMode(ePWM[j], EPWM_EMULATION_FREE_RUN);
    
            //
            // Set-up TBCLK
            //
            EPWM_setTimeBasePeriod(ePWM[j], period-1);
            EPWM_setPhaseShift(ePWM[j], 0U);
            EPWM_setTimeBaseCounter(ePWM[j], 0U);
    
            //
            // set duty 50% initially
            //
            HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_A, (period/2 << 8));
            HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_B, (period/2 << 8));
    
    
            //
            // Set up counter mode
            //
            EPWM_setTimeBaseCounterMode(ePWM[j], EPWM_COUNTER_MODE_UP);
            EPWM_disablePhaseShiftLoad(ePWM[j]);
            EPWM_setClockPrescaler(ePWM[j],
                                   EPWM_CLOCK_DIVIDER_1,
                                   EPWM_HSCLOCK_DIVIDER_1);
            EPWM_setSyncOutPulseMode(ePWM[j], EPWM_SYNC_OUT_PULSE_DISABLED);
    
            //
            // Set up shadowing
            //
            EPWM_setCounterCompareShadowLoadMode(ePWM[j],
                                                 EPWM_COUNTER_COMPARE_A,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
            EPWM_setCounterCompareShadowLoadMode(ePWM[j],
                                                 EPWM_COUNTER_COMPARE_B,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
            //
            // Set actions
            //
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_HIGH,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_A,  //EPWM_AQ_OUTPUT_B,
                                          EPWM_AQ_OUTPUT_LOW, //EPWM_AQ_OUTPUT_HIGH
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);// EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_B,  // EPWM_AQ_OUTPUT_A
                                          EPWM_AQ_OUTPUT_LOW,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); //EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_B,
                                          EPWM_AQ_OUTPUT_HIGH,//EPWM_AQ_OUTPUT_LOW
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    
            HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE);
            HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL);
            HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO);
    
            HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE);
            HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL);
            HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO);
    
            HRPWM_enableAutoConversion(ePWM[j]);
    
            //
            // Turn off high-resolution period control.
            //
    
            HRPWM_disablePeriodControl(ePWM[j]);
            HRPWM_disablePhaseShiftLoad(ePWM[j]);
    
    
            //
            // Interrupt where we will change the Compare Values
            // Select INT on Time base counter zero event,
            // Enable INT, generate INT on 1st event
            //
            //EPWM_setInterruptSource(ePWM[j], EPWM_INT_TBCTR_ZERO);
            //EPWM_enableInterrupt(ePWM[j]);
            //EPWM_setInterruptEventCount(ePWM[j], 1U);
        }
    
    }
    
    //
    // error - Halt debugger when called
    //
    void error (void)
    {
        ESTOP0;         // Stop here and handle error
    }
    
    

    Ashik 

  • I tried using EPWM_EMULATION_STOP_AFTER_FULL_CYCLE in EPWM_setEmulationMode.

    But it seems not working. The PWM changes back and forth from minimum to 50%.

  • Hi Luke,

    Hope you are doing fine.

    Is there any suggestion for above issue?

    Ashik

  • Hi Ashik,

    Apologies for the delayed response, I will provide you an update by the end of the day.

    Thank you,

    Luke

  • Hi Ashik, EPWM_EMULATION_STOP_AFTER_FULL_CYCLE in EPWM_setEmulationMode just determines the behavior of the EPWM when the debugger halts the CPU.

    What exactly do you mean by PWM changes back and forth between 50% and the minimum? Is the minimum 0%? Could you send a scope shot of what this looks like?

    Thank you,

    Luke

  • Minimum PWM is probably 4%. I meant that it starts from a minimum (4%) then goes to 50% and again reduces to 4% and it repeats. But I want to stop the repetition after it attains 50% duty cycle. 

    My objective is to start the PWM with a minimum duty cycle and reach maximum 50% slowly and after attaining the 50% duty cycle PWM2 get a 10 degree shift from PWM1. 

    I can send you a scope snapshot tomorrow.

    Ashik

  • Good morning Luke,

    Hope you are doing alright. I have uploaded a short video to make you understand.

    Click here to play this video

    Below is a snapshot when the PWM is 50% duty. (It is PWM1 and PWM2).

    Below is a snapshot when the PWM is minimum duty. (It is PWM1 and PWM2).

    Thanks for your consideration.

    Ashik

  • Ashik,

    Apologies, but the video you sent doesn't seem to be working on my side.

    In your code, you have a for loop inside of a while loop. When the for loop completes, it will restart because it is inside of a while loop. I suspect this is causing your duty cycle to reset to the minimum after it reaches 50%.

    Your code contains the following snippet:

    for(;;)
        {
             //
             // Sweep DutyFine
             //
             for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 50; dutyFine += 0.01)  //dutyFine < 99.9
             {
                 DEVICE_DELAY_US(1000);
                 for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
                 {
                     float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
                     uint32_t compCount = (count);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
                 }
    
                 //
                 // Call the scale factor optimizer lib function SFO()
                 // periodically to track for any change due to temp/voltage.
                 // This function generates MEP_ScaleFactor by running the
                 // MEP calibration module in the HRPWM logic. This scale
                 // factor can be used for all HRPWM channels. The SFO()
                 // function also updates the HRMSTEP register with the
                 // scale factor value.
                 //
                 status = SFO(); // in background, MEP calibration module
                                 // continuously updates MEP_ScaleFactor
    
                 if (status == SFO_ERROR)
                 {
                     error();   // SFO function returns 2 if an error occurs & #
                                // of MEP steps/coarse step
                 }              // exceeds maximum of 255.
             }
         }

    But to meet your use-case where the duty cycle stays stuck at 50%, the while loop should come AFTER the for-loop, like this:

     //
     // Sweep DutyFine
     //
     for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 50; dutyFine += 0.01)  //dutyFine < 99.9
     {
         DEVICE_DELAY_US(1000);
         for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
         {
             float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
             uint32_t compCount = (count);
             HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
             HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
         }
    
         //
         // Call the scale factor optimizer lib function SFO()
         // periodically to track for any change due to temp/voltage.
         // This function generates MEP_ScaleFactor by running the
         // MEP calibration module in the HRPWM logic. This scale
         // factor can be used for all HRPWM channels. The SFO()
         // function also updates the HRMSTEP register with the
         // scale factor value.
         //
         status = SFO(); // in background, MEP calibration module
                         // continuously updates MEP_ScaleFactor
    
         if (status == SFO_ERROR)
         {
             error();   // SFO function returns 2 if an error occurs & #
                        // of MEP steps/coarse step
         }              // exceeds maximum of 255.
     }
         
    for(;;){}

    Let me know if this is actually the issue.

    Thank you,

    Luke

  • Great!!! Luke,

    It worked.... Now the PWM stops at 50%.

    Le me try the phase shift now.

    Thanks again.

    Ashik

  • Hi Luke,

    Now I am trying to give phase shift after the PWM stops at 50% duty cycle. I have added another for loop to that will apply only to PWM2 and rest.

    But  it seems not working. Do you have any suggestion for this how to proceed?

    Thank you.

    Ashik

    //
             // Sweep DutyFine
             //
             for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 50; dutyFine += 0.01)  //dutyFine < 99.9
             {
                 DEVICE_DELAY_US(1000);
                 for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
                 {
                     float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
                     uint32_t compCount = (count);
                     //uint32_t compCount = 1;
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
                 }
                 //Add Phase
                 for(k=2; i<LAST_EPWM_INDEX_FOR_EXAMPLE; k++)
                  {
                      EPWM_selectPeriodLoadEvent(ePWM[k], EPWM_SHADOW_LOAD_MODE_SYNC);
                      EPWM_setPhaseShift(ePWM[k], 50UL);
                  }
    
    
                 //
                 // Call the scale factor optimizer lib function SFO()
                 // periodically to track for any change due to temp/voltage.
                 // This function generates MEP_ScaleFactor by running the
                 // MEP calibration module in the HRPWM logic. This scale
                 // factor can be used for all HRPWM channels. The SFO()
                 // function also updates the HRMSTEP register with the
                 // scale factor value.
                 //
                 status = SFO(); // in background, MEP calibration module
                                 // continuously updates MEP_ScaleFactor
    
                 if (status == SFO_ERROR)
                 {
                     error();   // SFO function returns 2 if an error occurs & #
                                // of MEP steps/coarse step
                 }              // exceeds maximum of 255.
             }
         //} //Ashik Disabled
    
             for(;;){} // Ashik Added
     

  • Ashik,

    You have this code:

    for(k=2; i<LAST_EPWM_INDEX_FOR_EXAMPLE; k++)

    Should this change to:

    'for(k=2; k<LAST_EPWM_INDEX_FOR_EXAMPLE; k++)

    I swapped the i with a k

  • Thanks Luke, for pointing this out.

    I have changed the k to i. But it seems not shifting the PWM yet.

    Fo your convenience I have uploaded the whole code again. The void initHRPWM(uint32_t period) function contains all the HRPWM information. I am not sure if i need to change it here or not. This function is called before the for loop we are discussing in earlier reply. So the PWM duty change is happening after calling the function initHRPWM(uint32_t period). So in my understanding the PWM phase change should also be done after sweeping the duty cycle.

    For your information, all the interrupt registers and interrupt enable functions are commented out as they are not used so far.

    Your suggestions will be appreciated.

    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    #include "SFO_V8.h"
    
    #define EPWM_TIMER_TBPRD            100UL
    #define MIN_HRPWM_DUTY_PERCENT      1.0/((float32_t)EPWM_TIMER_TBPRD)*100.0 //4.0/((float32_t)EPWM_TIMER_TBPRD)*100.0
    //
    // Defines
    //
    #define LAST_EPWM_INDEX_FOR_EXAMPLE    5
    
    //
    // Globals
    //
    
    float32_t dutyFine = MIN_HRPWM_DUTY_PERCENT;
    uint16_t status;
    
    int MEP_ScaleFactor; // Global variable used by the SFO library
                         // Result can be used for all HRPWM channels
                         // This variable is also copied to HRMSTEP
                         // register by SFO() function.
    
    volatile uint32_t ePWM[] =
        {0, myEPWM1_BASE, myEPWM2_BASE, myEPWM3_BASE, myEPWM4_BASE};
    //
    // Function Prototypes
    //
    void initHRPWM(uint32_t period);
    void error(void);
    //__interrupt void epwm1ISR(void);
    //__interrupt void epwm2ISR(void);
    //__interrupt void epwm3ISR(void);
    //__interrupt void epwm4ISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        uint16_t i = 0;
        uint16_t k = 0; //Ashik Added
    
        //
        // 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();
    
        //
        // Assign the interrupt service routines to ePWM interrupts
        //
        //Interrupt_register(INT_EPWM1, &epwm1ISR);
        //Interrupt_register(INT_EPWM2, &epwm2ISR);
        //Interrupt_register(INT_EPWM3, &epwm3ISR);
        //Interrupt_register(INT_EPWM4, &epwm4ISR);
    
        //
        // Initialize the EPWM GPIO Pins and change the XBAR inputs from using GPIO0
        //
        Board_init();
    
    
        //
        // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
        // HRMSTEP must be populated with a scale factor value prior to enabling
        // high resolution period control.
        //
        while(status == SFO_INCOMPLETE)
        {
            status = SFO();
            if(status == SFO_ERROR)
            {
                error();   // SFO function returns 2 if an error occurs & # of MEP
            }              // steps/coarse step exceeds maximum of 255.
        }
    
    
    
        //
        // Disable sync(Freeze clock to PWM as well)
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        initHRPWM(EPWM_TIMER_TBPRD);
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
    
        // Enable ePWM interrupts
        //
        //Interrupt_enable(INT_EPWM1);
        //Interrupt_enable(INT_EPWM2);
        //Interrupt_enable(INT_EPWM3);
        //Interrupt_enable(INT_EPWM4);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
    
        //for(;;) //Ashik Disabled
        //{ //Ashik Disabled
             //
             // Sweep DutyFine
             //
             for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 50; dutyFine += 0.01)  //dutyFine < 99.9
             {
                 DEVICE_DELAY_US(1000);
                 for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
                 {
                     float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
                     uint32_t compCount = (count);
                     //uint32_t compCount = 1;
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
                 }
                 //Add Phase
                 for(k=2; k<LAST_EPWM_INDEX_FOR_EXAMPLE; k++)
                  {
                      EPWM_selectPeriodLoadEvent(ePWM[k], EPWM_SHADOW_LOAD_MODE_SYNC);
                      EPWM_setPhaseShift(ePWM[k], 50UL);
                  }
    
    
                 //
                 // Call the scale factor optimizer lib function SFO()
                 // periodically to track for any change due to temp/voltage.
                 // This function generates MEP_ScaleFactor by running the
                 // MEP calibration module in the HRPWM logic. This scale
                 // factor can be used for all HRPWM channels. The SFO()
                 // function also updates the HRMSTEP register with the
                 // scale factor value.
                 //
                 status = SFO(); // in background, MEP calibration module
                                 // continuously updates MEP_ScaleFactor
    
                 if (status == SFO_ERROR)
                 {
                     error();   // SFO function returns 2 if an error occurs & #
                                // of MEP steps/coarse step
                 }              // exceeds maximum of 255.
             }
         //} //Ashik Disabled
    
             for(;;){} // Ashik Added
    }
    
    //
    // epwm1ISR - ePWM 1 ISR
    //
    //__interrupt void epwm1ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm2ISR - ePWM 2 ISR
    //
    //__interrupt void epwm2ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm3ISR - ePWM 3 ISR
    //
    //__interrupt void epwm3ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    //
    // epwm4ISR - ePWM 4 ISR
    //
    //__interrupt void epwm4ISR(void)
    //{
    //    EPWM_clearEventTriggerInterruptFlag(EPWM4_BASE);
    //    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    //}
    
    
    
    void initHRPWM(uint32_t period)
    {
    
        uint16_t j;
    
        //
        // ePWM channel register configuration with HRPWM
        // ePWMxA / ePWMxB toggle low/high with MEP control on Rising edge
        //
        for (j=1;j<LAST_EPWM_INDEX_FOR_EXAMPLE;j++)
        {
            EPWM_setEmulationMode(ePWM[j], EPWM_EMULATION_FREE_RUN); //EPWM_EMULATION_FREE_RUN
    
            //
            // Set-up TBCLK
            //
            EPWM_setTimeBasePeriod(ePWM[j], period-1);
            EPWM_setPhaseShift(ePWM[j], 0U);
            EPWM_setTimeBaseCounter(ePWM[j], 0U);
    
            //
            // set duty 50% initially
            //
            HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_A, (period/2 << 8));
            HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_B, (period/2 << 8));
    
    
            //
            // Set up counter mode
            //
            EPWM_setTimeBaseCounterMode(ePWM[j], EPWM_COUNTER_MODE_UP);
            EPWM_disablePhaseShiftLoad(ePWM[j]);
            EPWM_setClockPrescaler(ePWM[j],
                                   EPWM_CLOCK_DIVIDER_1,
                                   EPWM_HSCLOCK_DIVIDER_1);
            EPWM_setSyncOutPulseMode(ePWM[j], EPWM_SYNC_OUT_PULSE_DISABLED);
    
            //
            // Set up shadowing
            //
            EPWM_setCounterCompareShadowLoadMode(ePWM[j],
                                                 EPWM_COUNTER_COMPARE_A,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
            EPWM_setCounterCompareShadowLoadMode(ePWM[j],
                                                 EPWM_COUNTER_COMPARE_B,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
            //
            // Set actions
            //
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_HIGH,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_A,  //EPWM_AQ_OUTPUT_B,
                                          EPWM_AQ_OUTPUT_LOW, //EPWM_AQ_OUTPUT_HIGH
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);// EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO
    
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_B,  // EPWM_AQ_OUTPUT_A
                                          EPWM_AQ_OUTPUT_LOW,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); //EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA
            EPWM_setActionQualifierAction(ePWM[j],
                                          EPWM_AQ_OUTPUT_B,
                                          EPWM_AQ_OUTPUT_HIGH,//EPWM_AQ_OUTPUT_LOW
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    
            HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE);
            HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL);
            HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO);
    
            HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE);
            HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL);
            HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO);
    
            HRPWM_enableAutoConversion(ePWM[j]);
    
            //
            // Turn off high-resolution period control.
            //
    
            HRPWM_disablePeriodControl(ePWM[j]);
            HRPWM_disablePhaseShiftLoad(ePWM[j]);
    
    
            //
            // Interrupt where we will change the Compare Values
            // Select INT on Time base counter zero event,
            // Enable INT, generate INT on 1st event
            //
            //EPWM_setInterruptSource(ePWM[j], EPWM_INT_TBCTR_ZERO);
            //EPWM_enableInterrupt(ePWM[j]);
            //EPWM_setInterruptEventCount(ePWM[j], 1U);
        }
    
    }
    
    //
    // error - Halt debugger when called
    //
    void error (void)
    {
        ESTOP0;         // Stop here and handle error
    }
    
     

    Ashik

  • Hi Luke,

    Thanks for helping me out.

    If you have any suggestion regarding this you can let me know.

    Ashik

  • Hello Luke,

    Any help on this will be appriceiated.

    Ashik

  • Hi Ashik,

    Apologies for the delayed response.

    Are you enabling PHSEN in your EPWM by using the EPWM_enablePhaseShiftLoad function? I don't see this in your code.

    PHSEN must be set to 1 for a phase shift to take effect when a sync pulse is generated.

    Thank you,

    Luke

  • Hello Luke,

    Thanks for your reply.

    I have enabled the EPWM_enablePhaseShiftLoad function before initiating the loop regarding phase shift.

    It seems have no effect.

    Any suggestion will be appreciated.

                 for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
                 {
                     float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
                     uint32_t compCount = (count);
                     //uint32_t compCount = 1;
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount);
                     HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount);
                 }
                 //Add Phase
                 EPWM_enablePhaseShiftLoad(ePWM[i]);//Ashik Added
    
                 for(k=2; k<LAST_EPWM_INDEX_FOR_EXAMPLE; k++)
                  {
                      EPWM_selectPeriodLoadEvent(ePWM[k], EPWM_SHADOW_LOAD_MODE_SYNC);
                      EPWM_setPhaseShift(ePWM[k], 50UL);
                  }
    

  • Ashik,

    Can you confirm whether this same application code was working correctly before you implemented HRPWM support? It will be difficult to check your entire code to find a potential mistake.

    If this code was working before implementing HRPWM, and you can identify the code changes that you made to incorporate HRPWM support that will make it easier to identify the problem in your code.

    Thank you,

    Luke