dsPIC33A Peripheral Trigger Generator (PTG) Peripheral

Last modified by Microchip on 2025/09/23 09:59

Overview

This page covers the dsPIC33A Peripheral Trigger Generator (PTG), a module that coordinates peripheral operations without CPU intervention, reducing overhead and improving system efficiency. The PTG uses a programmable sequencer with a 32-step command queue, can process up to 16 hardware and one software input triggers, and can generate up to 32 output triggers (though most are reserved). It also supports up to 18 interrupts, two general-purpose timers, and a dedicated Watchdog Timer (WDT). 

The PTG operates by executing step commands that control input events, flow, and output generation. It connects with various peripherals, receiving triggers from modules like Pulse Width Modulation (PWM) and SCCP, and sending triggers to Analog-to-Digital Converter (ADC) and Peripheral Pin Select (PPS). Setup involves configuring the clock, related peripherals, PTG control registers, and loading the step command queue before enabling the PTG. 

There are four operating modes: Disabled, Halt, Running, and Single-Step (for debugging). The dsPIC33A PTG is mostly compatible with the dsPIC33C version, with similar step commands and trigger assignments, but some differences in ADC trigger handling and register size. 

Interrupts include individual Interrupt Requests (IRQs) for scheduled CPU actions, a step interrupt for debugging, and a WDT interrupt for error detection. Typical applications include generating phase-shifted PWM waveforms, interleaving ADC samples for power calculations, and ratioed sampling of different ADC channels at various rates, all synchronized with external signals. By using the PTG, you can automate and synchronize complex peripheral tasks efficiently. 

Features

  • User programmable sequencer using step commands
    • Step queue depth is 32 entries
  • Up to 16 hardware input triggers
    • Level or edge-sensitive, polarity selectable
  • One software input trigger
  • Up to 32 unique output trigger signals
  • Up to 18 interrupts
    • Up to 16 individual interrupt requests
    • PTG WDT interrupt
    • PTG Step interrupt
  • Two 16-bit general-purpose timers
  • Selectable clock

Comparison to the dsPIC33C Version

dsPIC33CdsPIC33A
All control registers are 16-bitAll registers are 32-bit (PTGHOLD, PTGTxLIM, PTGCxLIM, PTGADJ, and PTGL0 only have 16 bits implemented)
Peripheral runs off the clock selected in PTG registers; SFRs are on the peripheral clockPeripheral runs off the clock from dedicated CLKGEN, SFRs are on slow bus (1:4)
Strobe output can trigger ADC channel conversionsStrobe output is N/C, as ADC controller does not support it
Most output triggers are reserved/not implementedMost output triggers are reserved/not implemented

Back to Top

Peripheral Architecture

The PTG module is a user-programmable sequencer for generating complex peripheral trigger sequences. The PTG module provides the ability to schedule complex peripheral operations, which would be difficult or impossible to achieve via a software solution.

The user writes 8-bit commands, called step commands, to the PTG Queue registers (PTGQUE0-PTGQUE7). Each 8-bit step command is made up of a command code (CMD[3:0]) and an option field (OPTION[3:0]). Based on the commands, the PTG can interact with other peripherals, such as the PWM, ADC, SCCP/MCCP, and PPS. See the device-specific data sheet for the availability of peripherals.

Peripheral Architecture
Click image to enlarge.

Backwards Compatibility

This PTG module is partially backward compatible with the dsPIC33C PTG version:

  • Step commands are identical
  • Similar trigger assignments
    • ADC triggers have functional differences due to new ADC controller
      • One output trigger is dedicated to ADC
      • One PPS output trigger can be routed as an ADC trigger
      • With dsPIC33A ADC controller, one trigger can trigger many channel conversions at same time
  • Strobe output is not connected
  • Timing of programs may be different due to clocking changes
  • Output triggers used by legacy dsPIC33E peripherals remain reserved

Basic Setup

  • Select clock
    • Need to configure the assigned clock generator
  • Configure any other peripherals that the PTG interacts with
  • Configure settings in PTGCON, for example:
    • Trigger output pulse width
    • Internal register visibility
    • WDT timeout
    • Input trigger operation
  • Populate step command queue
  • Enable PTG and start executing commands
    • Set PTGCON.ON = 1
    • Then set PTGCON.PTGSTRT = 1
    • But not in the same write cycle

Clock Subsystem

  • PTG is on ¼ speed SFR bus
  • PTG clocked from a dedicated clock generator module
    • Clock generator instance will vary by device
    • To set up the clock, configure the respective clock generator registers
      • CLKnCON, CLKnDIV
      • If a PLL-derived clock is used, need to configure its registers
        • PLLnCON, PLLnDIV, VCOnDIV
  • Clock selection considerations will be application-specific

Operating Modes

  • Disabled (PTGCON.ON = 0)
    • Control registers can be freely written in this mode
  • Halt (PTGCON.ON = 1, PTGCON.PTGSTRT = 0)
    • Must be in this state to set PTGSTRT = 1
  • Running (PTGCON.ON = 1, PTGCON.PTGSTRT = 1)
    • Actively executing step commands
    • Control registers are read-only
  • Single-Step (PTGCON.PTGSSEN = 1)
    • Can only be entered while debugging
    • PTG will execute a single command, then halt, every time PTGSTRT is set

Interrupts

The PTG generates three types of interrupts: the individual interrupt requests, the PTG Step interrupt and the PTG Watchdog Timer time-out interrupt.

Individual Interrupt Requests

  • Individual IRQs are generated with the PTGIRQ step command
  • Can be used to make the CPU take action at scheduled times
  • Up to 16 interrupts may be supported
  • Existing devices typically have 4 – 8 implemented

PTG Step Interrupt

  • Indicates a step command has executed in Single-Step mode
  • Only occurs in Single-Step mode
  • Device is programmed in debug mode and halted where PTGSTRT = 0
  • PTGSSEN is set using the debugging tool
  • PTGSTRT is set to execute one command, then is hardware-cleared
  • Can be used for debugging purposes

PTG WDT Interrupt

  • Interrupt happens when the PTG’s WDT times out
  • Indicates that an expected external trigger did not occur
  • Useful for observing the error condition and/or taking corrective action

Back to Top

Example Applications

Phase Shifted PWM Waveforms

  • Example #1, revised from the dsPIC33E FRM: (DS70000669C)
  • Using PWM instead of SCCP peripheral
    • Route signals with PPS such that PTG triggers a Peripheral Component Interconnect (PCI)
    • Delay added before triggering second PWM
  • Using the PTG timer delay allows the phase shift between the two PWMs to be programmable
Phase shifted PWM waveforms
Click image to enlarge.

Steps for making a phase shifted PWM waveform

Interleaving Samples over Multiple Cycles

  • Average power calculation
    • Voltage and current are measured using two ADC channels 
  • PWM cycle triggers PTG
  • PTG triggers a series of ADC conversions
    • Clocking setup is important to maintain synchronization
  • Average power is computed every two PWM cycles
Interleaving sample waveform
Click image to enlarge.

Ratioed Sampling

The following figure shows an application example of sampling an ADC input at a fast rate (1× rate), a second analog input at a slower rate (1/2 rate), and four other inputs at a 1/8 rate. The example is a motor control application using a Silicon Controlled Rectifier (SCR) that triggers at a specified time after the AC line zero-crossing.

While this example uses the simple binary sampling ratios, the PTG module can generate a very wide range of sample ratios to meet the requirements of an application. This example demonstrates coordination between the PTG, ADC, PWM, and PPS to achieve the required sampling rates.

Waveform for sampling ADC channels at 3 different rates using PTG to coordinate the timing

Ratioed Sampling Step Command Program

This section describes the step command programming for implementing the timing sequence shown in the previous figure. The following assumptions are made:

  • Trigger Input 15 is connected to the Zero-Crossing Detect signal
    • The rising edge of the Zero-Crossing Detect signal starts the sequence
  • Trigger Output 24 enables the SCR in the application circuit
  • The trigger delay from Trigger Input 15 to the generation of Trigger Output 24 is 2 ms
  • Trigger Output 26 is connected to PWM1’s synchronization signal
  • PWM1 is configured to trigger the ADC to sample at 1/2x rate, and it is configured to trigger PWM2 which will sample the ADC at 1x rate
  • Trigger Output 12 is connected to the ADC to sample other data values (channels 0, 1, 2, and 3) once per cycle
  • The PTG clock is 8 MHz
#include <xc.h>
void clocks_initialize() {
//Configure CLKGEN5 to provide an 8MHz clock for the PWM
CLK5CONbits.ON = 1; //Enable CLKGEN5, if not already enabled
//Reset CLKGEN5 dividers for 1:1 ratio
CLK5DIVbits.INTDIV = 0;
CLK5DIVbits.FRACDIV = 0;
CLK5CONbits.DIVSWEN = 1;
//Wait for divider switch to complete
while(CLK5CONbits.DIVSWEN);
CLK5CONbits.NOSC = 1; //Select FRC, 8MHz
CLK5CONbits.OSWEN = 1; //Request clock switch
while (CLK5CONbits.OSWEN); //Wait for switch to complete
PCLKCONbits.MCLKSEL = 1; //Use CLKGEN5 for PWM clock
PLL1CONbits.ON = 1; //Enable PLL generator 1, if not already enabled
//Set up PLL1
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;
CLK1CONbits.DIVSWEN = 1;
//Wait for divider switch to complete
while(CLK1CONbits.DIVSWEN);
CLK1CONbits.NOSC = 1; //Set FRC as CPU clock source
CLK1CONbits.OSWEN = 1; //Request clock switch
while (CLK1CONbits.OSWEN); //Wait for switch to complete
//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;
CLK6CONbits.DIVSWEN = 1;
//Wait for divider switch to complete
while(CLK6CONbits.DIVSWEN);
CLK6CONbits.NOSC = 7; //Set PLL1 VCODIV as ADC clock source
CLK6CONbits.OSWEN = 1; //Request clock switch
while (CLK6CONbits.OSWEN); //Wait for switch to complete
//Configure CLKGEN11 to provide an 8MHz clock for the PTG
CLK11CONbits.ON = 1; //Enable CLKGEN10, if not already enabled
//Reset CLKGEN11 dividers for 1:1 ratio
CLK11DIVbits.INTDIV = 0;
CLK11DIVbits.FRACDIV = 0;
//Request CLKGEN11 divider switch
CLK11CONbits.DIVSWEN = 1;
//Wait for divider switch to complete
while(CLK11CONbits.DIVSWEN);
CLK11CONbits.NOSC = 1; //Select FRC, 8MHz
CLK11CONbits.OSWEN = 1; //Request clock switch
while (CLK11CONbits.OSWEN); //Wait for switch to complete
}
void PTG_initialize() {
PTGT0LIM = 16000; // 2 ms T0 delay
PTGT1LIM = 8000; // 1 ms T1 delay
PTGC0LIM = 2; // 3 iterations of the C0 loop
PTGQPTR = 0; //Initialize step queue pointer
//Initialize Step registers
PTGQUE0bits.STEP0 = PTGWHI(15); // Wait for trigger from INT2 (zero
crossing detect)
PTGQUE0bits.STEP1 = PTGTRIG(12); // Take 1/8 rate samples using ADC
trigger 30
PTGQUE0bits.STEP2 = PTGCTRL(t0Wait); // Wait 2ms
PTGQUE0bits.STEP3 = PTGTRIG(24); // Trigger PPS output 55 (SCR)
PTGQUE1bits.STEP4 = PTGCTRL(t1Wait); // Wait1ms before starting the 1x
and 1/2x triggers
PTGQUE1bits.STEP5 = PTGTRIG(26); // Trigger PWM1 to trigger
conversions at 1x and 1/2x rates
//Start main loop
PTGQUE1bits.STEP6 = PTGCTRL(t0Wait); // Wait2ms (pre-trigger delay) for
subsequent triggers
PTGQUE1bits.STEP7 = PTGTRIG(26); // Trigger PWM1 to trigger ADC
conversions at 1x and 1/2x rates
PTGQUE2bits.STEP8 = PTGJMPC0(6); // Jump to step 6 (twice, for 3
iterations total)
//End main loop
PTGQUE2bits.STEP9 = PTGJMP(0);
//Start the PTG
PTGCONbits.ON = 1;
PTGCONbits.PTGSTRT = 1;
}
void ADC_initialize() {
//Enable analog inputs AD1AN0 - AD1AN5
_ANSELA2 = 1;
_ANSELA4 = 1;
_ANSELA6 = 1;
_ANSELA5 = 1;
_ANSELB1 = 1;
_ANSELB3 = 1;
//Enable ADC
AD1CONbits.ON = 1;
while(!AD1CONbits.ADRDY);
//Assign ADC inputs to core 1 channels 0 - 5
AD1CH0CON1bits.MODE = 0; //Single-sample mode
AD1CH0CON1bits.PINSEL = 0; //Positive input is AD1AN0/RA2
AD1CH0CON1bits.NINSEL = 0; //Single-ended mode
AD1CH1CON1bits.MODE = 0; //Single-sample mode
AD1CH1CON1bits.PINSEL = 1; //Positive input is AD1AN1/RA4
AD1CH1CON1bits.NINSEL = 0; //Single-end

Back to Top