38.4.1 Digital Comparator
The ADC module features digital comparators that can be used to monitor selected analog input conversion results and generate interrupts when a conversion result is within the user-specified limits. Conversion triggers are still required to initiate conversions. The comparison occurs automatically once the conversion is complete. This feature is enabled by setting the Digital Comparator Module Enable bit, ENDCMP (ADCCMPCONx[7]).
The user application makes use of an interrupt that is generated when the analog-to-digital conversion result is higher or lower than the specified high and low limit values in the ADCCMPx register. The high and low limit values are specified in the DCMPHI[15:0] bits (ADCCMPx[31:16]) and the DCMPLO[15:0] bits (ADCCMPx[15:0]).
- When IEBTWN =
1
, an interrupt is generated when DCMPLO ≤ ADCDATA < DCMPHI - When IEHIHI =
1
, an interrupt is generated when DCMPHI ≤ ADCDATA - When IEHILO =
1
, an interrupt is generated when ADCDATA < DCMPHI - When IELOHI =
1
, an interrupt is generated when DCMPLO ≤ ADCDATA - When IELOLO =
1
, an interrupt is generated when ADCDATA < DCMPLO
The comparator event generation is illustrated in the following figure. When the ADC module generates a conversion result, the conversion result is provided to the comparator. The comparator uses the DIFFx and SIGNx bits of the ADCIMCONx register (depending on the analog input used) to determine the data format used and to appropriately select whether the comparison must be signed or unsigned. The global ADC setting, which is specified by the FRACT bit (ADCCON1[23]), is also used to set the fractional or integer format. The digital comparator compares the ADC result with the high and low limit values (depending on the selected comparison criteria) in the ADCCMPx register.
Depending on the comparator results, a digital comparator interrupt event may be generated. If a comparator event occurs, the Digital Comparator Interrupt Event Detected status bit, DCMPED (ADCCMPCONx[5]), is set, and the Analog Input Identification (ID) bits, AINID[4:0] (ADCCMPCONx[12:8]), are automatically updated so that the user application knows which analog input generated the interrupt event.
The following code is an example for ADC digital comparator.
int main(int argc, char** argv) {
int result = 0, eventFlag = 0;
/* Configure ADCCON1 */
ADCCON1 = 0; // No ADCCON1 features are enabled including: Stop-in-Idle,
// turbo, CVD mode, Fractional mode and scan trigger source. ADCCON1bits.SELRES = 3; // ADC resolution is 12 bits
ADCCON1bits.STRGSRC = 0; // No scan trigger.
/* Configure ADCCON2 */
ADCCON2bits.SAMC = 5; // ADC7 sampling time = 5 * TAD7
ADCCON2bits.ADCDIV = 1; // ADC7 clock freq = TAD7
/* Initialize warm up time register */ ADCANCON = 0;
/* No selection for dedicated ADC modules, no presync trigger, not sync sampling */ ADCTRGMODEbits = 0;
/* Select ADC input mode */
ADCIMCON1bits.SIGN8 = 0; // unsigned data format
ADCIMCON1bits.DIFF8 = 0; // Single ended mode
/* Configure ADCGIRQENx */
ADCGIRQEN1 = 0; // No interrupts are used
ADCGIRQEN2 = 0;
/* Configure ADCCSSx */
ADCCSS1 = 0; // No scanning is used
ADCCSS2 = 0;
/* Configure ADCCMPCONx */
ADCCMP1 = 0; // Clear the register ADCCMP1bits.DCMPHI = 0xC00; // High limit is a 3072 result. ADCCMP1bits.DCMPLO = 0x500; // Low limit is a 1280 result. ADCCMPCON1bits.IEBTWN = 1; // Create an event when the measured result is
// >= low limits and < high limit. ADCCMPEN1 = 0; // Clear all enable bits ADCCMPEN1bits.CMPE8 = 1; // set the bit corresponding to AN8
ADCCMPCON1bits.ENDCMP = 1; // enable comparator
ADCCMPCON2 = 0; ADCCMPCON3 = 0; ADCCMPCON4 = 0; ADCCMPCON5 = 0; ADCCMPCON6 = 0;
/* Configure ADCFLTRx */
ADCFLTR1 = 0; // No oversampling filters are used. ADCFLTR2 = 0;
ADCFLTR3 = 0; ADCFLTR4 = 0; ADCFLTR5 = 0; ADCFLTR6 = 0;
/* Set up the trigger sources */
ADCTRG3bits.TRGSRC8 = 3; // Set AN8 (Class 2) to trigger from scan source
/* Early interrupt */
ADCEIEN1 = 0; // No early interrupt
ADCEIEN2 = 0;
/* Turn the ADC on */ ADCCON1bits.ON = 1;
/* Wait for voltage reference to be stable */
while(!ADCCON2bits.BGVRRDY); // Wait until the reference voltage is ready while(ADCCON2bits.REFFLT); // Wait if there is a fault with the reference voltage
/* Enable clock to analog circuit */
ADCANCONbits.ANEN7 = 1; // Enable the clock to analog bias
/* Wait for ADC to be ready */
while(!ADCANCONbits.WKRDY7); // Wait until ADC7 is ready
/* Enable the ADC module */
ADCCON3bits.DIGEN7 = 1; // Enable ADC7
while (1) {
/* Trigger a conversion */ ADCCON3bits.GSWTRG = 1;
while (ADCDSTAT1bits.ARDY8 == 0);
/* fetch the result */
result = ADCDATA8;
/* Note: It is not necessary to fetch the result for the digital
* comparator to work. In this example we are triggering from
* software so we are using the ARDY8 to gate our loop. Reading the
* data clears the ARDY bit.
*/
/* See if we have a comparator event*/
if (ADCCMPCON1bits.DCMPED == 1) {
eventFlag = 1;
/*
* Process results here
*/
}
}
return (1);
}