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

A class for PCF8574.

Last Modified: November 05, 2017, at 03:58 AM
By: pert

Intro

The I2C bus can be used to extend the number of IO lines. A frequently used chip for this is the PCF8574 which offers 8 IO lines. The PCF8474 has multiple address lines so the I2C address can be changed.

PCF8574 library

The library supports

  • read and write (1 pin),
  • read8 and write8 (all pins),
  • toggle(pin),
  • leftShift(n) and rightShift(n),
  • value() returns the last value read.
  • lastError() returns the last I2C error code. (0 ==> OK)

The PCF8574 library on GitHub: https://github.com/RobTillaart/Arduino/tree/master/libraries/PCF8574

Installation notes

To use the library, make a folder in your SKETCHBOOKPATH\libraries with the name PCF8574 and put the .h and .cpp there.

Usage

A sketch shows how the library can be used ---

//
//    FILE: pcf8574_test.ino
//  AUTHOR: Rob Tillaart
//    DATE: 27-08-2013
//
// PURPOSE: demo 
//

#include "PCF8574.h"
#include <Wire.h>

// adjust addresses if needed
PCF8574 PCF_38(0x38);  // add switches to lines  (used as input)
PCF8574 PCF_39(0x39);  // add LEDs to lines      (used as output)

void setup()
{
  Serial.begin(115200);
  Serial.println("\nTEST PCF8574\n");

  uint8_t value = PCF_38.read8();
  Serial.print("#38:\t");
  Serial.println(value);

  for (int i=0; i<255; i++)
  {
    PCF_39.write8(i);
    delay(100);
  }

  PCF_39.write(0, 1);
  for (int i=0; i<7; i++)
  {
    PCF_39.shiftLeft();
    delay(100);
  }

  for (int i=0; i<7; i++)
  {
    PCF_39.shiftRight();
    delay(100);
  }

  for (int i=0; i<8; i++)
  {
    PCF_39.write(i, 1);
    delay(100);
    PCF_39.write(i, 0);
    delay(100);
  }

  for (int i=0; i<8; i++)
  {
    PCF_39.toggle(i);
    delay(100);
    PCF_39.toggle(i);
    delay(100);
  }
}

void loop()
{
  // echos the lines
  uint8_t value = PCF_38.read8();
  PCF_39.write8(value);
  delay(100);
}
//
// END OF FILE
//

Another example using the IRQ pin of the chip (not tested yet) - http://forum.arduino.cc/index.php?topic=204596.msg1506639#msg1506639 -

Todo

  • test test test test and ...
  • add pin change mask to see what has changed since last read.

Enjoy tinkering,

rob.tillaart@removethisgmail.com

pcf8574.h

//
//    FILE: PCF8574.H
//  AUTHOR: Rob Tillaart
//    DATE: 02-febr-2013
// VERSION: 0.1.02
// PURPOSE: I2C PCF8574 library for Arduino
//     URL: 
//
// HISTORY:
// see PCF8574.cpp file
// 

#ifndef _PCF8574_H
#define _PCF8574_H

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#define PCF8574_LIB_VERSION "0.1.02"

class PCF8574
{
  public:
  PCF8574(int address); 

  uint8_t read8(); 
  uint8_t read(uint8_t pin); 
  uint8_t value();  

  void write8(uint8_t value); 
  void write(uint8_t pin, uint8_t value); 

  void toggle(uint8_t pin);
  void shiftRight(uint8_t n=1);
  void shiftLeft(uint8_t n=1);

  int lastError();

  private:
  int _address;
  uint8_t _data;
  int _error;
};

#endif
//
// END OF FILE
//

pcf8574.cpp

//
//    FILE: PCF8574.cpp
//  AUTHOR: Rob Tillaart
//    DATE: 02-febr-2013
// VERSION: 0.1.02
// PURPOSE: I2C PCF8574 library for Arduino
//     URL: 
//
// HISTORY:
// 0.1.02 replaced ints with uint8_t to reduce footprint;
//        added default value for shiftLeft() and shiftRight()
//        renamed status() to lastError();
// 0.1.01 added value(); returns last read 8 bit value (cached); 
//        value() does not always reflect the latest state of the pins!
// 0.1.00 initial version
// 

#include "PCF8574.h"

#include <Wire.h>

PCF8574::PCF8574(int address) 
{
  _address = address;
  Wire.begin();
}

uint8_t PCF8574::read8()
{
  Wire.beginTransmission(_address);
  Wire.requestFrom(_address, 1);
#if (ARDUINO <  100)
   _data = Wire.receive();
#else
   _data = Wire.read();
#endif
  _error = Wire.endTransmission();
  return _data;
}

uint8_t PCF8574::value()
{
  return _data;
}

void PCF8574::write8(uint8_t value)
{
  Wire.beginTransmission(_address);
  _data = value;
  Wire.write(_data);
  _error = Wire.endTransmission();
}

uint8_t PCF8574::read(uint8_t pin)
{
  PCF8574::read8();
  return (_data & (1<<pin)) > 0;
}

void PCF8574::write(uint8_t pin, uint8_t value)
{
  PCF8574::read8();
  if (value == LOW) 
  {
    _data &= ~(1<<pin);
  }
  else 
  {
    _data |= (1<<pin);
  }
  PCF8574::write8(_data); 
}

void PCF8574::toggle(uint8_t pin)
{
  PCF8574::read8();
  _data ^=  (1 << pin);
  PCF8574::write8(_data); 
}

void PCF8574::shiftRight(uint8_t n)
{
  if (n == 0 || n > 7 ) return;
  PCF8574::read8();
  _data >>= n;
  PCF8574::write8(_data); 
}

void PCF8574::shiftLeft(uint8_t n)
{
  if (n == 0 || n > 7) return;
  PCF8574::read8();
  _data <<= n;
  PCF8574::write8(_data); 
}

int PCF8574::lastError()
{
  int e = _error;
  _error = 0;
  return e;
}
//
// END OF FILE
//