PCF8574 & I/O Quick Start

A while ago I received a couple of I/O port expander modules that use the I2C protocol. Using that Chinese module, you can use only the SDA and SCL pins of your Arduino, or any microcontroller capable of I2C communication, to handle up to 8 digital I/O ports!

PCF8574 Module

When playing with microcontrollers, sometimes a need arises to add more digital I/Os than the chip supports natively. The PCF8574 (PCF8574T) module is one of the more popular ways of expanding I/Os as it uses the I2C bus that requires only 2 pins on the microcontroller. It provides 8 additional digital I/Os which are easily daisy-chainable up to 64. Note that the module has an easy to use I2C interface that can be configured through movable jumpers to use any one out of the eight I2C addresses.

Take note that this module is designed around the PCF8574 (https://www.ti.com/lit/ds/symlink/pcf8574.pdf) – not PCF8574A. Actually, PCF8574 and PCF8574A are identical, except for the different fixed portion of the slave address. The three hardware address pins allow eight of each device to be on the same I2C-bus, so there can be up to 16 of these I/O expanders PCF8574/74A together on the same I2C-bus, supporting up to 128 I/Os.

When focusing on the chip, we can see that the PCF8574 provides general-purpose remote I/O expansion via the two-wire bidirectional I2C bus. It consists of 8 quasi-bidirectional ports, 100 kHz I2C-bus interface, 3 hardware address inputs and interrupt output operating between 2.5V and 6V. The quasi-bidirectional port can be independently assigned as an input to monitor interrupt status or keypads, or as an output to activate indicator devices such as LEDs. System master can read from the input port or write to the output port through a single register.

Let’s take a closer look at the PCF8574 I2CI/O Expansion module.

These are the key features of the module demoed here:

  • 8 bi-directional data lines
  • Loop-thru feature allows expansion of up to 8 modules / 64 data lines
  • I2C interface with jumper adjustable addresses
  • Interrupt output capability
  • 3.3V and 5V compatible.

There are three address selection jumps (A0-A2) that determine which I2C address to use. As shipped, these jumpers are all set to the LOW side (GND) as shown in the above picture. This puts the module at the default/base slave address of 0x20 (7-bit hexadecimal). The jumpers can be moved in a binary fashion to change the I2C address (0x20 to 0x27) as shown in the slave address map below.

The I/O expander PCF8574 can be configured to have a unique 7-bit address. The first

four bits of the 7-bit address are 0100, and the lower three bits are the settings on the device pins A2, A1, and A0. This ability to set unique addresses for the expander

makes it possible to have up to eight PCF8574 devices on the same I2C bus.

Arduino & PCF8574

Some Arduino projects may require more I/Os than the Arduino has. In such cases, you can use up to 8 x PCF8574 devices at ease using only the two-wire I²C bus. A simplified device description for your reference is shown below.

However, there’re a few things to note about before you get into the real-world applications.

First to note there’s a substantial difference between the PCF8574 and the PCF8574A ICs.

Likewise, the 8-bit I2C address of the PCF8574 is 0x40 in “write” mode when all pins (A2-A1-A0) are set to LOW. However, when you want to read the values, you need to set Bit 0 to 1, so the initial “read” address is 0x41.

Now to the tricky part…

The Arduino “Wire” library (https://www.arduino.cc/en/reference/wire) handles the I2C addresses a little differently. You only need to provide the 7 highest Bits of the I2C address, or it won’t respond to your calls.

I hope it’s clear, you need to shift the bits of your address one to the right in order to make it work with the Arduino library (you can do this within the code or you can define the shifted address before preparing your code).

Alright, Let’s go!

Below is a quick test code (taken from the web) for the simple Arduino setup shown next. The code makes the setup as a 2-channel 8-LED flasher (P0-P2-P4-P6 || P1-P3-P5-P7).

[code]

#include // I2C Arduino Library

#define PCF8574_ADDR (0x20) // I2C Slave Address

void setup()

{

wire.begin();

}

void loop()

{


Wire.beginTransmission(PCF8574_ADDR);

Wire.write(0xAA); // see
note

Wire.endTransmission();

delay(1000);


Wire.beginTransmission(PCF8574_ADDR);

Wire.write(0x55); // see
note

Wire.endTransmission();

delay(1000);

}

[/code]

My speedy, experimental setup has no series resistors for the LEDs but it’s great to employ them in your build (270Ω x8). Also note that the output of PCF8574 offers a minimum guaranteed sinking current of 10mA per I/O at 5V. Therefore, in applications demanding additional drive, two port pins may be connected together to sink up to 20mA current.

The good news is that there’re several PCF8574 libraries for Arduino (see below) to expand your project ideas, you can of course use your PCF8574 module with any other microcontroller features I2C communication, though.

Further, it’s easy to daisy-chain multiple PCF8574 modules (see below) as we previously noted (just something that you’ll want to keep in mind for future consideration).

While on the subject, what are 0xAA and Ox55 in the above test code doing?

Let me put it in layman’s terms! When converting to binary, 0xAA is equivalent to 1010 1010 and 0x55 is equivalent to 01010101. These numbers have 0s and 1s set in alternating locations.

Endnote

These PCF8574 modules are ridiculously cheap and can be bought easily from most online stores. Like in many other cases, the PCF8574 hardware is extremely simple to implement, as you just need to hook them up to the I2C bus and you are all ready to go. The only thing that requires some care is setting the correct jumper position for the desired I2C address. Moreover, many Arduino PCF8574 libraries comes with great examples which will help you in getting your hands on the I2CI/O Expander. That’s all for now!

Leave a Comment