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.

Figure 28-10. Phase-Shifted Waveform Example Application

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;
}