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.

TMS320F28377S: HRPWM up-down with dead-time

Part Number: TMS320F28377S

Hallo,

I need to extend already existing ePWM configuration. We have implemented FOC based on 3 ePWMs which are synchronized.

Period and dead-time are set once and never change, CMPAx is used for duty cycle. Output EPWMxB is inverted EPWMxA.

Shadow registers of CMPAx are loaded globally in single shot mode.

Additionally the SOC_A is triggered from PWM2:CMPB. This timing is constant.

The problem:

CAMPHR is properly updated what can be seen in debugger view. Unfortunately, no result is seen in output signal (oscilloscope). It works still as ePWM without HR extension.

As I add HRPWM configuration functions the dead-time seems to disappear. If I remove completely dead-time support then HRPWM works correctly.

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM3);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRPWM); //sourced from ePWM1 clock source

    while  (m_sfo_status == SFO_INCOMPLETE) // Call until complete
    {
        m_sfo_status = SFO();
        if (m_sfo_status == SFO_ERROR)
        {
            ESTOP0;    // SFO function returns 2 if an error occurs and number of MEP steps/coarse step exceeds maximum of 255.
        }
    }

    // Disable sync(Freeze clock to PWM as well)
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    // ePWM1 - master
    GPIO_setPadConfig(145, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_145_EPWM1A); // phase UH
    GPIO_setPadConfig(146, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_146_EPWM1B);
   // ePWM2
    GPIO_setPadConfig(147, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_147_EPWM2A); // phase VH
    GPIO_setPadConfig(148, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_148_EPWM2B);
    // ePWM3
    GPIO_setPadConfig(149, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_149_EPWM3A);
    GPIO_setPadConfig(150, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_150_EPWM3B);

    // master PWM gets no phase shift
    set_ePWM_config( EPWM1_BASE, m_period, 0, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    // slave PWMs get always phase shift 2
    set_ePWM_config( EPWM2_BASE, m_period, 2, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );
    set_ePWM_config( EPWM3_BASE, m_period, 2, deadband_delay_rising_edge_in_ticks, deadband_delay_falling_edge_in_ticks );

    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); // EPWM 1 is master and olny sync generator
    EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave
    EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); // slave

    // ADC trigger offset (EPWM_COUNTER_COMPARE_B)
    EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, ( adc_trigger_pmwcount ));
    EPWM_setADCTriggerSource(EPWM2_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPB);
    EPWM_setADCTriggerEventPrescale(EPWM2_BASE, EPWM_SOC_A, 1);
    EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);
    EPWM_setCounterCompareShadowLoadMode( EPWM2_BASE,
                                          EPWM_COUNTER_COMPARE_B,
                                          EPWM_COMP_LOAD_ON_CNTR_ZERO);

    // Enable global shadow to active load for CMPA registers. See TRM 13.4.7.2 "One-Shot Load Mode"
    EPWM_enableGlobalLoad(EPWM1_BASE);  //GLDCTL[GLD]=1, individual shadowing is ignored
    EPWM_enableGlobalLoadOneShotMode(EPWM1_BASE); // GLDCTL[OSHTMODE] enable one-shot
    EPWM_enableGlobalLoadRegisters(EPWM1_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR); // GLDCFG - register to be shadow-loaded
    EPWM_setGlobalLoadTrigger(EPWM1_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD); //load on CNT_ZERO - GLDCTL[GLDMODE]
    EPWM_setupEPWMLinks(EPWM1_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger (the same value of GLDCTL2) to ePWM1

    EPWM_enableGlobalLoad(EPWM2_BASE);
    EPWM_enableGlobalLoadOneShotMode(EPWM2_BASE);
    EPWM_enableGlobalLoadRegisters(EPWM2_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
    EPWM_setGlobalLoadTrigger(EPWM2_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);
    EPWM_setupEPWMLinks(EPWM2_BASE, EPWM_LINK_WITH_EPWM_3, EPWM_LINK_GLDCTL2); //writing to ePWM3 (one shot trigger) causes writing trigger to ePWM1

    EPWM_enableGlobalLoad(EPWM3_BASE);
    EPWM_enableGlobalLoadOneShotMode(EPWM3_BASE);
    EPWM_enableGlobalLoadRegisters(EPWM3_BASE, EPWM_GL_REGISTER_CMPA_CMPAHR);
    EPWM_setGlobalLoadTrigger(EPWM3_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD);

    // see Technical Reference page 1566: should be enabled after all ePWMs are initialized
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
	
	
	
	
	
void set_ePWM_config(uint32_t epwm_base, uint16_t period, uint16_t offset, uint16_t deadband_delay_rising_edge, uint16_t deadband_delay_falling_edge)
{
    // Set-up TBCLK
    EPWM_setPeriodLoadMode(epwm_base, EPWM_PERIOD_DIRECT_LOAD); //direct load and never change, shadow is not used for period
    EPWM_setTimeBasePeriod(epwm_base, period);
    EPWM_setPhaseShift(epwm_base, offset);
    EPWM_setTimeBaseCounter(epwm_base, offset);
    EPWM_setEmulationMode(epwm_base, EPWM_EMULATION_FREE_RUN);

    // Set up counter mode
    EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP_DOWN);

    EPWM_setClockPrescaler(epwm_base,EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    // if offset == 0 then there is master ePWM
    if( 0 == offset )
    {
        EPWM_disablePhaseShiftLoad(epwm_base);
//        HRPWM_disablePhaseShiftLoad(epwm_base);
    }
    else
    {
        EPWM_enablePhaseShiftLoad(epwm_base);
        EPWM_setCountModeAfterSync(epwm_base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
    }
//    HRPWM_selectPeriodLoadEvent(epwm_base, EPWM_SHADOW_LOAD_MODE_SYNC); //load shadow when sync happens, TODO: no one wants to reload period register
//    HRPWM_setCounterCompareShadowLoadEvent(epwm_base, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_PERIOD); //slaves do not reach CNTR==0 because of phase shift --check it!
    // Set actions
    EPWM_setActionQualifierAction(epwm_base,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    // down counting: Output A low
    EPWM_setActionQualifierAction(epwm_base,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

    // enable rising and falling edge delay (S0, S1)
    EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_RED, true);
    EPWM_setDeadBandDelayMode(epwm_base, EPWM_DB_FED, true);
    // set EPWM_A as "lead" signal (S4, S5)
    EPWM_setRisingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
    EPWM_setFallingEdgeDeadBandDelayInput(epwm_base, EPWM_DB_INPUT_EPWMA);
    // invert output logic of B, don't invert A (S2, S3)
    EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
    EPWM_setDeadBandDelayPolarity(epwm_base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    // set output swapping of out_A/out_B (S6, S7)
    EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_A, true);
    EPWM_setDeadBandOutputSwapMode(epwm_base, EPWM_DB_OUTPUT_B, true);
    // set delay counts
    EPWM_setFallingEdgeDelayCount(epwm_base, deadband_delay_falling_edge);
    EPWM_setRisingEdgeDelayCount(epwm_base, deadband_delay_rising_edge);

//    HRPWM_disablePeriodControl(epwm_base);
    HRPWM_setMEPControlMode(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); //MEP controlled by value of CMPA
    HRPWM_setMEPEdgeSelect(epwm_base, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);

    HRPWM_setDeadbandMEPEdgeSelect(epwm_base, HRPWM_DB_MEP_CTRL_RED_FED);
//    HRPWM_setChannelBOutputPath(epwm_base, HRPWM_OUTPUT_ON_B_INV_A); //dead time is overwritten?
}