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.

TMS320F28379D: EPWMx synchronization

Part Number: TMS320F28379D


Hi all,

Could someone tell me please, how the EPWM1A is synchronized with the EPWM5A in this TI Lab example,

Questions:

1)How the synchronization is done? How i could synchronize any other EPWMx with another EPWMx? 

2) It's necessary to update EPWM1 reg and EPWM5 reg in interrupt void adca1_isr routine? Why we should update if it is necessary? 

Thanks for considering my questions,

C code:

// FILE:   Lab3_cpu01.c

#include "F28x_Project.h"     		// Device Header File and Examples Include File

// Definitions for PWM generation
#define PWM1_PERIOD	0xC350			// PWM1 frequency = 2kHz
#define PWM1_CMPR25	PWM1_PERIOD>>2	// PWM1 initial duty cycle = 25%

// Function Prototypes
void ConfigureADC(void);
void ConfigureEPWM(void);
void SetupADCEpwm(void);
void InitEPwm1(void);				// Configure ePWM module 1
void InitEPwm2(void);				// Configure ePWM module 2
void InitEPwm5(void);				// Configure ePWM module 5
interrupt void adca1_isr(void);		// ADC interrupt service routine

// Variables
Uint16 period1 = PWM1_PERIOD;		// PWM1 period = 2kHz PWM
Uint16 dutyCycle1 = PWM1_CMPR25;	// PWM1 duty cycle = 25%
Uint16 dutyCycle5 = PWM1_CMPR25;	// PWM5 duty cycle = 25%
Uint16 phaseOffset5 = 0;			// PWM5 phase offset = 0

// Buffers for storing ADC conversion results
#define RESULTS_BUFFER_SIZE 256
Uint16 AdcaResults[RESULTS_BUFFER_SIZE];
Uint16 AdccResults[RESULTS_BUFFER_SIZE];
Uint16 resultsIndex;
Uint16 pretrig = 0;
Uint16 trigger = 0;


void main(void)
{
	// Initialize System Control
    InitSysCtrl();
    EALLOW;
    ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 1;
    EDIS;

    // Initialize GPIO
    InitGpio(); 		// Configure default GPIO
    InitEPwm1Gpio();	// Configure EPWM1 GPIO pins
    InitEPwm5Gpio();	// Configure EPWM5 GPIO pins

    EALLOW;
    GpioCtrlRegs.GPADIR.bit.GPIO31 = 1;			// Drives LED LD2 on controlCARD
    EDIS;
    GpioDataRegs.GPADAT.bit.GPIO31 = 1;			// Turn off LED

    // Clear all interrupts and initialize PIE vector table
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();

    // Map ISR functions
    EALLOW;
    PieVectTable.ADCA1_INT = &adca1_isr; 			// Function for ADCA interrupt 1
    EDIS;

    // Configure the ADC and power it up
    ConfigureADC();

    // Setup the ADC for ePWM triggered conversions on channel 0
    SetupADCEpwm();

    // Initialize ePWM modules
    InitEPwm1();
    InitEPwm2();
    InitEPwm5();

    // Initialize results buffers
    for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
    {
       	AdcaResults[resultsIndex] = 0;
     	AdccResults[resultsIndex] = 0;
    }
    resultsIndex = 0;

    // Enable global interrupts and higher priority real-time debug events
    IER |= M_INT1; 			// Enable group 1 interrupts
    EINT;  					// Enable Global interrupt INTM
    ERTM;  					// Enable Global realtime interrupt DBGM

    // Enable PIE interrupt
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

    // Sync ePWM
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;

    // Start ePWM
    EPwm2Regs.ETSEL.bit.SOCAEN = 1; 			// Enable SOCA
    EPwm2Regs.TBCTL.bit.CTRMODE = 0; 			// Un-freeze and enter up-count mode

    do {
      	GpioDataRegs.GPADAT.bit.GPIO31 = 0;		// Turn on LED
      	DELAY_US(1000 * 500);					// ON delay
      	GpioDataRegs.GPADAT.bit.GPIO31 = 1;   	// Turn off LED
      	DELAY_US(1000 * 500);					// OFF delay
    } while(1);
}


// Write ADC configurations and power up the ADC for both ADC A and ADC C
void ConfigureADC(void)
{
	EALLOW;

	// ADC-A
	AdcaRegs.ADCCTL2.bit.PRESCALE = 6; 			// Set ADCCLK divider to /4
	AdcaRegs.ADCCTL2.bit.RESOLUTION =  0; 		// 12-bit resolution
	AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; 		// Single-ended channel conversions (12-bit mode only)
	AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;		// Set pulse positions to late
	AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;			// Power up the ADC

	// ADC-C
	AdccRegs.ADCCTL2.bit.PRESCALE = 6; 			// Set ADCCLK divider to /4
	AdccRegs.ADCCTL2.bit.RESOLUTION =  0; 		// 12-bit resolution RESOLUTION_12BIT;
	AdccRegs.ADCCTL2.bit.SIGNALMODE = 0; 		// Single-ended channel conversions (12-bit mode only)
	AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;		// Set pulse positions to late
	AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;			// Power up the ADC
	EDIS;

	DELAY_US(1000);								// Delay for 1ms to allow ADC time to power up
}


void SetupADCEpwm(void)
{
	// Select the channels to convert and end of conversion flag
	EALLOW;
	AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;  		// SOC0 will convert pin A0
	AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14; 		// Sample window is 100 SYSCLK cycles
	AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 7; 		// Trigger on ePWM2 SOCA/C
	AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; 		// End of SOC0 will set INT1 flag
	AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;   		// Enable INT1 flag
	AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; 		// Make sure INT1 flag is cleared

	// Also setup ADC-C3 in this example
	AdccRegs.ADCSOC0CTL.bit.CHSEL = 3;  		// SOC0 will convert pin C3
	AdccRegs.ADCSOC0CTL.bit.ACQPS = 14; 		// Sample window is 100 SYSCLK cycles
	AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 7; 		// Trigger on ePWM2 SOCA/C
	EDIS;
}


void InitEPwm1(void)
{
   // Setup TBCLK
   EPwm1Regs.TBCTL.bit.CTRMODE = 0; 			// Count up
   EPwm1Regs.TBPRD = period1;  					// Set timer period
   EPwm1Regs.TBCTL.bit.PHSEN = 0;    	        // Disable phase loading
   EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
   EPwm1Regs.TBCTR = 0x0000;                  	// Clear counter
   EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1;   		// Clock ratio to SYSCLKOUT
   EPwm1Regs.TBCTL.bit.CLKDIV = 0;
   EPwm1Regs.TBCTL.bit.SYNCOSEL = 1;			// SYNC output on CTR = 0

   // Setup shadow register load on ZERO
   EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;
   EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0;
   EPwm1Regs.CMPCTL.bit.LOADAMODE = 0;
   EPwm1Regs.CMPCTL.bit.LOADBMODE = 0;

   // Set Compare values
   EPwm1Regs.CMPA.bit.CMPA = dutyCycle1; 	    // Set compare A value

   // Set actions
   EPwm1Regs.AQCTLA.bit.ZRO = 2;   		        // Set PWM1A on Zero
   EPwm1Regs.AQCTLA.bit.CAU = 1;    	        // Clear PWM1A on event A, up count
}


void InitEPwm2(void)
{
	EALLOW;
	// Assumes ePWM clock is already enabled
	EPwm2Regs.TBCTL.bit.CTRMODE = 3;            // Freeze counter
	EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0;			// TBCLK pre-scaler = /1
	EPwm2Regs.TBPRD = 0x07D0;			        // Set period to 2000 counts (50kHz)
	EPwm2Regs.ETSEL.bit.SOCAEN	= 0;	        // Disable SOC on A group
	EPwm2Regs.ETSEL.bit.SOCASEL	= 2;	        // Select SOCA on period match
    EPwm2Regs.ETSEL.bit.SOCAEN = 1; 			// Enable SOCA
	EPwm2Regs.ETPS.bit.SOCAPRD = 1;		        // Generate pulse on 1st event
	EDIS;
}


void InitEPwm5(void)
{
   // Setup TBCLK
   EPwm5Regs.TBCTL.bit.CTRMODE = 0;             // Count up
   EPwm5Regs.TBPRD = PWM1_PERIOD;               // Same period as PWM1
   EPwm5Regs.TBCTL.bit.PHSEN = 1;               // Enable phase loading
   EPwm5Regs.TBPHS.bit.TBPHS = phaseOffset5;    // Phase
   EPwm5Regs.TBCTR = 0x0000;                    // Clear counter
   EPwm5Regs.TBCTL.bit.HSPCLKDIV = 1;           // Clock ratio to SYSCLKOUT
   EPwm5Regs.TBCTL.bit.CLKDIV = 0;

   // Setup shadow register load on ZERO
   EPwm5Regs.CMPCTL.bit.SHDWAMODE = 0;
   EPwm5Regs.CMPCTL.bit.SHDWBMODE = 0;
   EPwm5Regs.CMPCTL.bit.LOADAMODE = 0;
   EPwm5Regs.CMPCTL.bit.LOADBMODE = 0;

   // Set Compare values
   EPwm5Regs.CMPA.bit.CMPA = dutyCycle5;        // Set compare A value

   // Set actions
   EPwm5Regs.AQCTLA.bit.ZRO = 2;                // Set PWM1A on Zero
   EPwm5Regs.AQCTLA.bit.CAU = 1;                // Clear PWM1A on event A, up count
}


interrupt void adca1_isr(void)
{
	// Read the ADC result and store in circular buffer
	if (trigger != 0)
	{
		AdcaResults[resultsIndex] = AdcaResultRegs.ADCRESULT0;
		AdccResults[resultsIndex++] = AdccResultRegs.ADCRESULT0;
		if(RESULTS_BUFFER_SIZE <= resultsIndex)
		{
			resultsIndex = 0;
			pretrig = 0;
			trigger = 0;

			// Update PWMs
			EPwm1Regs.TBPRD = period1;
			EPwm1Regs.CMPA.bit.CMPA = dutyCycle1;
			EPwm5Regs.TBPRD = period1;
			EPwm5Regs.CMPA.bit.CMPA = dutyCycle5;
			EPwm5Regs.TBPHS.bit.TBPHS = phaseOffset5;
		}
	}

	// This code identifies a low-to-high transition on PWM1A so the results buffer always starts
	// on a rising edge.  This makes phase observations between PWM1 and PWM5 clearer.
	else if (pretrig != 0)
	{
		trigger |= GpioDataRegs.GPADAT.bit.GPIO0;
	}
	else pretrig = GpioDataRegs.GPADAT.bit.GPIO0 - 1;

	// Return from interrupt
	AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; 		// Clear ADC INT1 flag
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;		// Acknowledge PIE group 1 to enable further interrupts
}

 // end of file