28.5.2.1 Interleaved Sampling Step Command Program
This section describes the step command programming for implementing the timing sequence shown in Figure 28-11.
The following assumptions are made:
- Trigger Input 0 is connected to the PWM1 signal. The rising edge of this signal starts the sequence. PWM1 has a period of 50us.
- Output Trigger 12 is connected to the ADC module. This signal gives command to the ADC module to begin a sample and conversion process.
- Interrupt 0 is used to indicate to the processor that a subsequence has started (provides status).
- Interrupt 1 is used to indicate to the processor that the entire sequence has completed.
- The PTG clock source is 125 MHz.
- The initial trigger delay is 5 μs.
- The second trigger delay is 6 μs.
- In each PWM cycle, the ADC will be triggered 25 times.
- The basic sequence is executed twice.
Interleaved Sampling Step Command Program
#include <xc.h>
//Allocate buffers for ADC results.
//Size of 50 is based on 2 PWM cycles, 25 results per cycle.
#define RESULT_BUFFER_SIZE 50
unsigned int voltage_buffer[RESULT_BUFFER_SIZE];
int voltage_buffer_index = 0;
unsigned int current_buffer[RESULT_BUFFER_SIZE];
int current_buffer_index = 0;
_Bool readings_ready = 0;
void clocks_initialize() {
//Set up CPU clock (Fcy) to run at 200 MHz.
//Start by configuring PLL1
PLL1CONbits.ON = 1; //Enable PLL1, if not already enabled
//PLL1 has input frequency 8MHz (FRC)
PLL1DIVbits.PLLPRE = 1; //Reference input will be 8MHz, no division
PLL1DIVbits.PLLFBDIV = 125; //Fvco = 8MHz * 125 = 1000MHz
PLL1DIVbits.POSTDIV1 = 5; //Divide Fcvo by 5
PLL1DIVbits.POSTDIV2 = 1; //Fpllo = Fvco / 5 / 1 = 200 MHz
//The PLLSWEN bit controls changes to the PLL feedback divider.
//Request PLL1 feedback divider switch
PLL1CONbits.PLLSWEN = 1;
//Wait for PLL1 feedback divider switch to complete
while(PLL1CONbits.PLLSWEN);
//The FOUTSWEN bit controls changes to the PLL output dividers.
//Request PLL1 output divider switch
PLL1CONbits.FOUTSWEN = 1;
//Wait for PLL1 output divider switch to complete
while(PLL1CONbits.FOUTSWEN);
VCO1DIVbits.INTDIV = 2; //Divide Fvco by 4
//The DIVSWEN bit controls changes to the VCO divider.
//Request PLL1 VCO divider switch
PLL1CONbits.DIVSWEN = 1;
//Wait for PLL1 VCO divider switch to complete
while(PLL1CONbits.DIVSWEN);
//Reset CLKGEN1 dividers for 1:1 ratio
CLK1DIVbits.INTDIV = 0;
CLK1DIVbits.FRACDIV = 0;
//Request CLKGEN1 divider switch
CLK1CONbits.DIVSWEN = 1;
//Wait for divider switch to complete
while(CLK1CONbits.DIVSWEN);
CLK1CONbits.NOSC = 5; //Set PLL1 Fout as CPU clock source
CLK1CONbits.OSWEN = 1; //Request clock switch
while (CLK1CONbits.OSWEN); //Wait for switch to complete
//Configure CLKGEN5 to provide a 125MHz PWM MCLK
CLK5CONbits.ON = 1; //Enable CLKGEN5, if not already enabled
CLK5DIVbits.INTDIV = 1; //Divide input clock by 2
CLK5DIVbits.FRACDIV = 0;
//Request CLKGEN5 divider switch
CLK5CONbits.DIVSWEN = 1;
//Wait for CLKGEN5 divider switch to complete
while(CLK5CONbits.DIVSWEN);
CLK5CONbits.NOSC = 7; //Use divided PLL1 VCO (250MHz)
CLK5CONbits.OSWEN = 1; //Request clock switch
while(CLK5CONbits.OSWEN); //Wait for switch to complete
PCLKCONbits.MCLKSEL = 1; //Use CLKGEN5 as PWM MCLK source
//Configure CLKGEN6 to provide a 250MHz input clock to the ADC
CLK6CONbits.ON = 1; //Enable CLKGEN6, if not already enabled
//Reset CLKGEN6 dividers for 1:1 ratio
CLK6DIVbits.INTDIV = 0;
CLK6DIVbits.FRACDIV = 0;
//Request CLKGEN6 divider switch
CLK6CONbits.DIVSWEN = 1;
//Wait for CLKGEN6 divider switch to complete
while(CLK6CONbits.DIVSWEN);
CLK6CONbits.NOSC = 7; //Use divided PLL1 VCO (250MHz)
CLK6CONbits.OSWEN = 1; //Request clock switch
while (CLK6CONbits.OSWEN); //Wait for switch to complete
//Configure CLKGEN11 to provide a 125MHz clock for the PTG.
CLK11CONbits.ON = 1; //Enable CLKGEN10, if not already enabled
CLK11DIVbits.INTDIV = 1; //Divide input clock by 2
CLK11DIVbits.FRACDIV = 0;
//Request CLKGEN11 divider switch
CLK11CONbits.DIVSWEN = 1;
//Wait for CLKGEN11 divider switch to complete
while(CLK11CONbits.DIVSWEN);
CLK11CONbits.NOSC = 7; //Use divided PLL1 VCO (125MHz)
CLK11CONbits.OSWEN = 1; //Request clock switch
while (CLK11CONbits.OSWEN); //Wait for switch to complete
}
void PTG_initialize() {
//Enable PTG interrupts 0 and 1
_PTG0IE = 1;
_PTG1IE = 1;
//Set up control registers
PTGT0LIM = 625; //5us T0 delay
PTGT1LIM = 125; //1us T1 delay
PTGC0LIM = 24; //Repeat C0 loop 25 times
PTGC1LIM = 1; //Repeat C1 loop once
PTGHOLD = 625; //5us (used to restore T0 delay)
PTGADJ = 125; //1us (added to T0 delay)
PTGQPTR = 0; //Initialize step queue pointer
//Outer loop
PTGQUE0bits.STEP0 = PTGWHI(0); // Wait for positive edge trigger 0 (PWM1 ADC Trigger 2)
PTGQUE0bits.STEP1 = PTGCTRL(t0Wait); // Start PTGT0, wait for time out
PTGQUE0bits.STEP2 = PTGIRQ(0); // Generate IRQ 0
// Inner loop
PTGQUE0bits.STEP3 = PTGTRIG(12); // Generate output trigger 12 (ADC conversion)
PTGQUE1bits.STEP4 = PTGCTRL(t1Wait); // Start PTGT1, wait for time out
PTGQUE1bits.STEP5 = PTGJMPC0(3); // Go to STEP3 if PTGC0 != PTGC0LIM, increment PTGC0 (ie. repeat steps 3-5 24 times)
// End inner loop
PTGQUE1bits.STEP6 = PTGADD(t0Limit); // Add PTGADJ to PTGT0LIM
PTGQUE1bits.STEP7 = PTGJMPC1(0); // Jump to 0 PTGC1LIM times (once, making 2 iterations)
// End outer loop
PTGQUE2bits.STEP8 = PTGIRQ(1); // Generate IRQ 1
PTGQUE2bits.STEP9 = PTGCOPY(t0Limit);
See PTG Command Definitions for PTG command definitions. See PTGCTRL Options and Options for PTGADD and PTGCOPY Commands for PTGCTRL
, PTGADD
and
PTGCOPY
command options.