MCP23017 - 16-Bit I/O Expander

The MCP23017 is a 16-bit I/O expander with I²C interface, enabling the expansion of input/output pins on microcontrollers. It provides 16 GPIO pins, which can be configured as inputs or outputs, and supports multiple devices on the same I²C bus via unique addresses. The chip offers features like internal pull-ups, interrupt generation, and programmable polarity inversion, making it ideal for applications requiring additional I/O in space-constrained designs.

MCP23017 16-Bit I/O Expander in PDIP-28 package
Fig.: MCP23017 16-Bit I/O Expander in PDIP-28 package

Applications

Features/Specifications

Operating Voltage 1.8V to 5.5V
Maximum Clock Speed 1.7 MHz
Max. Current of the IC 150mA
Max. Current per Pin 25mA
I²C Addresses 0x20 to 0x27
Operating Temperature -40°C to +125°C

📄 MCP23017 datasheet (865 kB)

Connections

Terminal diagram of the MCP23017
Fig.: Terminal diagram of the MCP23017
Pin Name Pin No Pin type Function
GPB0 1 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB1 2 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB2 3 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB3 4 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB4 5 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB5 6 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB6 7 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
GPB7 8 I/O Bidirectional I/O pin. Can be enabled for interrupt-on-change and/or internal weak pull-up resistor.
VDD 9 P Power
VSS 10 P Ground
NC/CS 11 I NC (MCP23017), Chip Select (MCP23S17)
SCL/SCK 12 I Serial clock input
SDA/SI 13 I/O Serial data I/O (MCP23017), Serial data input (MCP23S17)
NC/SO 14 O NC (MCP23017), Serial data out (MCP23S17)
A0 15 I Hardware address pin. Must be externally biased.
A1 16 I Hardware address pin. Must be externally biased.
A2 17 I Hardware address pin. Must be externally biased.
RESET 18 I Hardware reset. Must be externally biased
INTB 19 O Interrupt output for PORTB. Can be configured as active-high, active-low or open-drain.
INTA 20 O Interrupt output for PORTA. Can be configured as active-high, active-low or open-drain.
GPA0 21 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA1 22 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA2 23 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA3 24 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA4 25 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA5 26 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA6 27 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.
GPA7 28 I/O Bidirectional I/O pin. Can be enabledfor interrupt-on-change and/or internal weak pull-up resistor.

I²C-Addresses

The I²C address of the MCP23017 can be varied using the A0, A1, and A2 pins:

A0 A1 A2 Address
0 0 0 0x20
1 0 0 0x21
0 1 0 0x22
1 1 0 0x23
0 0 1 0x24
1 0 1 0x25
0 1 1 0x26
1 1 1 0x27

Pull-up Resistors for SDA/SCL

The I²C interface requires two lines through which data and the clock signal are transmitted. Data is sent over SDA from the master to the slave and vice versa. For this reason, the pins on this data line must be open-drain outputs.

To ensure that the lines still have a defined voltage level, pull-up resistors (here: 4.7 kΩ) are required. If these pull-up resistors are not used, only the internal pull-ups of the microcontroller (e.g. Arduino) are active. As a result, the signal may no longer be transmitted correctly.

Used Components

Basic Circuit

The following schematic shows the basic circuit between the Arduino UNO and the MCP23017. The I/O pins are not used at this point.

Circuit diagram for connecting the MCP23017 with a Arduino UNO
Fig.: Circuit diagram for connecting the MCP23017 with a Arduino UNO

Direct Control via Registers

Output

GPA0 to GPA7 (=A register) and GPB0 to GPB7 (=B register) each form a register that can be accessed using the Wire.h library. To set all pins of the A and B registers to OUTPUT, you can use the following code (typically in setup()):

Wire.beginTransmission(0x20);
Wire.write(0x00); // IODIRA register
Wire.write(0x00); // set all of port A to outputs
Wire.endTransmission();
Wire.beginTransmission(0x20);
Wire.write(0x01); // IODIRB register
Wire.write(0x00); // set all of port B to outputs
Wire.endTransmission();

If you now want to control some of the output pins in loop(), use the following code:

Wire.beginTransmission(0x20);
Wire.write(0x12); // address port A
Wire.write(??);  // value to send
Wire.endTransmission();
Wire.beginTransmission(0x20);
Wire.write(0x13); // address port B
Wire.write(??);  // value to send
Wire.endTransmission();

Replace the ?? with the desired binary, hexadecimal, or decimal values. You can think of each pin as a bit that can be set to 0 (LOW) or 1 (HIGH). All pins combined as one number are then sent to the MCP23017. For example, if you want to set pin 7 and pin 1 to HIGH, the value must be 10000010, which is 0x82 in hexadecimal and 130 in decimal.

Input

The MCP23017 is set to input mode by default, so no additional configuration is needed.
In the following example, we use the basic circuit described above and extend it with 4 push-buttons connected to pins GPB0, GPB1, GPB2, and GPB3.

#include "Wire.h"
byte inputs=0;

void setup() {
    Serial.begin(9600);
    Wire.begin(); // wake up I²C bus
}

void loop() {
    Wire.beginTransmission(0x20);
    Wire.write(0x13); // set MCP23017 memory pointer to GPIOB address
    Wire.endTransmission();
    Wire.requestFrom(0x20, 1); // request one byte of data from MCP23017
    inputs = Wire.read(); // store the incoming byte into "inputs"
    if (inputs > 0) {
        // if a button was pressed
        Serial.println(inputs, BIN); // display the contents of the GPIOB register in binary
        delay(200); // for debounce
    }
}

Since all pins are read at once, pressing multiple buttons at the same time can also be detected.

Circuit with Adafruit-MCP23017 Library

Ex. 1

The following sketch uses the Adafruit_MCP23017 library and makes all 16 pins blink alternately:

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;

void setup() {
    mcp.begin(0); // Init MCP23017 at address 0x20
    for (byte i=0; i<16; i++) {
        mcp.pinMode(i, OUTPUT);
    }
}

void loop() {
    for (byte i=0; i<16; i++) {
        mcp.digitalWrite(i, HIGH);
    }
    delay(500);

    for (byte i=0; i<16; i++) {
        mcp.digitalWrite(i, LOW);
    }
    delay(500);
}

Ex. 2

It is possible to control multiple MCP23017 ICs per Arduino using different addresses. The following schematic and sketch demonstrate this. Again, all output pins will blink — this time from two MCP chips:

Circuit diagram for operating two MCP23017 chips with the Arduino Uno
Fig.: Circuit diagram for operating two MCP23017 chips with the Arduino Uno
#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;

void setup() {
    mcp1.begin(0); // Init MCP23017 at address 0x20
    mcp2.begin(1); // Init MCP23017 at address 0x21

    for (byte i=0; i<16; i++) {
        mcp1.pinMode(i, OUTPUT);
        mcp2.pinMode(i, OUTPUT);
    }
}

void loop() {
    for (byte i=0; i<16; i++) {
        mcp1.digitalWrite(i, HIGH);
        mcp2.digitalWrite(i, HIGH);
    }
    delay(500);

    for (byte i=0; i<16; i++) {
        mcp1.digitalWrite(i, LOW);
        mcp2.digitalWrite(i, LOW);
    }
    delay(500);
}
Last edited by Christian Grieger on 2025-05-12
X
  1. [top]
  2. Applications
  3. Features/Specifications
  4. Connections
  5. I²C-Addresses
  6. Pull-up Resistors for SDA/SCL
  7. Used Components
  8. Basic Circuit
  9. Direct Control via Registers
  10. Circuit with Adafruit-MCP23017 Library