1
\$\begingroup\$

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();
    }
}
\$\endgroup\$
  • \$\begingroup\$ Could anyone give me some suggestions or any code looks suspicious? \$\endgroup\$ – GangNanTed Jan 23 '15 at 14:44
  • \$\begingroup\$ how do you test? You need to change voltage level on one of the comparator inputs. If they stay at the same level all the time you will only get one comparator event (which you're clearing during init so you won't see it). You may also want to set COE and observe the output directly to save time. \$\endgroup\$ – Oleg Mazurov Jan 23 '15 at 18:13
  • \$\begingroup\$ Hi, i test the comparator by give a stable voltage input into the Vin-(about +1.4v), and then after the debugging is running, i instantly connect the Vin+ with a +3.3v input and hold it for a while then move it away to try to trigger the interrupt event. I have tried to enabled the COE bit and configured the C1OUT to a peripheral port, and use oscilloscope to monitor the state change of that port, but it is always voltage HIGH during the test. I don't know whether there is any other settings i need to do. \$\endgroup\$ – GangNanTed Jan 26 '15 at 8:00
  • \$\begingroup\$ but when i manually set the interrupt flag, and the +3.3v is connected to the Vin+, both CMSTATbits.C1EVT and CMSTATbits.C1OUT is set as i checked in the ISR, and as +3.3v moved away, these two bits are cleared as it should be. It is very confusing. \$\endgroup\$ – GangNanTed Jan 26 '15 at 8:01
  • \$\begingroup\$ Hi Oleg, actually what you said is somehow right, there is only one comparator event been generated, but it is not because of the way i'm doing the test. Thanks for your comment. \$\endgroup\$ – GangNanTed Jan 27 '15 at 11:31
1
\$\begingroup\$

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 
\$\endgroup\$
0
\$\begingroup\$

IFS1bits.CMPIF = 0; clear the comparator flag.

The Comparator Interrupt Flag (CMPIF) bit (IFS1<2>) is set when the synchronized output value of any of the comparators changes, with respect to the last read value. The CxEVT bits in the CMSTAT register can be read by the user application to detect an event.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.