Part Number: TMS320F28377D
I am trying to implement the same 120 degree phase shift between epwm channels in a design as is illustrated in sprug04a figures 59 and 60 and example 13 code snip. The only difference in my design is that I am using the driver library routines instead of direct register access method and I am trying to shift phase between epwm1, epwm4, and epwm7, while keeping epwm 2 and 3 the same phase as epwm1, epwm 5 and 6 the same as epwm4, and epwm 8 and 9 the same as epwm7. I am close to successful, but not quite, in that the waveform I am getting for epwm7a/7b seems to be inverted from what I want such that 7b (the complement of 7a) looks like what I want 7a to look like. I am wondering if what I want to do is possible and I've just got some register set wrong or something similarly simple but non-obvious to me right now as a relatively new user of the epwm peripheral.
Thank you,
// -----------------------------------------------------------------------------
// FILE INFORMATION
// -----------------------------------------------------------------------------
// File Name : epwm_config.c
// Description : source code to setup the DSP epwm
// Design Notes : Handles dev board versus proto hardware
// -----------------------------------------------------------------------------
// REVISION HISTORY:
// Date By Description of Change
// -------- -------- -----------------------------------------------------------
// 20180314 sebeiter Original
// -------- -------- -----------------------------------------------------------
#include "epwm.h"
#include "peripherals.h"
#define EPWM_TIMER_TBPRD 1875 // this will be 3750 counts in up-down mode or 20KHz at 150MHz/2
#define EPWM_MIN_CMPA 1250 // = 33%
#define DEADBAND_1USEC 75
//
// initEPWM - Configure ePWM
//
void EPWM_init(epwm_group_enum epwm_group)
{
uint32_t phase_a_base;
uint32_t phase_b_base;
uint32_t phase_c_base;
uint16_t phase_shift_count = 0U;
EPWM_SyncCountMode sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC;
bool phase_enable = false;
switch(epwm_group)
{
case EPWM_GROUP_ONE:
phase_a_base = EPWM1_BASE;
phase_b_base = EPWM2_BASE;
phase_c_base = EPWM3_BASE;
phase_shift_count = 0;
phase_enable = false;
sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC;
break;
case EPWM_GROUP_TWO:
phase_a_base = EPWM4_BASE;
phase_b_base = EPWM5_BASE;
phase_c_base = EPWM6_BASE;
phase_shift_count = 1250;
phase_enable = true;
sync_count_mode = EPWM_COUNT_MODE_DOWN_AFTER_SYNC;
break;
case EPWM_GROUP_THREE:
phase_a_base = EPWM7_BASE;
phase_b_base = EPWM8_BASE;
phase_c_base = EPWM9_BASE;
phase_shift_count = 1250;
phase_enable = true;
sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC;
break;
default:
ASSERT(FALSE);
break;
}
EPWM_setupCommon(phase_a_base, phase_enable, phase_shift_count, sync_count_mode);
EPWM_setupCommon(phase_b_base, true, 0, sync_count_mode);
EPWM_setupCommon(phase_c_base, true, 0, sync_count_mode);
if(epwm_group == EPWM_GROUP_ONE)
{
// Select INT on Time base counter zero event,
// Enable INT, generate INT on 1st event
EPWM_setInterruptSource(phase_a_base, EPWM_INT_TBCTR_ZERO);
EPWM_enableInterrupt(phase_a_base);
EPWM_setInterruptEventCount(phase_a_base, 1U);
}
}
void EPWM_setupCommon(uint32_t base, bool phase_enable, uint16_t phase_shift, EPWM_SyncCountMode count_mode)
{
// Set-up TBCLK
EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD);
EPWM_setCountModeAfterSync(base, count_mode);
EPWM_setPhaseShift(base, phase_shift); //phase_shift);
EPWM_setTimeBaseCounter(base, 0U);
// Set Compare values
EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, EPWM_MIN_CMPA);
// Set up counter mode
EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN);
if(phase_enable == true)
{
EPWM_enablePhaseShiftLoad(base);
EPWM_setSyncOutPulseMode(base, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
}
else
{
EPWM_disablePhaseShiftLoad(base); // was disable
EPWM_setSyncOutPulseMode(base, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
}
EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
// Set up shadowing
EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
// Set actions
EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_A, false); // no swap on A S6=0
EPWM_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_B, false); // no swap on B S7=0
EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true); // rising edge delay S1 = 1
EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true); // falling edge delay S0 = 1
EPWM_setDeadBandDelayPolarity(base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH ); // rising edge delay not inverted S2=0
EPWM_setDeadBandDelayPolarity(base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); // falling edge delay inverted S3=1
EPWM_setRisingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); // input ePWMA to the RED S4=0
EPWM_setFallingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); // input ePWMA to the FED (AHC) S5=0
EPWM_setDeadBandControlShadowLoadMode(base, EPWM_DB_LOAD_FREEZE); // freeze shadow to active load
EPWM_disableDeadBandControlShadowLoadMode(base); // the deadband value stays the same, no need to reload each period
EPWM_setRisingEdgeDelayCountShadowLoadMode(base, EPWM_RED_LOAD_FREEZE);
EPWM_disableRisingEdgeDelayCountShadowLoadMode(base);
EPWM_setFallingEdgeDelayCountShadowLoadMode(base, EPWM_FED_LOAD_FREEZE);
EPWM_disableFallingEdgeDelayCountShadowLoadMode(base);
EPWM_setDeadBandCounterClock(base, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);
EPWM_setRisingEdgeDelayCount(base, (uint16_t)DEADBAND_1USEC);
EPWM_setFallingEdgeDelayCount(base, (uint16_t)DEADBAND_1USEC);
}