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.