Source: https://mokxi.com/learn/arduino-pcf8574-mcp23017
Updated: 2026-10-25

Learn

# More pins for an Arduino: the PCF8574 and the MCP23017

Intermediate

Written by the Mokxi team, updated October 25, 2026

Start building free Open the editor

Or see every lesson.

- 455 parts on the bench
- 43 boards running now
- 1.00x real time, on every board

Two I/O expanders on one I2C bus, on a simulated ATmega328P. The button is on the MCP23017’s GPB0.

An Uno runs out of pins fast. An I/O expander adds more over the two I2C wires you may already be using: eight with a PCF8574, sixteen with an MCP23017, and up to eight of either chip on one bus. They do the same job in two very different ways, and this page puts them side by side.

The circuit above is an Uno with both chips on one I2C bus. The PCF8574 walks a single low bit along its first four pins, and the MCP23017 reads a button on one pin and drives another to match. It runs in your browser on the sketch below, so you can see each chip’s pins change on the canvas and break the wiring on purpose.

## What you need

- An Arduino Uno
- A PCF8574 module (the blue board with three address jumpers)
- An MCP23017 chip (28-pin DIP)
- A pushbutton
- A half-size breadboard and jumper wires

## Wiring

Part and pin | Goes to | Note

Both chips SDA | A4 | The PCF8574 board carries pull-ups for the bus

Both chips SCL | A5 |

PCF8574 VCC and GND | 5 V and GND | Address 0x20 on its jumpers

MCP23017 VDD and VSS | 5 V and GND |

MCP23017 A0, A1, A2 | 5 V | All high: address 0x27

MCP23017 RESET | 5 V | It has no pull-up of its own

Button | MCP23017 GPB0 and GND | GPB0 uses the chip’s pull-up

## The PCF8574: a byte is the pins

The PCF8574 has no settings at all. Every byte you write lands on its eight pins, P0 in bit 0, and every byte you read is their levels. The Wire library is the whole driver: beginTransmission(0x20), write() a byte, endTransmission().

A 0 pulls a pin hard to ground. A 1 only lets it go, with a weak pull-up of about 100 microamps. That has two results. A pin written 1 is also an input: wire a button from it to ground and read it. And an LED has to go from 5 V through a resistor into the pin, lit when the bit is 0. Wired the Arduino way, from the pin to ground, it barely glows.

The sketch writes ~(1 << step): every bit 1 except one. The chip’s pins read 11111110, then 11111101, 11111011, 11110111, and around again, four times a second. This is the same chip that sits on the back of an I2C LCD backpack.

## The MCP23017: registers for everything

The MCP23017 is a proper pair of 8-bit ports, A and B, with a register for direction, pull-ups, polarity and interrupts. Its outputs push and pull, so an LED from a pin to ground works as on the Uno. The Adafruit_MCP23X17 library makes it look like the Arduino’s own pins: mcp.pinMode(), mcp.digitalWrite() and mcp.digitalRead(), with pins 0 to 7 for GPA0 to GPA7 and 8 to 15 for GPB0 to GPB7.

Here GPB0 is an input with its pull-up on and a button to ground, and GPA0 is an output that goes high while the button is held. The serial monitor says "button up" four times a second, and "button held" while you press it.

The expanders sketch

## Addresses: eight of each on one bus

Both chips take their address from three pins. On the PCF8574 board they are jumpers, giving 0x20 to 0x27; the PCF8574A version uses 0x38 to 0x3F, so check which one you have. On the MCP23017 they are the chip’s A0, A1 and A2 pins, also 0x20 to 0x27.

The MCP23017 has no pull-ups or pull-downs on A0 to A2 or on RESET, so all four must be tied to 5 V or ground. Leave any of them loose and the chip may not answer at all. Unplug the jumper that ties RESET high in this circuit and press Run: the first lines say "PCF8574 at 0x20" and "no MCP23017 at 0x27".

## Which one to use

Use a PCF8574 for a few buttons or LEDs wired to 5 V, when you want the smallest code and a cheap module. Use an MCP23017 for sixteen pins, real push-pull outputs, or an interrupt pin that tells the Uno which input changed.

In the editor, add four LEDs to the PCF8574 from 5 V through 330 ohm resistors into P0 to P3 and watch one lit LED walk along them. Or set another MCP23017 pin as an output and light an LED from it to ground.

## Common mistakes

LEDs from a PCF8574 pin to ground. The pin’s high is too weak to light one. Wire them from 5 V into the pin.

Writing a 0 to a PCF8574 pin you want to read. A pin written 0 always reads 0. Write it 1 first.

Leaving RESET or an address pin on the MCP23017 floating.

Not checking begin_I2C(). If the chip is missing, its digitalRead() returns LOW, so this sketch prints "button held" over and over with nothing pressed. Check the return value, as the sketch does, before you trust a reading.

Mixing up the PCF8574 and PCF8574A addresses. Run an I2C scanner if nothing answers.

## Questions

What is the difference between the PCF8574 and the MCP23017?

The PCF8574 has eight pins and no registers: a byte written is the pins, and its highs are weak. The MCP23017 has sixteen pins with direction, pull-up and interrupt registers and real push-pull outputs.

How many I/O expanders can I put on one Arduino?

Up to eight chips in the 0x20 to 0x27 range, PCF8574s and MCP23017s together, since both use those addresses, plus eight PCF8574As at 0x38 to 0x3F. No two chips on one bus can share an address.

Do I need a library for the PCF8574?

No. Wire.h alone writes and reads it, as this sketch does. Libraries such as Rob Tillaart’s PCF8574 add pin-by-pin calls, and Mokxi includes them.

Why does my MCP23017 not show up on an I2C scan?

Usually RESET or one of A0 to A2 is not connected. None of them has a pull-up inside the chip. Tie RESET to 5 V and each address pin to 5 V or GND.

Related

## Keep going

I2C Explained: Addresses, Acknowledges and Pull-Ups Arduino LCD I2C 16x2: Wiring, Code, Scrolling Text Pull-Up Resistors and the Floating Input They Fix Arduino CD74HC4067 Multiplexer: 16 Analog Inputs How the PCF8574 is modeled How the MCP23017 is modeled The Arduino Uno simulator The project page, with the full sketch Intermediate

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
