15.5.7 Multiple Channels Scan

In Multiple Channels Scan Example, three channels are scanned. To scan these channels, they are triggered from the same trigger source.

Multiple Channels Scan Example

#include <xc.h>

volatile long channel_2_an1;
volatile long channel_4_an2;
volatile long channel_6_an3;

// Define peripheral clock frequency.
#define FCY (150000000UL)             // 150MHz
// Define the CCP1 timer frequency.
#define TIMER_FREQUENCY (100UL)       // 1kHz

int main() { 
    // In this example channels ## 2, 4 and 6 will be scanned.
    // To scan channels they must be triggered from one source.
    // The channel with lowest number (#2) will be converted first.
    // The channel with highest number (#6) will be converted last.
    
    // CHANNEL 2
    // Single conversion mode.
    AD1CH2CONbits.MODE = 0;
    // CCP1 Timer starts conversion (same for all scanned channels).
    AD1CH2CONbits.TRG1SRC = 12;
    // Select the AN1 analog input/pin for the channel #2.
    AD1CH2CONbits.PINSEL = 1;
    // Select signal sampling time (6.5 TADs = 81nS).
    AD1CH2CONbits.SAMC = 3;
    
    // CHANNEL 4
    // Single conversion mode.
    AD1CH4CONbits.MODE = 0;
    // CCP1 Timer starts conversion (same for all scanned channels).
    AD1CH4CONbits.TRG1SRC = 12;
    // Select the AN2 analog input/pin for the channel #4.
    AD1CH4CONbits.PINSEL = 2;
    // Select signal sampling time (8.5 TADs = 106nS).
    AD1CH4CONbits.SAMC = 4; 
    
    // CHANNEL 6
    // Single conversion mode.
    AD1CH6CONbits.MODE = 0;
    // CCP1 Timer starts conversion (same for all scanned channels).
    AD1CH6CONbits.TRG1SRC = 12;
    // Select the AN3 analog input/pin for the channel #6.
    AD1CH6CONbits.PINSEL = 3;
    // Select signal sampling time (10.5 TADs = 131nS).
    AD1CH6CONbits.SAMC = 5; 
    
    // Set ADC to RUN mode.
    AD1CONbits.MODE = 2;
    // Enable ADC.
    AD1CONbits.ON = 1;
    // Wait when ADC will be ready/calibrated.
    while(AD1CONbits.ADRDY == 0);
    
    // Configure CCP1 Timer to trigger all channels (to scan).
    CCP1CON1bits.MOD = 0;
    // Set 32-bit timer.
    CCP1CON1bits.T32 = 1;
    // Set period.
    CCP1PR = FCY/TIMER_FREQUENCY;
    // Run timer.
    CCP1CON1bits.ON = 1;
    
    // Enable channel # 6 interrupt.
    // This channel is processed last and all other channels results 
    // will be ready in the channel #6 ISR.
    _AD1CH6IE = 1;
    
    while(1); 
    
    return 1;
}

// Channel # 6 interrupt (processed last). All channels
// results in the scan are available here.
void __attribute__((interrupt)) _AD1CH6Interrupt(){
    channel_2_an1 = AD1CH2DATA;
    channel_4_an2 = AD1CH4DATA;
    channel_6_an3 = AD1CH6DATA;
    _AD1CH6IF = 0; 
}