This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: HRPWM frequency and duty cycle issue

Part Number: TMS320F28379D


if want to generate HRPWM of 20khz or any frequency I want...with duty cycle for example 25% the what should I do in below code to do so?

#include "driverlib.h"
#include "device.h"
#include "sfo_v8.h"
//
// Defines
//
// # of PWM channels
#define PWM_CH            2
#define STATUS_SUCCESS    1
#define STATUS_FAIL       0
//
// Globals
//
uint16_t updateFine, periodFine, status;
//
// 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(0) function.
//
int MEP_ScaleFactor = 0;
//
// Used by SFO library (ePWM[0] is a dummy value that isn't used)
//
volatile uint32_t ePWM[(PWM_CH + 1)] = {0, EPWM1_BASE, EPWM2_BASE};
//
// Function Prototypes
//
void error(void);
void initEPWM1GPIO(void);
void initEPWM2GPIO(void);
void initEPWMModule(uint32_t base, uint32_t period);
void initHRPWMModule(uint32_t base, uint32_t period);
//
// Main
//
void main(void)
{
    uint16_t i;
    uint32_t base;
    //
    // Initialize device clock and peripherals
    //
    Device_init();
    //
    // Disable pin locks and enable internal pull-ups.
    //
    Device_initGPIO();
    //
    // Initialize PIE and clear PIE registers.
    //
    Interrupt_initModule();
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    //
    // Configure ePWM1 and ePWM2 GPIOs
    //
    initEPWM1GPIO();
    initEPWM2GPIO();
    //
    // Setup example variables
    //
    updateFine = 1;
    periodFine = 0;
    status = SFO_INCOMPLETE;
    //
    // 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)
        {
            //
            // SFO function returns 2 if an error occurs & # of MEP
            // steps/coarse step exceeds maximum of 255.
            //
            error();
        }
    }
    //
    // EPWM & HRPWM configurations
    //
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    for(i = 0; i < PWM_CH; i++)
    {
        base = EPWM1_BASE + (i * 0x100U);
        initHRPWMModule(base, 20U);
    }
    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;
    for(;;)
    {
        //
        // Sweep periodFine as a Q16 number from 0.2 - 0.999
        //
        for(periodFine = 0x3333; periodFine < 0xFFBF; periodFine++)
        {
            if(updateFine)
            {
                //
                // Because auto-conversion is enabled, the desired
                // fractional period must be written directly to the
                // TBPRDHR (or TBPRDHRM) register in Q16 format
                // (lower 8-bits are ignored)
                //
                // EPwm1Regs.TBPRDHR = periodFine;
                //
                // The hardware will automatically scale
                // the fractional period by the MEP_ScaleFactor
                // in the HRMSTEP register (which is updated
                // by the SFO calibration software).
                //
                // Hardware conversion:
                // MEP delay movement = ((TBPRDHR(15:0) >> 8) *  HRMSTEP(7:0) +
                //                       0x80) >> 8
                //
                for(i = 0; i < PWM_CH; i++)
                {
                    base = EPWM1_BASE + (i * 0x100U);
                    //
                    // Write fractional period value in Q16 format
                    //
                    HWREGH(base + HRPWM_O_TBPRDHR) = periodFine;
                }
            }
            else
            {
                //
                // No high-resolution movement on TBPRDHR.
                //
                for(i = 0; i < PWM_CH; i++)
                {
                    HWREGH(base + HRPWM_O_TBPRDHR) = 0U;
                }
            }
            //
            // Call the scale factor optimizer lib function SFO(0)
            // 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. HRMSTEP
            // register is automatically updated by the SFO function.
            // In background, MEP calibration module continuously updates
            // MEP_ScaleFactor
            //
            status = SFO();
            if(status == SFO_ERROR)
            {
                //
                // SFO function returns 2 if an error occurs & # of
                // MEP steps/coarse step exceeds maximum of 255.
                //
                error();
            }
        }
    }
}
//
// initHRPWMModule - Configure HRPWM module
//
void initHRPWMModule(uint32_t base, uint32_t period)
{
    //
    // Initialize HRPWM extension
    //
    HWREGH(base + HRPWM_O_CMPA) = (1U << 8U);
    HRPWM_setCounterCompareShadowLoadEvent(base, HRPWM_CHANNEL_A,
                                           HRPWM_LOAD_ON_CNTR_ZERO_PERIOD);
    HWREG(base + HRPWM_O_CMPB) |= (1U << 8U);
    HRPWM_setCounterCompareShadowLoadEvent(base, HRPWM_CHANNEL_B,
                                           HRPWM_LOAD_ON_CNTR_ZERO_PERIOD);
    //
    // Configure MEP edge & control mode for channel A & B. MEP Edge control is
    // on falling edge. Control mode is duty control.
    //
    HRPWM_setMEPEdgeSelect(base, HRPWM_CHANNEL_A,
                           HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
    HRPWM_setMEPControlMode(base, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL);

    HRPWM_setMEPEdgeSelect(base, HRPWM_CHANNEL_B,
                           HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
    HRPWM_setMEPControlMode(base, HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL);
    //
    // Enable auto-conversion logic.
    //
    HRPWM_enableAutoConversion(base);
    //
    // Enable HRPWM phase synchronization on software sync. Required for
    // up-down count HR control.
    //
    HRPWM_enablePhaseShiftLoad(base);
    //
    // Enable high-resolution period control.
    //
    HRPWM_enablePeriodControl(base);
    //
    // Enable TBCLK within EPWM.
    //
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    //
    // Synchronize high resolution phase to start HR period
    //
    EPWM_forceSyncPulse(base);
}

//
// initEPWM1GPIO - Configure ePWM GPIO
//
void initEPWM1GPIO(void)
{
    //
    // Disable pull up on GPIO 0 and GPIO 1 and configure them as PWM1A and
    // PWM1B output respectively.
    //
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_1_EPWM1B);
}
void error (void)
{
    //
    // Stop here and handle error
    //
    ESTOP0;
}
//
// End of file
//
  • Hi,

    This example sweeps the period value i.e update the frequency at each iteration. But as in your case, you need to generate a constant frequency signal of 20 Khz which can be done just as part of initial configuration :

      for(i = 0; i < PWM_CH; i++)
        {
            base = EPWM1_BASE + (i * 0x100U);
            initHRPWMModule(base, 2500U);   // For 20 KHz : (100 Mhz / 20 Khz) / 2 = 2500U
        }

    In order to get the desired duty value, you can just update the CMPA register as (duty * Period) i.e. 0.25 * 2500U = 625U

    If my reply answers your question please click on "This resolved my issue" button located at the bottom of my post.

    Regards

    Himanshu

  • ok .. as you said this example update frequency at each iteration.. so can you point out where and what I do so it can not update frequency at each iteration instead I become constant 

    and next thing the period you got out its for updown mode if I want it in up mode only then what is the step for the period calculation and duty cycle

  • Hi,

    You can probably start with hrpwm_ex2_duty_sfo_v8 example. But again as I also directed you in another recent thread created by you on this same issue https://e2e.ti.com/support/microcontrollers/c2000/f/171/p/834506/3086349#3086349 , you need to first go through the basics of PWM module and its configuration registers  in order to code for any desired frequency and duty.

    Like for an example, I gave the Period value for up-down mode i.e. 2500U and now if you want to operate in up-mode then there is no need of division by 2 hence the value be 5000U. But its very important to note that we are here to just help you with any peripheral debug or to direct you towards useful resources, we can't just code down the entire thing for you.

    Thus again I would advise you to refer device TRM http://www.ti.com/lit/ug/spruhm8h/spruhm8h.pdf in order to gain basic understanding of the peripheral.

    If my reply answers your question please click on "This resolved my issue" button located at the bottom of my post.

    Regards

    Himanshu