Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

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.

  1. // Install Pin change interrupt for a pin, can be called multiple times
  2.  
  3. void pciSetup(byte pin)
  4. {
  5.     *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  6.     PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  7.     PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
  8. }
  9.  
  10. // Use one Routine to handle each group
  11.  
  12. ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
  13.  {    
  14.      digitalWrite(13,digitalRead(8) and digitalRead(9));
  15.  }
  16.  
  17. ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here
  18.  {
  19.      digitalWrite(13,digitalRead(A0));
  20.  }  
  21.  
  22. ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here
  23.  {
  24.      digitalWrite(13,digitalRead(7));
  25.  }  
  26.  
  27. void setup() {  
  28. int i;
  29.  
  30. // set pullups, if necessary
  31.   for (i=0; i<=12; i++)
  32.       digitalWrite(i,HIGH);  // pinMode( ,INPUT) is default
  33.  
  34.   for (i=A0; i<=A5; i++)
  35.       digitalWrite(i,HIGH);
  36.  
  37.   pinMode(13,OUTPUT);  // LED
  38.  
  39. // enable interrupt for pin...
  40.   pciSetup(7);
  41.   pciSetup(8);
  42.   pciSetup(9);
  43.   pciSetup(A0);
  44. }
  45.  
  46.  
  47. void loop() {
  48.   // Nothing needed
  49. }