Domanda

I have some code below that has a slight bug that I don't know how to fix. Essentially what is happening is my high ISR is running twice after the the flag is set. It only runs twice and is consistent. The subroutine should run only once because the flag is set when the input on RB changes, and the routine runs twice after one change to RB's input. The testing was conducted in MPLAB v8.6 using the workbook feature.

#include <p18f4550.h>
#include <stdio.h>  

void init(void)
{   
    RCONbits.IPEN =1;       //allows priority    
    INTCONbits.GIE = 1;     //allows interrupts
    INTCONbits.PEIE = 1;    //allows peripheral interrupts
    INTCONbits.RBIF = 0;  //sets flag to not on
    INTCONbits.RBIE = 1; //enables RB interrupts
    INTCON2bits.RBPU = 1; //enable pull up resistors
    INTCON2bits.RBIP = 1;   //RB interrupts is high priority
    PORTB = 0x00;  
    TRISBbits.RB7 = 1; //enable RB7 as an input so we can throw interrupts when it changes. 
}

#pragma code
#pragma interrupt high_isr
void high_isr(void)
{
    if(INTCONbits.RBIF == 1)
    {
        INTCONbits.RBIF = 0;  
        //stuff
    }
}

#pragma code    
#pragma code high_isr_entry = 0x08
void high_isr_entry(void)
{_asm goto high_isr _endasm}


void main(void)
{
    init();
    while(1);   
}   
È stato utile?

Soluzione

The RB7 interrupt flag is set based on a compare of the last latched value and the current state of the pin. In the datasheet it says "The pins are compared with the old value latched on the last read of PORTB. The 'mismatch' outputs of RB7:RB4 are ORed together to generate the RB Port Change Interrupt with Flag bit."

To clear the mismatch condition the datasheet goes on to say "Any read or write of PORTB (except with the MOVFF (ANY), PORTB instruction). This will end the mismatch condition."

You then wait one Tcy (execute a nop instruction) and then clear the flag. This is documented on page 116 of the datasheet.

So the simplest fix in this scenario is in the interrupt routine declare a dummy variable and set it to RB7 like this:

#pragma interrupt high_isr
void high_isr(void)
{
    unsigned short dummy;

    if(INTCONbits.RBIF == 1)
    {
        dummy = PORTBbits.RB7;  // Perform read before clearing flag
        Nop();
        INTCONbits.RBIF = 0;
        // rest of your routine here
        // ...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top