DsPIC33E comparator interrupt doesn’t occur

comparatorinterruptsisrpic

I'm currently trying to get the comparator on dsPIC33EP256GP502 works, but get stuck in the comparator interrupt. Basically what i want to do is just using the comparator to compare two external voltage inputs, and generate the interrupt upon the low-to-high transition of the comparator output is detect, but the program has never enter the ISR in the test.

i have tried to manually set the interrupt flag(IFS1bits.CMIF) to 1 in the main loop, then the interrupt has been successfully triggered, and entered the ISR, and in the ISR i have tested, the below interrupt condition is fulfilled:

CMSTATbits.C1EVT = 1 and CMSTATbits.C1OUT = 1

I just don't know why the interrupt cannot be triggered automatically when the preconditions are fulfilled, maybe there are some setting errors ?

I really need suggestions and instruction as i have already wasted so much time on this issue.

Any suggestions are greatly appreciated, and thanks in advance.

I paste my code for setting the comparator below:

   // comparator 1 input pin set
    ANSELBbits.ANSB2 = 1; // C1IN1+ ANALOG
    TRISBbits.TRISB2 = 1; // C1IN1+ INPUT
    ANSELBbits.ANSB3 = 1; // C1IN1- ANALOG
    TRISBbits.TRISB3 = 1; // C1IN1- INPUT

    // COMPARATOR 1
    CM1CONbits.COE = 0;         // comparator output is internal only
    CM1CONbits.CPOL = 1;        // comparator output is inverted
    CM1CONbits.OPMODE = 0;      // Op Amp is disabled
    CM1CONbits.CEVT = 0;        // clear comparator event bit
    CM1CONbits.COUT = 0;        // initially the Vin+ > Vin-
    CM1CONbits.EVPOL = 0b01;    // interrupt is generated only on low-to-high transition of the comparator output
    CM1CONbits.CREF = 0;        // VIN+ input connects to C1IN1+
    CM1CONbits.CCH = 0b00;      // select VIN- input connects to C1IN1-
    CM1CONbits.CON = 1;         // enable comparator 1

    CM1FLTRbits.CFLTREN = 0;    // disablt the digital filter

    CMSTATbits.PSIDL = 0; // continues operation of all comparators in idle mode

    IPC4bits.CMIP = 4; // set interrupt priority to 4
    IFS1bits.CMIF = 0; // clear the intrrupt flag
    IEC1bits.CMIE = 1; // Enable the interrupt
    INTCON2bits.GIE = 1 // Enable the global interrupt

// ISR
void __attribute__((interrupt,no_auto_psv)) _CM1Interrupt(void)
{
    IFS1bits.CMIF = 0;

    // IF INTERRUPT FROM CM1
    if(CMSTATbits.C1EVT && CMSTATbits.C1OUT)
    {
        CM1CONbits.CEVT = 0;
        CM1CONbits.COUT = 0;

        // Turn off the valve1 PWM output
        set_valve_channel_one_pwm_off();
    }
}

Best Answer

Actually what Oleg Mazurov said is somewhat right, there is only one comparator event been generated, but it is not because of the way i'm doing the test. The reason is that the comparator enabling(CON = 1) is several lines of code ahead of the comparator interrupt enabling(CMIE = 1), which will lead to one even been triggered and set the CEVT bit as the initial transition of C1OUT before the comparator interrupt enabling, but the copmparator interrupt flag will not be set to enter the ISR as the interrupt is not enabled now, without entering the ISR the CEVT bit won't be cleared, which will block all the rest comparator events as the CEVT bit haven't been cleared.

So the solution is that put the comparator enable and interrupt enable codes side by side:

CM1CONbits.CON = 1; // enable comparator 1
IEC1bits.CMIE = 1; // Enable the interrupt

or clear the CEVT bit before enable the interrupt:

CM1CONbits.CEVT = 0; // clear comparator event bit
IEC1bits.CMIE = 1; // Enable the interrupt