Hi, I have tried implementing the described workaround for enabling 0/100% duty cycle. As I want to put this in a general driver, not a specific interrupt, I have used the knowledge of current and next (desired) CMP value and register states to determine which "step" the code currently is in. The following code is an excerpt from the function that is called in every PWM interrupt.
void DutyWorkaround(volatile struct EPWM_REGS *epwm_regs_p, enum PWM_CHANNEL channel, uint16_t next_cmp) {
if (next_cmp == 0) {
if (epwm_regs_p->CMPA.half.CMPA != 0) { // CMP non-zero -> zero
epwm_regs_p->AQCTLA.bit.ZRO = AQ_ACTION_SET;
} else { // Next cycle after CMP non-zero -> zero
epwm_regs_p->AQCTLA.bit.ZRO = AQ_ACTION_NONE;
epwm_regs_p->AQCTLA.bit.CAD = AQ_ACTION_CLEAR;
}
} else {
if (epwm_regs_p->CMPA.half.CMPA == 0) { // CMP zero -> non-zero
epwm_regs_p->AQCTLA.bit.ZRO = AQ_ACTION_CLEAR;
epwm_regs_p->AQCTLA.bit.CAD = AQ_ACTION_NONE;
epwm_regs_p->CMPCTL.bit.LOADAMODE = 2;
} else { // Next cycle after CMP zero -> non-zero
epwm_regs_p->AQCTLA.bit.ZRO = AQ_ACTION_NONE;
epwm_regs_p->AQCTLA.bit.CAD = AQ_ACTION_CLEAR;
epwm_regs_p->CMPCTL.bit.LOADAMODE = 0;
}
}
This seems to work, with the exception that when I toggle the duty cycle between zero (CMP = PRD) and 100 (CMP = 0) in every interrupt, it does no longer work, and produces an output looking like a 75% duty cycle.
1: Is this workaround incompatible with this kind of toggling? Does it expect at least two cycles after CMP going to/from 0 before it does the opposite?
2: The workaround only describes the method, not the source of the problem. Could you please provide me with more information on what causes this problem, so that it is easier to understand and maybe implement a better workaround?