Electronic – Using multiple external interrupts in PIC

interruptsmicrochipmicrocontrollerpicprogramming

I've used PIC16F877 (datasheet) for several projects. For a single external pin change interrupts, you can use PORTB0 interrupt. But now I need to support 8 independent external pin change interrupts, in a single circuit.

In the datasheet it says there are 15 interrupts in PIC16F877, but i guess those are counted including timer overflow interrupts etc… which are useless in this case.

This is what datasheet say about INTCON register.

enter image description here

Can I have 4 independent interrupts using bit0, RBIF? It represent change in PB7:PB4. How can I identify which pin changed, is it by reading the port value in the interrupt routine?

Even I get positive answers to above, I need 8 interrupts? of course I can still use INTE, for PORTB0 change. Then 4 + 1 = 5, but what about other 3? (However being all the 8 interrupt events are of same type, the 4 + 1 + 3 = 8 thing seems ugly, isn't it?)

There's no other heavy tasks expected from the micro-controller other that monitoring 8 pins. (Talking about the other tasks, it'll have to maintain a set of separate counter variables and frequently transmit about 4 bytes to PC serially)

Any suggestions are welcome. Even if it's about changing the micro-controller for more suited one (but uh.. don't tell me to go away from PICs).

Best Answer

This is C pseudo-code to explain one idea. It uses and exclusive OR to work out which pins have changed and will call your different handlers within the one RBIE interrupt. Depending on how critical the application is you may want to check how the PIC handles situations such as a port changing while the interrupt is executing to make sure you won't miss any events.

int old_port_b;

void isr_handler()
{
    int new_port_b, changed_pins;
    new_port_b = read_port_b();
    changed_pins = new_port_b ^ old_port_b;
    if (changed_pins | 1)
        rb0_hander();
    if (changed_pins | 2)
        rb1_hander();
        // ... etc
    old_port_b = new_port_b;
}

int main()
{
    old_port_b = read_port_b();
    enable_interrupt();
}