28.5.1 Generating Phase-Shifted Waveforms
Figure 28-10 shows an application example for generating phase-shifted PWM waveforms. In this example, PWM1 generates a waveform and the rising edge of this pulse is the trigger input to the PTG module. When the trigger from PWM1 is received, the PTG module waits on PTG Timer 0 using the PTGCTRL(0b1000) command, inserting a programmable delay and then outputting a PCI signal to PWM2. This signal is the synchronization source for PWM2, which is configured to output a single cycle with the same period and duty cycle as PWM1. As PWM2 is repeatedly triggered by the PTG, it outputs a phase-shifted version of PWM1, with the phase shift determined by the PTG Timer 0 delay.
Generating Phase-Shifted Waveforms shows code for generating a phase-shifted waveform.
Generating Phase-Shifted Waveforms
#include <xc.h>
void IO_initialize() {
_PCI12R = 137; //Connect PCI 12 to PTG trigger 26
_TRISD2 = 0; //Set RD2 as output (used by PWM1H)
_TRISD0 = 0; //Set RD0 as output (used by PWM2H)
}
void PWM1_initialize() {
PG1CONbits.CLKSEL = 1; //Main PWM clock (undivided/unscaled) used for PWM2
PG1IOCON1bits.PENH = 1; //PWM generator 1 controls PWM1H pin
PG1EVT2bits.ADTR2EN1 = 1; //PGA1TRIGA match controls PWM1 ADC Trigger 2
PG1PER = 8000 << 4; //Period 1ms for a 8MHz PWM clock
PG1DC = 4000 << 4; //50% duty cycle
PG1PHASE = 0; //0 phase offset
PG1TRIGA = 0; //PWM ADC trigger 2 will happen at start of cycle
PG1CONbits.ON = 1; //Enable PWM Generator 1
}
void PWM2_initialize() {
PG2CONbits.CLKSEL = 1; //Main PWM clock (undivided/unscaled) used for PWM2
PG2CONbits.SOCS = 0b1111; //PCI sync used for start of cycle
PG2IOCON1bits.PENH = 1; //PWM generator 2 controls PWM2H pin
PG2PER = 8000 << 4; //Period 1ms for a 8MHz PWM clock
PG2DC = 4000 << 4; //50% duty cycle
PG2PHASE = 0; //0 phase offset
PG2SPCI2 = 0x1100; //PCI12 as PWM2 sync source
PG2CONbits.ON = 1; //Enable PWM Generator 2
}
void PTG_initialize() {
PTGT0LIM = 1000; //0.125ms T0 delay
PTGQUE0bits.STEP0 = PTGWHI(0); //Wait for high-to-low edge on trigger from PWM1
PTGQUE0bits.STEP1 = PTGCTRL(t0Wait); //Wait on T0
PTGQUE0bits.STEP2 = PTGTRIG(26); //Trigger PWM2
PTGQUE0bits.STEP3 = PTGJMP(0); //Restart sequence
PTGCONbits.ON = 1; //Enable PTG
PTGCONbits.PTGSTRT = 1; //Start executing commands
}
void clocks_initialize() {
//Configure both CLKGEN5 (PWM) and CLKGEN11 (PTG) to use 8MHz clock from FRC.
//Enable CLKGEN5, if not already enabled
CLK5CONbits.ON = 1;
//Reset CLKGEN5 fractional divider for 1:1 ratio
CLK5DIVbits.INTDIV = 0;
CLK5DIVbits.FRACDIV = 0;
//Request CLKGEN5 fractional divider switch
CLK5CONbits.DIVSWEN = 1;
//Wait for CLKGEN5 fractional divider switch to complete
while(CLK5CONbits.DIVSWEN);
//Select FRC as CLKGEN5's new clock source
CLK5CONbits.NOSC = 1;
//Request CLKGEN5 clock source switch
CLK5CONbits.OSWEN = 1;
//Wait for CLKGEN5 clock source switch to complete
while(CLK5CONbits.OSWEN);
PCLKCONbits.MCLKSEL = 1; //Use CLKGEN5 to provide PWM MCLK
//Enable CLKGEN11, if not already enabled
CLK11CONbits.ON = 1;
//Reset CLKGEN11 fractional divider for 1:1 ratio
CLK11DIVbits.INTDIV = 0;
CLK11DIVbits.FRACDIV = 0;
//Request CLKGEN11 fractional divider switch
CLK11CONbits.DIVSWEN = 1;
//Wait for CLKGEN11 fractional divider switch to complete
while(CLK11CONbits.DIVSWEN);
//Select FRC as CLKGEN11's new clock source
CLK11CONbits.NOSC = 1;
//Request CLKGEN11 clock source switch
CLK11CONbits.OSWEN = 1;
//Wait for CLKGEN11 clock source switch to complete
while(CLK11CONbits.OSWEN);
}
int main(void) {
clocks_initialize();
IO_initialize();
PWM1_initialize();
PWM2_initialize();
PTG_initialize();
while (1);
return 0;
}