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.

F28075 ePWM frequency issues

Other Parts Discussed in Thread: CONTROLSUITE

Hi there, 

I'm currently moving my code from a F28335 to a F28075. Doing so, i'm having some problems in configuring the PWM frequency.

I read in the reference manual (spruhm9.pdf), that the EPWMCLK is prescaled from SYSCLK (120Mhz) to 60Mhz by default.

Thus, in order to obtain a given PWM-frequency (F_PWM) I just  just set TBPRD to

TBPRD = EPWM / (2 * F_PWM)

Right? Doing so for F_PWM = 10 kHz I measure a frequency of 8.85 kHz. That would correspond to EPWMCLK = ~ 53Mhz.

This is the code for my PWM-steup:

#include "F28x_Project.h"     // Device Headerfile and Examples Include File
#include "constants.h"
#include "pwm.h"

void PWM_Update(void)
{//interrupt generated when counter is 0
	EPwm1Regs.TBPRD  = PR;
	EPwm1Regs.CMPA.bit.CMPA = CVU_BUFF;
	EPwm1Regs.CMPB.bit.CMPB = CVU_BUFF;
	EPwm2Regs.TBPRD  = PR;
	EPwm2Regs.CMPA.bit.CMPA = CVV_BUFF;
	EPwm2Regs.CMPB.bit.CMPB = CVV_BUFF;
	EPwm3Regs.TBPRD  = PR;
	EPwm3Regs.CMPA.bit.CMPA = CVW_BUFF;
	EPwm3Regs.CMPB.bit.CMPB = CVW_BUFF;

}


unsigned short Set_fs(float fs){

	return ( (CLOCK_FREQUENCY/2) / (2*fs));		// K(5.3097e6 / 2*fs
}

void PWM_HW_Init()
{
     	EALLOW;
// This will enable the pullups for the specified pins.
// For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
// These functions are in the F28M36x_EPwm.c file
    InitEPwm1Gpio();
    InitEPwm2Gpio();
    InitEPwm3Gpio();

    EDIS;

	EPwm1Regs.TBCTR = 0x0000;//have the 3 counters in sinchron
	EPwm2Regs.TBCTR = 0x0000;
	EPwm3Regs.TBCTR = 0x0000;

	EPwm1Regs.TBPRD = 1000;//to have something in PR registers
	EPwm2Regs.TBPRD = 1000;
	EPwm3Regs.TBPRD = 1000;


	EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;//write directly into the PR shadow register
	EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;//write directly into the PR shadow register
	EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;//write directly into the PR shadow register


	EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
	EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
	EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
//no prescaller is used the timer runs at EPWMCLK = SYSCLKOUT / 2 = 60Mhz
	EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to EPWMCLK
	EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
	EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to EPWMCLK
	EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
	EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to EPWMCLK
	EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;

	EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm1Regs.AQCTLA.bit.CAD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1
	EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm1Regs.AQCTLB.bit.CBD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1


	EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm2Regs.AQCTLA.bit.CAD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1
	EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm2Regs.AQCTLB.bit.CBD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1



	EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm3Regs.AQCTLA.bit.CAD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1
	EPwm3Regs.AQCTLB.bit.CBU = AQ_CLEAR;//when Timer match the CPR reg val upcount period PWM pin set 0
	EPwm3Regs.AQCTLB.bit.CBD = AQ_SET;//when Timer match the CPR reg val downcount period PWM pin set 1


	EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; //load the compare value in double update
	EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
	EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
	EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD; //load the compare value in double update
	EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;
	EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;

	EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //CMPR registers are  shadowed
	EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; //CMPR registers are  shadowed
	EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
	EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

	//EPwm1Regs.ETPS.bit.INTCNT = 1; //generate interrupt on the first event
	//EPwm2Regs.ETPS.bit.INTCNT = 1;
	//EPwm3Regs.ETPS.bit.INTCNT = 0;

	//set up the interrupts
	EPwm1Regs.ETSEL.bit.INTEN = 0;//Disable EPWM1_INt GENERATION
	EPwm2Regs.ETSEL.bit.INTEN = 0;//Disable EPWM2_INt GENERATION

	EPwm1Regs.ETSEL.bit.SOCAEN = 1; 				//Enable EPWMxSOCA pulse
	EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; 		//Enable event time-base counter equal to zero. (TBCTR = 0x0000)
	EPwm1Regs.ETSEL.bit.SOCBEN = 1; 				//Enable EPWMxSOCB pulse
	EPwm1Regs.ETSEL.bit.SOCBSEL = ET_CTR_PRD; 		//Enable event time-base counter equal to zero. (TBCTR = 0x0000)
	EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;		//Enable event time-base counter equal 0
	EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_PRD;		//Enable event time-base counter equal PR

	EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; 			//Generate EPWMxSOCA pulse on first event
	EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;				//Generate an interrupt on the first event
	EPwm1Regs.ETPS.bit.SOCBPRD = ET_1ST;			//Generate EPWMxSOCB pulse on first event
	EPwm2Regs.ETPS.bit.INTPRD = ET_1ST;				//Generate an interrupt on the first event
	EPwm3Regs.ETPS.bit.INTPRD = ET_DISABLE;			//Generate an interrupt on the first event

	EPwm1Regs.ETCLR.bit.INT = 1;// To receive more interrupts ePWM modul
	EPwm2Regs.ETCLR.bit.INT = 1;// To receive more interrupts ePWM modul
	EPwm3Regs.ETCLR.bit.INT = 0;// To receive more interrupts ePWM modul

	EPwm1Regs.ETSEL.bit.INTEN = 0; //Stop the interrupt before initialisation
	EPwm2Regs.ETSEL.bit.INTEN = 0;

	PR = Set_fs(fs);

	EPwm1Regs.TBPRD = PR;//to have something in PR registers
	EPwm2Regs.TBPRD = PR;
	EPwm3Regs.TBPRD = PR;

	EPwm1Regs.CMPA.bit.CMPA = PR/2;
	/*
	EPwm2Regs.CMPA.bit.CMPA = PR/2;
	EPwm3Regs.CMPA.bit.CMPA = PR/2;
	EPwm1Regs.CMPB.bit.CMPB = PR/4;
	EPwm2Regs.CMPB.bit.CMPB = PR/4;
	EPwm3Regs.CMPB.bit.CMPB = PR/4;
	*/

	EALLOW;
	CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0;
	EDIS;

	IER = M_INT1|M_INT3; //Enable INT1 and INT3  in IER to enable PIE group

	// Enable ePWM1 in the PIE: Group 3 interrupt 1
	PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
	PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
	PieCtrlRegs.PIEIER3.bit.INTx3 = 0;

}

void Start_PWM_INT(){
	EPwm1Regs.ETSEL.bit.INTEN = 1;
	EPwm2Regs.ETSEL.bit.INTEN = 1;
}

void Stop_PWM_INT(){
	EPwm1Regs.ETSEL.bit.INTEN = 0;
	EPwm2Regs.ETSEL.bit.INTEN = 0;
}

Can anyone see any mistakes in this? It might be due to changing from one ePWM-type to another, but I'm not sure. This code worked on the F28335. It was setup to trigger two SOC if it is of any help.

Kind regards,

Carl Richter

Edit: F_PWM is fs. If I test for F_PWM = 20 kHz I measure a frequency of roughly 17.8kHz, so it looks like a linear error.