Simple Pin Change Interrupt on all pins
It is possible to use pin change interrupts on "all" pins of the arduino using Pin Change Interrupt Requests. The example below uses some macros from the pins_arduino.h library.
The interrupt can be enabled for each pin individually (analog and digital!), but there are only 3 interrupt vectors, so 6-8 pins share one service routine:
- ISR (PCINT0_vect) pin change interrupt for D8 to D13
- ISR (PCINT1_vect) pin change interrupt for A0 to A5
- ISR (PCINT2_vect) pin change interrupt for D0 to D7
The interrupt fires on a change of the pin state (rising and falling). For more information please refer to the excellent tutorials of Nick Gammon: http://gammon.com.au/interrupts.
Interrupt Pins should be set as INPUT, pullup resistors can be enabled to be able to detect simple switches
pinMode(i,INPUT); // set Pin as Input (default)
digitalWrite(i,HIGH); // enable pullup resistor
It´s true, you can only install one routine for each group of pins, but there are a lot of cases where this is sufficient:
- if only one interrupt pin (per group) is needed
- if two or more pins share the same routine anyway (e.g. Reading of Rotary encoders).
If it is necessary to have a separate routine for each pin, it may be more efficient to use one of the existing PCI-libraries.
Example sketch
This sketch demonstrates the pin change interrupt on pin 7,8,9 and A0, Pin 13 (LED) is used for indication.
// Install Pin change interrupt for a pin, can be called multiple times
void pciSetup(byte pin)
{
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
// Use one Routine to handle each group
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
{
digitalWrite(13,digitalRead(8) and digitalRead(9));
}
ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here
{
digitalWrite(13,digitalRead(A0));
}
ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here
{
digitalWrite(13,digitalRead(7));
}
void setup() {
int i;
// set pullups, if necessary
for (i=0; i<=12; i++)
digitalWrite(i,HIGH); // pinMode( ,INPUT) is default
for (i=A0; i<=A5; i++)
digitalWrite(i,HIGH);
pinMode(13,OUTPUT); // LED
// enable interrupt for pin...
pciSetup(7);
pciSetup(8);
pciSetup(9);
pciSetup(A0);
}
void loop() {
// Nothing needed
}