Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE
Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE
Hello Prashant,
In this case ePWM1 is the master PWM that sends syncout pulse on Time-base counter zero event. ePWM2, ePWM3, ePWM4 are slave PWMs that are synced in based on ePWM1. If you do ctrl+click on the function in CCS it will open it in epwm.h library and provide the function description, so you can get more details.
Please let me know if you have further questions or concerns.
Hi Stevan,
I am looking for phase sequence PWM1,PWM2,PWM3,PWM4 in one line cycle. Next cycle PWM2,PWM3,PWM4,PWM1, In next cycle phase sequence PWM3,PWM4,PWM31PWM2. In next cycle PWM4,PWM3,PWM2,PWM1. Like this rotation of PWM seq will continue. Do you think ,its possible with TMS320F28379. Because PWM can be triggered only one way.
Still if you have an idea , how to do it, please tell me.

Thanks for your reply,
Prashant Gugle
Hello Prashant,
Could you further clarify one line cycle approach, please? Do you want to update sequence each ISR, each Time Base period or certain sequence? What is the desired outcome and application?
Hi Stevan,
Each line cycle means, 50Hz AC input voltage .I am having zero crossover signal , at 20ms(50Hz), which is interrupt to DSP. For first 20ms ,I want to keep phase sequence PWM1,PWM2,PWM3,PWM4. For next 20ms I want to keep PWM2,PWM3,PWM4,PWM1. For next 20ms I want to keep PWM3,PWM4,PWM1,PWM2. For next 20ms PWM4,PWM1,PWM2,PWM3. Like this 4 intervals will continue in DSP firmware.
This is to reduce ripple in output voltage.
Thanks and Regards,
Prashant Gugle
Hello Prashant,
Since you want to have PWM sequence change every 20ms or each ISR, you could use a state-based logic within your Interrupt Service Routine (ISR) to reassign duty cycle values to your PWM channels. Make a sequence state counter: Use a static state variable (e.g., sequence_index) that increments from 0 to 3 inside the ISR and resets to 0 after the fourth interval. Inside the switch statement make a "case" for each statement.
Instead of doing hardware change and modifying syncout pulse, keep the hardware synchronization chain fixed (e.g., PWM1 syncs PWM2, PWM2 syncs PWM3, etc.) and simply swap the values you write to their duty cycle (CMPA) and phase (TBPHS) registers. In this case, you do not need to change the sync-in/sync-out routing.
Hope this helps.
Hi Stevan,
Thanks for your suggestion, I will do the same.
Is it possible to phase shift and synchronize PWM1 to PWM8?
Thanks and Regards,
Prashant Gugle
Prashant,
You could use following pipeline which would use ePWM1 output then set SYNCSELECT.EPWM7SYNCIN mux to 00 and then use EPWM7 syncout as EPWM8 sync in.

There is a nice video on this C2000 enhanced pulse width modulator (ePWM): Time-Base Submodule that explains further how to achieve ePWM synchronization:
https://www.ti.com/video/series/C2000-enhanced-pulse-width-modulator.html
Hi Stevan,
As suggested by you, I kept synch chain fixed and try to rotate phase only. Code is attached for your reference. But then every 80ms I get doubling of switching period for each PWM. What could be the reason for that? Is there any way we can eliminate that?
SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
switch(cycle_number)
{
case 1:
EPWM_setPhaseShift(myEPWM2_BASE, 4167);
EPWM_setTimeBaseCounter(myEPWM2_BASE, 4167);
EPWM_setPhaseShift(myEPWM3_BASE, 6250);
EPWM_setTimeBaseCounter(myEPWM3_BASE, 6250);
EPWM_setPhaseShift(myEPWM4_BASE, 8333);
EPWM_setTimeBaseCounter(myEPWM4_BASE, 8333);
EPWM_setPhaseShift(myEPWM5_BASE, 10416);
EPWM_setTimeBaseCounter(myEPWM5_BASE, 10416);
break;
case 2:
EPWM_setPhaseShift(myEPWM2_BASE, 10416);
EPWM_setTimeBaseCounter(myEPWM2_BASE, 10416);
EPWM_setPhaseShift(myEPWM3_BASE, 4167);
EPWM_setTimeBaseCounter(myEPWM3_BASE, 4167);
EPWM_setPhaseShift(myEPWM4_BASE, 6250);
EPWM_setTimeBaseCounter(myEPWM4_BASE, 6250);
EPWM_setPhaseShift(myEPWM5_BASE, 8333);
EPWM_setTimeBaseCounter(myEPWM5_BASE, 8333);
break;
case 3:
EPWM_setPhaseShift(myEPWM2_BASE, 8333);
EPWM_setTimeBaseCounter(myEPWM2_BASE, 8333);
EPWM_setPhaseShift(myEPWM3_BASE, 10416);
EPWM_setTimeBaseCounter(myEPWM3_BASE, 10416);
EPWM_setPhaseShift(myEPWM4_BASE, 4167);
EPWM_setTimeBaseCounter(myEPWM4_BASE, 4167);
EPWM_setPhaseShift(myEPWM5_BASE, 6250);
EPWM_setTimeBaseCounter(myEPWM5_BASE, 6250);
break;
case 4:
GPIO_togglePin(myGPIO0);
EPWM_setPhaseShift(myEPWM2_BASE, 6250);
EPWM_setTimeBaseCounter(myEPWM2_BASE, 6250);
EPWM_setPhaseShift(myEPWM3_BASE, 8333);
EPWM_setTimeBaseCounter(myEPWM3_BASE, 8333);
EPWM_setPhaseShift(myEPWM4_BASE, 10416);
EPWM_setTimeBaseCounter(myEPWM4_BASE, 10416);
EPWM_setPhaseShift(myEPWM5_BASE, 4167);
EPWM_setTimeBaseCounter(myEPWM5_BASE, 4167);
break;
default:
break;
}
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
Prashant,
After reviewing the code, I found an underlying issue. The problem is that you're setting both the Phase Shift register (TBPHS) and the Time Base Counter (TBCTR) to the same values:
EPWM_setPhaseShift(myEPWM2_BASE, 4167); // Sets TBPHS
EPWM_setTimeBaseCounter(myEPWM2_BASE, 4167); // Sets TBCTR - NOT CORRECT
This is causing the PWM period to double every 80ms because:
- TBPHS is the phase offset that gets loaded into the counter once on a sync event
- TBCTR is the running counter that determines where you are in the current PWM period
- By forcing TBCTR to the same value as TBPHS while the counter is already running, you're effectively "skipping" counts each time, making the effective period twice as long. The correct implementation should be:
EPWM_setPhaseShift(myEPWM2_BASE, 4167); // Sets TBPHS
EPWM_setTimeBaseCounter(myEPWM2_BASE, 0); // Reset to 0, NOT the phase value
Also, you could just remove EPWM_setTimeBaseCounter() function and just do:
SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
switch(cycle_number)
{
case 1:
EPWM_setPhaseShift(myEPWM2_BASE, 4167);
EPWM_setPhaseShift(myEPWM3_BASE, 6250);
EPWM_setPhaseShift(myEPWM4_BASE, 8333);
EPWM_setPhaseShift(myEPWM5_BASE, 10416);
break;
// ... other cases
}
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
Hope this helps.
Hi Stevan,
I tried the way you suggested, but still I am getting doubling of duty cycle. What I observed, this unintended event is happening when phase jumps from 4167 to 10416 . For your information my time base period is 6250 and it's in updown count mode.
switch(cycle_number)
{
case 1:
EPWM_setPhaseShift(myEPWM2_BASE, 4167);
EPWM_setPhaseShift(myEPWM3_BASE, 6250);
EPWM_setPhaseShift(myEPWM4_BASE, 8333);
EPWM_setPhaseShift(myEPWM5_BASE, 10416);
break;
// ... other cases
Prashant,
Thank you providing more details. The issue you are facing is simply because phase shift value should not exceed the time base period (TBPRD)
TBPRD = 6250
Up-down count mode means the total PWM period = 2 × TBPRD = 2 × 6250 = 12,500 counts
BUT phase shift values must be ≤ TBPRD (6250), not the total period
For up-down count mode with TBPRD = 6250, you need to recalculate all phase shift values to be within the valid range (0 to 6249). To give you an example, if you want to use 4 PWM channels with equal 90° phase spacing, you would define: (Also make sure to add value of 2 to take into account internal syncout / syncin synchronization delay):
case 1:
EPWM_setPhaseShift(myEPWM2_BASE, 0+2); // 0°
EPWM_setPhaseShift(myEPWM3_BASE, 156+2); // 90° = 3125/2 = 1562.5 ≈ 1562
EPWM_setPhaseShift(myEPWM4_BASE, 3125+2); // 180° = 6250/2 = 3125
EPWM_setPhaseShift(myEPWM5_BASE, 4687+2); // 270° = 9375/2 = 4687.5 ≈ 4687
break;
Hi Stevan,
I tried as per your suggestion below code. But still doubling of duty cycle is coming. What could be the reason for this?
case 1:
EPWM_setPhaseShift(myEPWM2_BASE, 0+2); // 0°
EPWM_setPhaseShift(myEPWM3_BASE, 156+2); // 90° = 3125/2 = 1562.5 ≈ 1562
EPWM_setPhaseShift(myEPWM4_BASE, 3125+2); // 180° = 6250/2 = 3125
EPWM_setPhaseShift(myEPWM5_BASE, 4687+2); // 270° = 9375/2 = 4687.5 ≈ 4687
break;
Thanks and Regards ,
Prashant Gugle
Prashant,
I'm sorry for the typo, it should be 1560 + 2 and not 156 for the TBPHS value. Could you share what is your CMPA value and how do you configure the Action Qualifier module so I can assist you further, please?
Hi Stevan,
I actually use C2000ware examples from below path, epwm_ex3_synchronization
C:\ti\c2000\C2000Ware_6_00_01_00\driverlib\f2837xd\examples\cpu1\epwm
EPWM_TIMER_TBPRD is 6250 , so CMPA value is 6250/4 and I get 75% duty cycle.
Prashant,
It seems that the action is being missed that's why your PWM keeps being high or low for additional cycle. When Phase shift is applied, per say 3120 and your CMPA is 1560 the action will be executed once TBCTR equals 1560 which would happen in next cycle.
For clarification, do you count down or up after you sync up?
Hi Stevan,
I am not taking care of phase direction. Do you mean to say I need to set TBCTL[PHDIR] at every 20ms?
Thanks and Regards,
Prashant Guhle
Prashant,
It is the settings to choose direction of your counter after sync, whether you want to count up or down, depending on if you want to produce lead or lag phase.
You set it just one time.
Hi Stevan,
I have tried TBCTL[PHSDIR] =1 , it has no impact on doubling of duty cycle. Any idea how to resolve this issue?
Thanks and Regards,
Prashant Gugle
Hi Stevan,
In up-down count mode with 6250 (1milli second) as period, I tried 4167(333 uS), 6250 (500 uS),8333 (666 uS), 10416 (833 uS) in rotation mode. I am observing correct amount of phase lead on oscilloscope between PWMs. The only problem is doubling of duty cycle.
Is there any way out of this issue?
Thanks and Regards,
Prashant Gugle
Prashant,
Doubling of duty cycle happens because the action has been missed for additional period. This could be resolved by using CMPA and CMPB method instead of TBPHS register. Please allow me some time to check if CMPA/CMPB method strategy is feasible in this case, and I will get back to you with more clear and concise suggestions to your problem statement. Thank you for your patience.
Prashant,
Please refer to this app note and the part where they configure three-phase 120 degree phase shifts using CMPA/CMPB method: https://www.ti.com/lit/an/sprad15/sprad15.pdf?ts=1771457208541&ref_url=https%253A%252F%252Fwww.google.com%252F
It will be good starting point to understand how this method works. Please reach out to me for any questions or concerns.
Hi Stevan,
Referring to the attached document I have understood CMPB is phase shift and CMPA-CMPB is 50% duty cycle. For variable duty cycle, like sine triangle PWM, can we keep fix values for CMPB =1/3 PRD for PWM2 & CMPB = 1/6 PRD for PWM3 and calculate PWM value for CMPA.
The global load is GLDCTL[ GLD] and one shot mode is GLDCTL[OSHTMODE] in following paragraph? And how and where do we need to use this.
First, global load is configured separately in PWM 1/2/3 to make sure the period and comp A/B values are loaded simultaneously when CTR=0. Second, one-shot load is enabled, to make sure the value is loaded only after the control loop running is totally finished before the content in the shadow registers is loaded into the active registers."
Thanks and Regards,
Prashant Gugle
Prashant,
The global load feature is used to do shadow to active register transfer at the same time, so the registers are updated simultaneously avoiding any unwanted overwrites. If you want to set duty cycle to be 50%, then you need to make sure that CMPA + CMPB = TBPRD in up-down count mode? Could you let me know if in your application you want to maintain fixed duty cycle and what it would be?
Hi Stevan,
In my application duty cycle is not fixed, it varies from 0 to 100%, depending on modulation index. We need to use PWM timebase in up-down counter mode.Then can we use CMPA and CMPB method for phase shift?
Thanks and Regards,
Prashant Gugle
Prashant,
You could use different CMPA and CMPB, just make sure to use global load feature. You actually could use one-shot global load which would make sure that transfer shadow-to-active registers would happen once all shadow registers are ready.
Hi Stevan,
By using global load feature can we fix the doubling of duty cycle in existing synchronization scheme?
Thanks and Regards,
Prashant Gugle
Hi Stevan,
Can we use CLB for PWM phase rotation?
Thanks and Regards,
Prashant Gugle
Prashant,
Doubling of the duty cycle happens because there is a missed action while using the TBPHS register for phase shift. TBPHS register does not have shadow register, so shadow to active register transfer cannot be achieved as it is the case with CMPA/CMPB regs, which have shadow registers available.
Hi Stevan,
In this example they are changing phase and frequency together. And they have discussed doubling of duty cycle , is something relevant for us hear?
Leverage New Type ePWM Features for Multiple Phase Control
Thanks and Regards,
Prashant Gugle
Prashant,
You could also refer to this appnote for your application. It shows step by step instructions to configure global load one shot mode on sync event and how to avoid corner cases.