PCA9555 GPIO Expander with Arduino Using Interrupts

by Lewis Loflin

In this series I'll be connecting the PCA9555D 32-bit GPIO expander board to an Arduino micro-controller. First we started out simple with counting from 0 to 255 in binary on eight LEDs. See Part 1 for technical information and getting started.

Here in part three we will learn to use the interrupt pin to jump to the key scan routine only when a key is pressed. A BCD value is output on the eight LEDs.

In part two we learned to connect a 4X4 keypad to an 8-bit port. Using "polling" the routine getKey() we will check for a key press and return a BCD value from 0 to 16 displayed on the eight LEDs. See Part 2



In part four we will connect a type a Hd44780 type LCD display and learn how to enter data and manipulate character date and strings. In addition to the LCD display we will scan a keypad, use hardware interrupts, all connected through a single PCA9555 module. In addition I'll reveal some code little discussed with Arduino and we will convert/manipulate code for output to the LCD display. See Part 4

This differs from two only in the addition of interrupt use instead of polling.

4X4 keypad
4X4 keypad used in this demo.



#include <Wire.h> // specify use of Wire.h library.

int i, j;
byte temp1;

volatile byte flag_bit = LOW;

void setup()

{
  pinMode(2, INPUT);
  Wire.begin();
  Wire.beginTransmission(0x20);  // setup out direction registers
  Wire.write(0x06);  // pointer
  Wire.write(0x0F);  // DDR Port0 bits 0-3 input 4-7 output 
  Wire.write(0x00);  // DDR Port1 all output
  Wire.endTransmission(); 

  Wire.beginTransmission(0x20);  // 
  Wire.write(0x02);  // pointer
  Wire.write(0x00);  // clear bits 4-7 PORT0
  Wire.endTransmission(); 

  Wire.beginTransmission(0x20);  // invert bit
  Wire.write(0x04);  // pointer
  Wire.write(0xFF);  // invert bits PORT0 on read
  Wire.endTransmission(); 
  
    // clear LEDs PORT1
  Wire.beginTransmission(0x20);  
  Wire.write(0x03); // begin here
  Wire.write(temp1); 
  Wire.endTransmission();
  
  
  attachInterrupt(0, flag1, FALLING); 
}  // end setup

void loop() {

  if (flag_bit = HIGH)  {
    detachInterrupt(0); 
    temp1 = getKey(); // scan keypad for BCD code. 
    if (temp1 != 0x00)   {
      Wire.beginTransmission(0x20);  
      Wire.write(0x03); // begin here
      Wire.write(temp1); 
      Wire.endTransmission();
    }

    flag_bit = 0x00;
    attachInterrupt(0, flag1, FALLING); 

  }





} // end loop


void flag1() // set bit
{
  flag_bit = HIGH; 
} 




byte getKey()  {



  Wire.beginTransmission(0x20);  
  Wire.write(0);  // set data pointer
  Wire.endTransmission();
  Wire.requestFrom(0x20, 1);
  byte c = Wire.read();
  if ((c & 0x0F) == 0) return 0x00;  // no key pressed


  Wire.beginTransmission(0x20);
  Wire.write(0x02);
  Wire.write(B11100000); // check row L1
  Wire.endTransmission();

  Wire.beginTransmission(0x20);  
  Wire.write(0);  // set data pointer
  Wire.endTransmission();
  Wire.requestFrom(0x20, 1);
  c = Wire.read();
  if ((c & 0x1F) > 0x10) {
    if (c==B00010001) c = 0x01; 
    if (c==B00010010) c = 0x02; 
    if (c==B00010100) c = 0x03; 
    if (c==B00011000) c = 0x04;
    delay(100);
    resetPort0();
    return c;
  }

  Wire.beginTransmission(0x20);
  Wire.write(0x02);
  Wire.write(B11010000); // check row L2
  Wire.endTransmission(); 

  Wire.beginTransmission(0x20);  
  Wire.write(0);  // set data pointer
  Wire.endTransmission();
  Wire.requestFrom(0x20, 1);
  c = Wire.read();
  if ((c & 0x2F) > 0x20) {
    if (c==B00100001) c = 0x05; 
    if (c==B00100010) c = 0x06; 
    if (c==B00100100) c = 0x07; 
    if (c==B00101000) c = 0x08;
    delay(100);
    resetPort0();
    return c;
  }


  Wire.beginTransmission(0x20);
  Wire.write(0x02);
  Wire.write(B10110000); // check row L3
  Wire.endTransmission(); 

  Wire.beginTransmission(0x20);  
  Wire.write(0);  // set data pointer
  Wire.endTransmission();
  Wire.requestFrom(0x20, 1);
  c = Wire.read();
  if ((c & 0x4F) > 0x40) {
    if (c==B01000001) c = 0x09; 
    if (c==B01000010) c = 0x10; 
    if (c==B01000100) c = 0x11; 
    if (c==B01001000) c = 0x12;
    delay(100);
    resetPort0();
    return c;
  }


  Wire.beginTransmission(0x20);
  Wire.write(0x02);
  Wire.write(B01110000); // check row L4
  Wire.endTransmission(); 

  Wire.beginTransmission(0x20);  
  Wire.write(0);  // set data pointer
  Wire.endTransmission();
  Wire.requestFrom(0x20, 1);
  c = Wire.read();
  if ((c & 0x8F) > 0x80) {
    if (c==B10000001) c = 0x13; 
    if (c==B10000010) c = 0x14; 
    if (c==B10000100) c = 0x15; 
    if (c==B10001000) c = 0x16;
    delay(100);
    resetPort0();
    return c;
  }



}


void  resetPort0()   {

  Wire.beginTransmission(0x20);  // 
  Wire.write(0x02);  // pointer
  Wire.write(0x00);  // clear bits 4-7 PORT0
  Wire.endTransmission(); 

}

Added June 7, 2013:

You Tube Arduino Microcontroller Video Series March 2012: