Other Parts Discussed in Thread: CONTROLSUITE
Hi,
we intend to use high resolution pwm with symmetric pwm (up/down counting mode) on the 28075 Piccolo.
I derived a first program from the examples in the controlSUITE (C:\ti\controlSUITE\device_support\F2807x\v190\F2807x_examples_Cpu1\epwm_updown_aq and C:\ti\controlSUITE\device_support\F2807x\v190\F2807x_examples_Cpu1\hrpwm_prdupdown_sfo_v8).
I have the following measurements:
- PWM period = 3 MHz (TBPRD = 10), PWM1A without HRPWM, PWM2A with HRPWM
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // clear PWM1A on event A, up count
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // set PWM1A on event A, down count
(So high pulse length should be proportional to the compare register value.)
f_epwm = 60 MHz (1 inc in cmp = 16.6 ns)
hpwx = high pulse width in ns, compare register value CMPA.CMPAHR = (long)ldexp(cmp, 16);
Results (plus some matlab code to plot)
cmp = [0 1 3 3.5 4 4.25 4.5 4.75 5 5.5 6 9 10];
hpw1 = [0 34 100 100 133 133 133 133 167 167 200 300 333];
hpw2 = [17 50 117 100 151 126 133 142 184 167 217 300 333];
plot(cmp, hpw1, 'o-', cmp, hpw2, 'd-', [0 10], [0 333.333]); grid;
legend('w/o HR', 'w HR', 'HR expected', 0);
xlabel('CMPA.CMPAHR'); ylabel('ns');
title('EPWM high pulse lengths on 28075 for CAU = CLEAR, CAD = SET');

conclusions
- with HRPWM the pulse is 1 inc longer if CMPA.CMPAHR == 0
- with HRPWM the pulse is 1 inc shorter if CMPA.CMPAHR != 0
(PWM1A is as expected)
comparison PWM1A, PWM2A signals on scope for different CMPA.CMPAHR:
5.00: CAD set 2A ca. 16 ns before CAD set 1A
5.25: CAD set 2A ca. 16 ns after CAD set 1A
5.50: CAU clear 2A and CAD set 2A both ca. 8 ns after 1A
5.75: CAU clear 2A and CAD set 2A ca. 12, 4 ns after 1A
This will give some strange results in the behavior of a control loop if the control algorithm produces accidentially a pwm value with CMPAHR = 0, I think.
As a workaroud I used the following code:
/* workaround / fix for a good pwm: */
/* add 0x8000 to get right pulse length, or 0x0100 to avoid CMPxHR = 0 */
pa_cmpval = (pa_cmpval + 0x8000) | 0x0100;
EPwm1Regs.CMPA.all = pa_cmpval;
Can anyone (at TI) verify the measurements?
Will the workaround help in any condition or has anyone a better idea?
Thanks,
Frank
(The code is derived from the examples and follows the suggestion given here:
)
Some snippets of changes:
/* Time Base Control Register (TBCTL) - set counter mode, divider */
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // count up
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
/* Time Base Control Register 2 (TBCTL2) - TODO */
/* Time Base Counter Register (TBCTR) - clear counter */
EPwm1Regs.TBCTR = 0x0000;
/* Time Base Status Register (TBSTS) - clear events */
EPwm1Regs.TBSTS.bit.CTRMAX = 1;
EPwm1Regs.TBSTS.bit.SYNCI = 1;
/* Time Base Phase High (TBPHS) */
EPwm1Regs.TBPHS.all = 0x00000000;
/* Time Base Period Register (TBPRD) */
EPwm1Regs.TBPRD = pwm_period;
/* Time Base Period High Resolution Register (TBPRDHR) */
EPwm1Regs.TBPRDHR = 0;
EPwm1Regs.HRCNFG.all = 0x0;
EPwm1Regs.HRCNFG2.all = 0x0;
EPwm1Regs.HRPCTL.all = 0x0;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // clear PWM1A on event A, up count
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // set PWM1A on event A, down count
EPwm2Regs.HRCNFG.all = 0x0;
EPwm2Regs.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges
EPwm2Regs.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control
EPwm2Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD
EPwm2Regs.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
EPwm2Regs.HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
EPwm2Regs.HRCNFG.bit.HRLOADB = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD
EPwm2Regs.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period
/* High Resolution Period Control Register (HRPCTL) */
/* enable TBPHSHR sync (required for updwn count HR control) */
EPwm2Regs.HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwn count HR control)
EPwm2Regs.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
EPwm2Regs.HRCNFG2.all = 0x0;
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // clear PWM1A on event A, up count
EPwm2Regs.AQCTLA.bit.CAD = AQ_SET; // set PWM1A on event A, down count
Compare register is set in a timer ISR (cmp is written by CCS debugger):
float cmp;
pa_cmpval = (long)ldexp(cmp, 16);
/* workaround / fix for a good pwm: */
/* add 0x8000 to get right length, or 0x0100 to avoid CMPxHR = 0 */
// pa_cmpval = (pa_cmpval + 0x8000) | 0x0100;
EPwm1Regs.CMPA.all = pa_cmpval;
EPwm2Regs.CMPA.all = pa_cmpval;