Events management (Part 3)
Now that we managed to handle external interrupts on PIND2 and PIND3 some may want to get even more! Why not 😉
And yes, it is possible thanks to the “Pin Change Interrupt”! In this way each of the port lines can be used for triggering an external interrupt! Look at the pinout below, you will find the correspondance between PORTD:B and the PCINT2:0:
Even better than triggering an external interrupt using one input line, you can use multiple lines. The example below illustrates the use of PIND6 and PIND7 from PORTD for triggering one event in ISR(PCINT2_vect). If one or the other, or both pins change in state, the Interrupt Service Request reads their status and records it in a global variable.
#include #define PIN_INPUT1 PIND6 // PCINT22 #define PIN_INPUT2 PIND7 // PCINT23 #define LED_PIN PINB5 byte pushButtonState = 0x00; // Ground true long interval = 100; long lastTime = 0; void setup(void) { // Setup input pins DDRD &= ~((1 << PIN_INPUT1) | (1 << PIN_INPUT2)); // Bias input pins PORTD |= ((1 << PIN_INPUT1) | (1 << PIN_INPUT2)); // Set led pin as output DDRB |= (1 << LED_PIN); // Attach interrupt to PIND6 and PIND7 PCMSK2 = ((1 << PCINT22) | (1 << PCINT23)); // Pin Change Mask Register 2 PCICR = (1 << PCIE2); // Pin Change Interrupt Enable 2 // Set global variable lastTime = millis(); // Functions blinkLed(5, 200); } void loop(void) { writeState(); // write inputs state on led output // Do something else here delay(10); } ISR(PCINT2_vect) { // Read inputs state (Ground true) pushButtonState = ((~PIND >> PIN_INPUT1) & 0x01) | ((~PIND >> PIN_INPUT2) & 0x01); } void writeState() { // Write inputs state on led output if (pushButtonState) PORTB |= (1 << LED_PIN); // Turn led on else PORTB &= ~(1 << LED_PIN); // Turn led off } void blinkLed(int nbrBlinks, int intervals){ // Blink status led for (int i = 0; i < (nbrBlinks * 2); i++) { PORTB ^= (1 << LED_PIN); // toggle status led delay (intervals); } }
Isn’t it great?