3-6 are interrupt-on-change, so they interrupt when anything on there changes. Kevin’s code determines which pin changed by saving the old state of the port. You XOR the old port state with the current port state to see which bits have flipped and act accordingly. Then you save the current port state as the old port state (that you’ll use the next time it interrupts).
RBIF is a single bit that tells you that some bit in PORTB (the state of all the interrupt 3-6 pins) has flipped. You actually have to read PORTB before RBIF can be cleared. So now that you have the current value of PORTB, you compare it to the value of PORTB the last time something changed, and that tells you what’s changed to cause this interrupt.
couldn’t you just look at the specific pin to see if it is the pin that is activated?
such as
if(INCONbits.RBIF)
{
if(PORTBbits.RB7)
{
yadda yaddaa
}
if(PORTBbits.RB6)
{
yadda yadda
}
etc. etc.
}
I’ve been muddling through the pic18f8722 data sheet and I think that PORTB is just another set of bits that refer to the pins RB0 thru RB7. Is that a valid way to isolate the interrupts in INTCONbits.RBIF?
I think you have to read the entire port to be able to clear the flag, but reading a single pin might work. What happens is if you don’t clear the mismatch by reading the entire port, or maybe reading one pin, is the flag continues to be set over and over, and you’ll keep jumping back into your ISR. So if you try your way and get a red light of death, you’ll know why.
Second point. Your method works if you only care about 0 to 1 transitions on the pin. 1 to 0 transitions will still cause interrupts and you’ll still have to service them, however. So using interrupts 3-6 when you only care about 0 to 1 transitions is pretty wasteful of your resources and you’ll only be able to service half as many interrupts as you’d other wise be able to.
What if some other pin changed on the port and that pin was already high (it was high before and is continued to be high) that would give a false impression of that pin changing, right?
Look at Kevin Watson’s example here. Look at the way he uses the static variable “Old_Port_B” in user_rourtines_fast.c and you will begin to understand…
if (INTCONbits.RBIF && INTCONbits.RBIE) // external interrupts 3 through 6?
{
// This does two things. First we grab a copy of PORTB, which
// contains the states of the four interrupts. Secondly, reading
// this register resets an internal flag that would otherwise cause
// another interrupt to fire-off when you cleared the interrupt
// flag in the next instruction...
Port_B = PORTB;
// This clears the interrupt flag, informing the processor that you've
// handled the interrupt
INTCONbits.RBIF = 0;
// This line of code updates a variable using the exclusive-or operation.
// If the state of one of the interrupts has changed between the last
// time this function was called and now, a bit in Port_B_Delta will be
// set to one, signaling that that interrupt service routine needs to be
// called
Port_B_Delta = Port_B ^ Old_Port_B;
// Now that we know which inputs have changed, save a copy of the
// current state so we'll know which one(s) changed next time.
Old_Port_B = Port_B;
// This checks to see if the bit associated with interrupt 3 has changed
// and if it has, call the interrupt service routine
if(Port_B_Delta & 0x10)
{
// Call the interrupt 3 handler and include the current state of the
// interrupt pin. The wacky bit of code "Port_B & 0x10 ? 1 : 0" is the
// same thing as:
//
// if(Port_B & 0x10)
// {
// return(1)
// }
// else
// {
// return(0)
// }
// This is done to ensure the value sent into the interrupt
// handler is either 0 or 1.
Int_3_Handler(Port_B & 0x10 ? 1 : 0);
}
// Each one must be checked individually because more than one may
// have changed
if(Port_B_Delta & 0x20)
{
Int_4_Handler(Port_B & 0x20 ? 1 : 0);
}
if(Port_B_Delta & 0x40)
{
Int_5_Handler(Port_B & 0x40 ? 1 : 0);
}
if(Port_B_Delta & 0x80)
{
Int_6_Handler(Port_B & 0x80 ? 1 : 0);
}
}