Gain Error Calibration Example
#include <xc.h>
// The channel output.
long result = 0;
// Gain compensation coefficient.
long coefficient;
// Oscillator initialization procedure.
void OscillatorInitialization();
int main(){
// Initialize the oscillator.
// Clock generator 6 should provide 320MHZ to the ADCs.
OscillatorInitialization();
// Enable ADC.
AD1CONbits.ON = 1;
// Wait when ADC will be ready/calibrated.
while(AD1CONbits.ADRDY == 0);
////////////////////////////////////////////////////////////////////
// GET A COEFFICIENT FOR THE GAIN ERROR COMPENSATION
////////////////////////////////////////////////////////////////////
// Select oversampling mode.
AD1CH1CONbits.MODE = 3;
// 256 conversions
AD1CH1CONbits.ACCNUM = 3;
// Software trigger will start a conversion.
AD1CH1CONbits.TRG1SRC = 1;
// Back-to-back conversions
AD1CH1CONbits.TRG2SRC = 2;
// Select the AN14 input which is connected to 15/16 of AVDD
AD1CH1CONbits.PINSEL = 14;
// Select signal sampling time (6.5 TADs = 81nS @ 80MHZ ADC clock).
AD1CH1CONbits.SAMC = 3;
// Average 256 results of the reference voltage
AD1SWTRGbits.CH1TRG = 1;
// Wait when the result is ready
while(AD1STATbits.CH1RDY == 0);
// Oversampling result is 16 Bit (has additional 4 bits).
// Calculate the gain compensation coefficient.
// The coefficient is in fixed-point format (18 bits before point).
coefficient = (long)(3840.0*16.0*(1<<18)/AD1CH1DATA);
////////////////////////////////////////////////////////////////////
// CONVERT AND COMPENSATE THE GAIN ERROR
////////////////////////////////////////////////////////////////////
// Clean channel register for new settings.
AD1CH1CON = 0;
// Select single conversion mode.
AD1CH1CONbits.MODE = 0;
// Software trigger will start a conversion.
AD1CH1CONbits.TRG1SRC = 1;
// Select the AN7 input for conversions
AD1CH1CONbits.PINSEL = 7;
// Select signal sampling time (6.5 TADs = 81nS @ 80MHZ ADC clock).
AD1CH1CONbits.SAMC = 3;
// Trigger channel #1 in software and wait for the result.
while(1){
// Trigger channel # 1.
AD1SWTRGbits.CH1TRG = 1;
// Wait for a conversion ready flag.
while(AD1STATbits.CH1RDY == 0);
// Read result. It will clear the conversion ready flag.
// The gain error correction coefficient is in fixed-point format (18 bits before point).
result = (coefficient*AD1CH1DATA)>>18;
}
return 1;
}
void OscillatorInitialization(){
PLL1CONbits.ON = 1;
OSCCTRLbits.PLL1EN = 1;
while(OSCCTRLbits.PLL1RDY == 0);
PLL1CONbits.FSCMEN = 0; // disable clock fail monitor
VCO1DIVbits.INTDIV = 1; // 1:2 = 320MHz
PLL1DIVbits.PLLFBDIV = 80; // VCO = 640 MHz
PLL1DIVbits.PLLPRE = 1;
PLL1DIVbits.POSTDIV1 = 4;
PLL1DIVbits.POSTDIV2 = 1;
PLL1CONbits.DIVSWEN = 1;
while(PLL1CONbits.DIVSWEN == 1);
PLL1CONbits.NOSC = 1; // FRC
PLL1CONbits.OSWEN = 1;
while(PLL1CONbits.OSWEN == 1);
PLL1CONbits.FOUTSWEN = 1;
while(PLL1CONbits.FOUTSWEN == 1);
PLL1CONbits.PLLSWEN = 1;
while(PLL1CONbits.PLLSWEN == 1);
while(PLL1CONbits.CLKRDY == 0);
CLK1CONbits.NOSC = 5; // PLL1
CLK1CONbits.OSWEN = 1;
while(CLK1CONbits.OSWEN == 1);
while(CLK1CONbits.CLKRDY == 0);
// ADC high speed clock (Generator 6), should be 320 MHz for 80MHz operation
CLK6CONbits.ON = 1;
CLK6CONbits.NOSC = 7; // PLL1 VCO divider
CLK6CONbits.OSWEN = 1;
while(CLK6CONbits.OSWEN == 1);
while(CLK6CONbits.CLKRDY == 0);
}