Hello,
I'd like to generate N PWM shifted of 360/N° to control an interleaved buck converter.
I use PWM1 as reference (master) and generate a SYNCOUT signal when CTR = 0 to feed the others PWM modules (slaves).
When zooming on the edges of slaves PWM i observe a jitter of 20ns which seems to correspond to the note page 1967 of the TRM (jitter of +/-2 clock period).
How can I synchronize the PWM in HR mode without having this jitter ?
Here's my initialization code :
void PWM_configureModule(PWM_moduleConfiguration_s* conf)
{
volatile struct EPWM_REGS * moduleRegs = &EPwm1Regs + conf->module;
PWM_calibrate();
EALLOW;
SyncSocRegs.SYNCSELECT.bit.EPWM4SYNCIN = 0U;
SyncSocRegs.SYNCSELECT.bit.EPWM7SYNCIN = 0U;
SyncSocRegs.SYNCSELECT.bit.EPWM10SYNCIN = 0U;
// Stop PWM synchronization during configuration
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0U;
moduleRegs->TBCTL.bit.PRDLD = 0U; // Period register is shadowed
*((volatile uint32_t*)(&moduleRegs->TBPRDHR)) = (uint32_t)(64000.0F * (float32_t)SYSCTRL_getCpuFreqInMhz() / conf->frequency) << 8U;
if(conf->module == PWM_MODULE_1)
{
moduleRegs->TBCTL.bit.PHSEN = 0U;
moduleRegs->TBCTL.bit.SYNCOSEL = 1U;
}
else
{
moduleRegs->TBCTL.bit.SYNCOSEL = 0U;
if(conf->enablePhaseSynchronisation)
{
if(conf->phase < 180.0F)
{
moduleRegs->TBPHS.all = (uint32_t)(conf->phase / 180.0F * (float32_t)(*((volatile uint32_t*)(&moduleRegs->TBPRDHR))));
moduleRegs->TBCTL.bit.PHSDIR = 0U;
}
else
{
moduleRegs->TBPHS.all = (uint32_t)((360.0F - conf->phase) / 180.0F * (float32_t)(*((volatile uint32_t*)(&moduleRegs->TBPRDHR))));
moduleRegs->TBCTL.bit.PHSDIR = 1U;
}
moduleRegs->TBCTL.bit.PHSEN = 1U;
}
else
{
moduleRegs->TBCTL.bit.PHSEN = 0U;
}
}
moduleRegs->TBCTR = 0U; // Reset timebase counter
moduleRegs->TBCTL.bit.CTRMODE = 2U; // Up-down count mode
moduleRegs->TBCTL.bit.CLKDIV = 0U;
moduleRegs->TBCTL.bit.HSPCLKDIV = 0U;
moduleRegs->TBCTL.bit.FREE_SOFT = 2U;
if(conf->linkDutyCycle)
{
moduleRegs->EPWMXLINK.bit.CMPALINK = conf->linkedModule;
moduleRegs->EPWMXLINK.bit.CMPBLINK = conf->linkedModule;
}
else
{
}
// Enable dead-band half cycle clocking
// to allow high resolution on dead-band
moduleRegs->DBCTL.bit.HALFCYCLE = 1U;
moduleRegs->DBCTL.bit.DEDB_MODE = 0U;
moduleRegs->DBCTL.bit.OUT_MODE = 3U; // Falling and rising edge dead band
moduleRegs->DBCTL.bit.IN_MODE = 2U; // PWMA is the source for rising edge delay, PWMB is the source for falling edge delay
moduleRegs->DBCTL.bit.SHDWDBFEDMODE = 0U; // Dead band registers are shadowed
moduleRegs->DBCTL.bit.SHDWDBREDMODE = 0U;
moduleRegs->DBCTL2.bit.LOADDBCTLMODE = 1U;
switch(conf->mode)
{
case PWM_SINGLE_A:
moduleRegs->DBCTL.bit.POLSEL = 0U; // Non Inverted A
moduleRegs->AQCTLA.bit.CAU = 2U;
moduleRegs->AQCTLA.bit.CAD = 1U;
break;
case PWM_SINGLE_B:
moduleRegs->DBCTL.bit.POLSEL = 0U; // Non Inverted B
moduleRegs->AQCTLB.bit.CBU = 2U;
moduleRegs->AQCTLB.bit.CBD = 1U;
break;
case PWM_COMPLEMENTARY_AB:
moduleRegs->DBCTL.bit.POLSEL = 2U; // Non inverted A, Invert B path
moduleRegs->AQCTLA.bit.CAU = 2U;
moduleRegs->AQCTLA.bit.CAD = 1U;
moduleRegs->AQCTLB.bit.CBU = 2U;
moduleRegs->AQCTLB.bit.CBD = 1U;
break;
case PWM_COMPLEMENTARY_BA:
moduleRegs->DBCTL.bit.POLSEL = 1U; // Inverted A path, Non inverted B
moduleRegs->AQCTLA.bit.CAU = 2U;
moduleRegs->AQCTLA.bit.CAD = 1U;
moduleRegs->AQCTLB.bit.CBU = 2U;
moduleRegs->AQCTLB.bit.CBD = 1U;
break;
}
*((volatile uint32_t*)(&moduleRegs->DBREDHR.all)) = (uint32_t)(conf->risingDeadband / 90.0F * (float32_t)(*((volatile uint32_t*)(&moduleRegs->TBPRDHR))));
*((volatile uint32_t*)(&moduleRegs->DBFEDHR.all)) = (uint32_t)(conf->fallingDeadband / 90.0F * (float32_t)(*((volatile uint32_t*)(&moduleRegs->TBPRDHR))));
moduleRegs->CMPCTL.bit.SHDWAMODE = 0U; // CMPA register is shadowed
moduleRegs->CMPCTL.bit.SHDWBMODE = 0U; // CMPB register is shadowed
moduleRegs->CMPCTL.bit.LOADAMODE = 2U; // Load CMPA of TBCTR = PRD
moduleRegs->CMPCTL.bit.LOADBMODE = 2U; // Load CMPB of TBCTR = PRD
/* Use trip action defined in TZCTL2, TZCTLDCA and TZCTLDCB */
moduleRegs->TZCTL2.all = 0x8FFF;
moduleRegs->TZCTLDCA.all = 0xFFF;
moduleRegs->TZCTLDCA.all = 0xFFF;
moduleRegs->TZCTLDCB.all = 0xFFF;
moduleRegs->TZCTLDCB.all = 0xFFF;
/* Digital compare submodule input is a combination of TRIP inputs */
moduleRegs->DCTRIPSEL.bit.DCAHCOMPSEL = 0xF;
moduleRegs->DCTRIPSEL.bit.DCALCOMPSEL = 0xF;
moduleRegs->DCTRIPSEL.bit.DCBHCOMPSEL = 0xF;
moduleRegs->DCTRIPSEL.bit.DCBLCOMPSEL = 0xF;
moduleRegs->TZDCSEL.bit.DCAEVT1 = 0x2U;
moduleRegs->TZDCSEL.bit.DCAEVT2 = 0x4U;
moduleRegs->TZDCSEL.bit.DCBEVT1 = 0x2U;
moduleRegs->TZDCSEL.bit.DCBEVT2 = 0x4U;
moduleRegs->TBCTL.bit.CTRMODE = 2U; // Up count mode
if(PWM_MODULE_HAS_HR_CAPABILITY(conf->module) && conf->enableHighResolution)
{
moduleRegs->HRCNFG.all = 0x0000U; // Clear register
moduleRegs->HRCNFG.bit.CTLMODE = 0U; // TBPRDHR Register controls the edge position
// (i.e., this is duty or period control mode).
moduleRegs->HRCNFG.bit.CTLMODEB = 0U; //TBPRDHR(8) Register controls the edge position
// (i.e., this is duty or period control mode).
moduleRegs->HRCNFG.bit.HRLOAD = 2U; // Load CMPAHR on either CTR = Zero or CTR = PRD
moduleRegs->HRCNFG.bit.HRLOADB = 2U; // Load CMPBHR on either CTR = Zero or CTR = PRD
moduleRegs->HRCNFG.bit.AUTOCONV = 1U; // Autoconversion ON
moduleRegs->HRCNFG.bit.EDGMODE = 3U; // MEP control of both edges
moduleRegs->HRCNFG.bit.EDGMODEB = 3U; // MEP control of both edges
moduleRegs->HRCNFG2.bit.EDGMODEDB = 3U; // MEP control of both edges (rising edge of DBREDHR or falling
// edge of DBFEDHR )
moduleRegs->HRCNFG2.bit.CTLMODEDBFED = 1U; // Load on either CTR = Zero or CTR = PRD
moduleRegs->HRCNFG2.bit.CTLMODEDBRED = 1U; // Load on either CTR = Zero or CTR = PRD
moduleRegs->HRPCTL.bit.PWMSYNCSEL = 0U;
moduleRegs->HRPCTL.bit.TBPHSHRLOADE = 1U;
moduleRegs->HRPCTL.bit.HRPE = 1U;
moduleRegs->HRPWR.bit.CALPWRON = 1U; // Enable MEP calibration logic
}
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1U;
forceSynchronization(conf->module);
EDIS;
}
Thank you for your support,
Arthur