Part Number: TMS320F28379D
Hi
I am using the example code PWM up_down for generating PWM signals. I am now trying to generate a phase-shift between few PWM signals, which is not coming out to be as expected.
I am using ePWM3, ePWM 4, ePWM5 and ePWM6.
I want phase-shift X between ePWM3 abd ePWM5, and similarly phase-shift X between ePWM4 and ePWM6. I have attached the code for your reference here.
I have enabled PHS in TBCTL, loaded TBCTR with TBPHS value. The problem I am having is that there is always a minimum phase shift Y even if I load the TBCTR with phase value zero.
Kindly help me rectify this issue.
1. How to generate the required phase shift between ePWMs?
2. How to generate the phase shift between ePWMs which are not in the same ePWM tree, e.g. ePWM 4 and ePWM12?
Thanks
Sneha Thakur
#include "F28x_Project.h"
//
// Defines
// TBPRD = 250 for 200 kHz, TBPRD = 166.66 for 300 kHz
// original values
//#define EPWM3_TIMER_TBPRD 2000 // Period register
//#define EPWM3_MAX_CMPA 950
//#define EPWM3_MIN_CMPA 50
//#define EPWM3_MAX_CMPB 1950
//#define EPWM3_MIN_CMPB 1050
#define period 167;//250
#define duty 83.49;
#define dutyA 88.51;
#define dutyB 78.51;
#define phase_A 0;
#define phase_B 78.49;
#define phase_Bup 78.51;
#define phase_Bdown 78.51;
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
//
// Globals
//
typedef struct
{
volatile struct EPWM_REGS *EPwmRegHandle;
Uint16 EPwm_CMPA_Direction;
Uint16 EPwm_CMPB_Direction;
Uint16 EPwmTimerIntCount;
Uint16 EPwmMaxCMPA;
Uint16 EPwmMinCMPA;
Uint16 EPwmMaxCMPB;
Uint16 EPwmMinCMPB;
}
EPWM_INFO;
EPWM_INFO epwm1_info;
EPWM_INFO epwm2_info;
EPWM_INFO epwm3_info;
//
// Function Prototypes
//
void InitEPwm1Example(void);
void InitEPwm2Example(void);
void InitEPwm3Example(void);
void InitEPwm4Example(void);
void InitEPwm5Example(void);
void InitEPwm6Example(void);
__interrupt void epwm1_isr(void);
__interrupt void epwm2_isr(void);
__interrupt void epwm3_isr(void);
__interrupt void epwm4_isr(void);
__interrupt void epwm5_isr(void);
__interrupt void epwm6_isr(void);
void update_compare(EPWM_INFO*);
//
// Main
//
void main(void)
{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
InitSysCtrl();
//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
// InitGpio();
//
// enable PWM1, PWM2 and PWM3
//
CpuSysRegs.PCLKCR2.bit.EPWM1=1;
CpuSysRegs.PCLKCR2.bit.EPWM2=1;
CpuSysRegs.PCLKCR2.bit.EPWM3=1;
CpuSysRegs.PCLKCR2.bit.EPWM4=1;
CpuSysRegs.PCLKCR2.bit.EPWM5=1;
CpuSysRegs.PCLKCR2.bit.EPWM6=1;
//
// For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
// These functions are in the F2837xD_EPwm.c file
//
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();
InitEPwm4Gpio();
InitEPwm5Gpio();
InitEPwm6Gpio();
//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT;
//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
InitPieCtrl();
//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
IER = 0x0000;
IFR = 0x0000;
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
InitPieVectTable();
//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1_isr;
PieVectTable.EPWM2_INT = &epwm2_isr;
PieVectTable.EPWM3_INT = &epwm3_isr;
PieVectTable.EPWM4_INT = &epwm4_isr;
PieVectTable.EPWM5_INT = &epwm5_isr;
PieVectTable.EPWM6_INT = &epwm6_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
//
// For this example, only initialize the ePWM
//
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
InitEPwm1Example();
InitEPwm2Example();
InitEPwm3Example();
InitEPwm4Example();
InitEPwm5Example();
InitEPwm6Example();
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
//
// Step 4. User specific code, enable interrupts:
//
//
// Enable CPU INT3 which is connected to EPWM1-3 INT:
//
IER |= M_INT3;
//
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
//
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
// PieCtrlRegs.PIEIER4.bit.INTx3 = 1;
//PieCtrlRegs.PIEIER5.bit.INTx1 = 1;
//PieCtrlRegs.PIEIER6.bit.INTx2 = 1;
//
// Enable global Interrupts and higher priority real-time debug events:
//
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
//
// Step 5. IDLE loop. Just sit and loop forever (optional):
//
for(;;)
{
asm (" NOP");
}
}
//
// epwm1_isr - EPWM1 ISR
//
__interrupt void epwm1_isr(void)
{
//
// Update the CMPA and CMPB values
//
// update_compare(&epwm1_info);
//
// Clear INT flag for this timer
//
EPwm1Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
//
// epwm2_isr - EPWM2 ISR
//
__interrupt void epwm2_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm2_info);
//
// Clear INT flag for this timer
//
EPwm2Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
//
// epwm3_isr - EPWM3 ISR
//
__interrupt void epwm3_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm3_info);
//
// Clear INT flag for this timer
//
EPwm3Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
// epwm4_isr - EPWM4 ISR
//
__interrupt void epwm4_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm3_info);
//
// Clear INT flag for this timer
//
EPwm4Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
// epwm5_isr - EPWM5 ISR
__interrupt void epwm5_isr(void)
{
//
// Update the CMPA and CMPB values
//
// update_compare(&epwm1_info);
//
// Clear INT flag for this timer
//
EPwm5Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
// epwm6_isr - EPWM6 ISR
__interrupt void epwm6_isr(void)
{
//
// Update the CMPA and CMPB values
//
// update_compare(&epwm1_info);
//
// Clear INT flag for this timer
//
EPwm6Regs.ETCLR.bit.INT = 1;
//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
//
// InitEPwm1Example - Initialize EPWM1 configuration
//
void InitEPwm1Example()
{
//
// Setup TBCLK
//
EPwm1Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm1Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm1Regs.CMPA.bit.CMPA = dutyA; // Set compare A value
EPwm1Regs.CMPB.bit.CMPB = dutyB; // actual EPWM1_MAX_CMPB;//Set Compare B value
//
// Setup counter mode
//
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up
// count
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
// down count
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;//AQ_SET; // Set PWM1B on event B, up
// count
EPwm1Regs.AQCTLB.bit.CBD = AQ_SET;//AQ_CLEAR; // Clear PWM1B on event B,
// down count
}
//
// InitEPwm2Example - Initialize EPWM2 configuration
//
void InitEPwm2Example()
{
//
// Setup TBCLK
//
EPwm2Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm2Regs.TBPHS.bit.TBPHS = phase_A;//0x0000; // Phase is 0
EPwm2Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm2Regs.CMPA.bit.CMPA = dutyB; // Set compare A value
EPwm2Regs.CMPB.bit.CMPB = dutyA; // Set Compare B value
//
// Setup counter mode
//
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Disable phase loading
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up
// count
EPwm2Regs.AQCTLA.bit.CAD = AQ_SET; // Clear PWM2A on event B, down
// count
EPwm2Regs.AQCTLB.bit.CBU = AQ_SET;//AQ_SET; // Set PWM1B on event B, up
// count
EPwm2Regs.AQCTLB.bit.CBD = AQ_CLEAR;
// EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on zero
// EPwm2Regs.AQCTLB.bit.PRD = AQ_SET; // Set PWM2B on period
}
//
// InitEPwm3Example - Initialize EPWM3 configuration
//
void InitEPwm3Example()
{
//
// Setup TBCLK
//
EPwm3Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm3Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm3Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm3Regs.CMPA.bit.CMPA = dutyA; // Set compare A value
EPwm3Regs.CMPB.bit.CMPB = dutyB; // actual EPWM1_MAX_CMPB;//Set Compare B value
//
// Setup counter mode
//
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up
// count
EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
// down count
EPwm3Regs.AQCTLB.bit.CBU = AQ_CLEAR;//AQ_SET; // Set PWM1B on event B, up
// count
EPwm3Regs.AQCTLB.bit.CBD = AQ_SET;//AQ_CLEAR; // Clear PWM1B on event B,
// down count
}
// InitEPwm4Example - Initialize EPWM4 configuration
//
void InitEPwm4Example()
{
//
// Setup TBCLK
//
EPwm4Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm4Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm4Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm4Regs.CMPA.bit.CMPA = dutyB; // Set compare A value
EPwm4Regs.CMPB.bit.CMPB = dutyA; // Set Compare B value
//
// Setup counter mode
//
EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm4Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm4Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm4Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm4Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up
// count
EPwm4Regs.AQCTLA.bit.CAD = AQ_SET; // Clear PWM2A on event B, down
// count
EPwm4Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up
// count
EPwm4Regs.AQCTLB.bit.CBD = AQ_CLEAR;
// EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on zero
// EPwm2Regs.AQCTLB.bit.PRD = AQ_SET; // Set PWM2B on period
}
void InitEPwm5Example()
{
//
// Setup TBCLK
//
EPwm5Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm5Regs.TBPHS.bit.TBPHS =phase_A; // Phase is 0
EPwm5Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm5Regs.CMPA.bit.CMPA = dutyA; // Set compare A value
EPwm5Regs.CMPB.bit.CMPB = dutyB; // actual EPWM1_MAX_CMPB;//Set Compare B value
//
// Setup counter mode
//
EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Disable phase loading
EPwm5Regs.TBCTL.bit.SWFSYNC= 1;
//EPwm5Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm5Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm5Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up
// count
EPwm5Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
// down count
EPwm5Regs.AQCTLB.bit.CBU = AQ_CLEAR;//AQ_SET; // Set PWM1B on event B, up
// count
EPwm5Regs.AQCTLB.bit.CBD = AQ_SET;//AQ_CLEAR; // Clear PWM1B on event B,
}
//
// InitEPwm6Example - Initialize EPWM6 configuration
//
void InitEPwm6Example()
{
//
// Setup TBCLK
//
EPwm6Regs.TBPRD = period; // Set timer period 801 TBCLKs
EPwm6Regs.TBPHS.bit.TBPHS = phase_A;//0x0000; // Phase is 0
EPwm6Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm6Regs.CMPA.bit.CMPA = dutyB; // Set compare A value
EPwm6Regs.CMPB.bit.CMPB = dutyA; // Set Compare B value
//
// Setup counter mode
//
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Disable phase loading
EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;
//
// Setup shadowing
//
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up
// count
EPwm6Regs.AQCTLA.bit.CAD = AQ_SET; // Clear PWM2A on event B, down
// count
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up
// count
EPwm6Regs.AQCTLB.bit.CBD = AQ_CLEAR;
// EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on zero
// EPwm2Regs.AQCTLB.bit.PRD = AQ_SET; // Set PWM2B on period
//
}
//
// End of file
//
