I'm having trouble getting the analogue comparator working on a dsPIC33EP512MU810. I want to compare two external voltages. Connected to C1IN1+ is my reference voltage (1.5V) and C1IN1- is my variable voltage (1.1 - 1.9V). I've set the Event trigger to be generated on both rising edge and falling edge but I only get an interrupt when the program starts and nothing after that.
// Macro to provide an indicator of when the ISR is running on a digital output pin (G6).
#define MONIT_1 (LATGbits.LATG6)
// Configuration registers.
_FGS(GSSK_OFF);
_FOSCSEL(FNOSC_PRIPLL & IESO_ON);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT & IOL1WAY_OFF);
_FWDT(FWDTEN_OFF);
_FPOR(BOREN_ON);
_FICD(ICS_PGD2);
_FAS(APLK_OFF);
// The SYS_OSCSEL bits are written to the OSCCON.NOSC bits to select a new
// oscillator and read from the OSCCON.COSC bits to determine the current
// oscillator.
#define SYS_OSCSEL 0b011 // 011 = Primary Oscillator with PLL (XTPLL, HSPLL, ECPLL)
#define SYS_FIN 8000000LL // clock-frequecy in Hz with suffix LL (64-bit-long)
#define SYS_PLLPRE 0
#define SYS_PLLPOST 1
#define SYS_PLLDIV 38
#define SYS_FVCO ((SYS_FIN * (SYS_PLLDIV + 2)) / (SYS_PLLPRE + 2))
#define SYS_FOSC (SYS_FVCO / (2 * (SYS_PLLPOST + 1)))
#define SYS_FCY (SYS_FOSC/2)
// bit 0 OSWEN: Oscillator Switch Enable bit
#define OSCCON_OSWEN (0x0001)
// bit 5 LOCK: PLL Lock Status bit (read-only)
#define OSCCON_LOCK (0x0020)
// bit 6 IOLOCK: Peripheral Pin Select (PPS) Lock bit
#define OSCON_IOLOCK (0x0040)
static volatile int _cout; // To capture the comparator output during the ISR.
int main(int argc, char** argv)
{
// Set up PLL to give Fosc = 40MHz from an 8MHz Crystal.
CLKDIVbits.PLLPRE = SYS_PLLPRE;
CLKDIVbits.PLLPOST = SYS_PLLPOST;
PLLFBDbits.PLLDIV = SYS_PLLDIV;
CLKDIVbits.DOZEN = 0; // No Doze
CLKDIVbits.ROI = 0; // not setting recover on interrupt
// Switch to PLL mode from XT.
__builtin_write_OSCCONH(SYS_OSCSEL);
__builtin_write_OSCCONL(OSCCON | 0x01);
// Wait for Clock switch to occur
while (OSCCON_OSWEN & OSCCON);
// Wait for PLL to lock
while (OSCCONbits.LOCK != 1);
// Wait for Oscillator to match
while (OSCCONbits.COSC != OSCCONbits.NOSC);
// PIN20, C1IN1+ as analogue reference pin, VBUS -> PL1.PIN20
ANSELBbits.ANSB5 = 1;
TRISBbits.TRISB5 = 1;
// PIN11, C1IN1- as analogue voltage pin for VM1 -> PL1.PIN11
ANSELGbits.ANSG7 = 1;
TRISGbits.TRISG7 = 1;
// PIN10: digital MONIT_1
ANSELGbits.ANSG6 = 0;
TRISGbits.TRISG6 = 0;
MONIT_1 = 0;
// Disable comparator
CM1CONbits.CON = 0;
// Continue operation in idle mode.
CMSTATbits.CMSIDL = 0;
// Comparator output is internal only
CM1CONbits.COE = 0;
// Comparator input is not inverted
CM1CONbits.CPOL = 0;
// Trigger/event/interrupt is generated on any change of the comparator output (while CEVT = 0)
CM1CONbits.EVPOL = 0b11;
// Comparator reference input selection. VIN+ input connects to external C1IN1+ pin
CM1CONbits.CREF = 0;
// Comparator channel selection. VIN- input connects to external C1IN1- pin
CM1CONbits.CCH = 0b00;
// Enable comparators
CM1CONbits.CON = 1;
// Enable comparator interrupts
IEC1bits.CMIE = 1;
// Enable the global interrupt
INTCON2bits.GIE = 1;
// Clear comparator interrupt flag
IFS1bits.CMIF = 0;
// Clear this value to enable future triggers and interrupts.
CM1CONbits.CEVT = 0;
while(1)
{
Nop();
}
return (EXIT_SUCCESS);
}
void __attribute__ ((__interrupt__,no_auto_psv)) _CM1Interrupt(void)
{
MONIT_1 = 1; // Turn the G6 IO on.
// Clear comparator interrupt flag
IFS1bits.CMIF = 0;
// Check if comparator event 1 occurred.
if (CM1CONbits.CEVT > 0)
{
_cout = CM1CONbits.COUT;
// Clear comparator events to trigger the next event.
CM1CONbits.CEVT = 0;
}
MONIT_1 = 0; // Turn the G6 IO off.
}