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.
All:
There are a lot of nuances with respect to sychronization of EPwms. Can someone create an example for C2000Ware that will set up sync of EPwm1, EPwm2, EPwm3, and EPwm4 to show how it is done?
All 4 can be the same period if that helps.Also, set up associated GPIO so the waveforms can be viewed on Oscilloscope or Logic Analyzer.
// // Nima Eskadari // 1/31/2019 // // // Included Files // #include "driverlib.h" #include "device.h" #define EPWM_TIMER_TBPRD 2000 // // Function Prototypes // void initEPWM(uint32_t epwm_base); void initEPWMWithOffset(uint32_t epwm_base, uint16_t offset); __interrupt void epwm1ISR(void); __interrupt void epwm2ISR(void); __interrupt void epwm3ISR(void); __interrupt void epwm4ISR(void); // // 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(); // // 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); // // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 as ePWM1A/1B, ePWM2A/2B and // ePWM3A/3B pins 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); GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_2_EPWM2A); GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_3_EPWM2B); GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_4_EPWM3A); GPIO_setPadConfig(5, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_5_EPWM3B); GPIO_setPadConfig(6, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_6_EPWM4A); GPIO_setPadConfig(7, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_7_EPWM4B); // CHANGE XBAR inputs from using GPIO0 // if EPWM SYNCIN is enabled, EXTSYNCIN1 and EXTSYNCIN2 will use // GPIO0 (which is the output of EPWM1). // Pick and unused GPIO XBAR_setInputPin(XBAR_INPUT5, 50); XBAR_setInputPin(XBAR_INPUT6, 50); // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); initEPWM(EPWM1_BASE); initEPWMWithOffset(EPWM2_BASE, 300); initEPWMWithOffset(EPWM3_BASE, 600); initEPWMWithOffset(EPWM4_BASE, 900); EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); EPWM_enablePhaseShiftLoad(EPWM2_BASE); EPWM_enablePhaseShiftLoad(EPWM3_BASE); SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM4, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT); EPWM_enablePhaseShiftLoad(EPWM4_BASE); // // 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; // // IDLE loop. Just sit and loop forever (optional): // for(;;) { } } // // epwm1ISR - ePWM 1 ISR // __interrupt void epwm1ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm2ISR - ePWM 2 ISR // __interrupt void epwm2ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm3ISR - ePWM 3 ISR // __interrupt void epwm3ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm4ISR - ePWM 4 ISR // __interrupt void epwm4ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM4_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } void initEPWM(uint32_t epwm_base) { // // Set-up TBCLK // EPWM_setTimeBasePeriod(epwm_base, EPWM_TIMER_TBPRD); EPWM_setPhaseShift(epwm_base, 0U); EPWM_setTimeBaseCounter(epwm_base, 0U); // // Set Compare values // EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_A, 2*EPWM_TIMER_TBPRD/3); EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_B, 2*EPWM_TIMER_TBPRD/3); // // Set up counter mode // EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP); EPWM_disablePhaseShiftLoad(epwm_base); EPWM_setClockPrescaler(epwm_base, EPWM_CLOCK_DIVIDER_8, EPWM_HSCLOCK_DIVIDER_1); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set actions // EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 3rd event // EPWM_setInterruptSource(epwm_base, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(epwm_base); EPWM_setInterruptEventCount(epwm_base, 1U); } void initEPWMWithOffset(uint32_t epwm_base, uint16_t offset) { // // Set-up TBCLK // EPWM_selectPeriodLoadEvent(epwm_base, EPWM_SHADOW_LOAD_MODE_SYNC); EPWM_setTimeBasePeriod(epwm_base, EPWM_TIMER_TBPRD); EPWM_setPhaseShift(epwm_base, offset); EPWM_setTimeBaseCounter(epwm_base, offset); // // Set Compare values // EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_A, 2*EPWM_TIMER_TBPRD/3); EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_B, 2*EPWM_TIMER_TBPRD/3); // // Set up counter mode // EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP); EPWM_disablePhaseShiftLoad(epwm_base); EPWM_setClockPrescaler(epwm_base, EPWM_CLOCK_DIVIDER_8, EPWM_HSCLOCK_DIVIDER_1); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set actions // EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 3rd event // EPWM_setInterruptSource(epwm_base, EPWM_INT_TBCTR_U_CMPA); EPWM_enableInterrupt(epwm_base); EPWM_setInterruptEventCount(epwm_base, 1U); }
Here you go. EPWM1 as master, EPWM2 following master and passing its sync input to its sync output. EPWM3 following EPWM2 (which is just forwarding EPWM1). EPWM4 following EPWM1 master.
Yellow EPWM1A. Green EPWM2A, PURPLE EPWM3A, PINK EPWM4A