MCP23S17 addressable 16-Bit I/O Expander with SPI

I'm working on an mbed library for the MicroChip MCP23S17. The library is currently at version 0.4; expect the API to change incompatibly until  v 1.0. (See below).

Verison 0.4 adds a method to configure input pull-ups.

The chip has several advantages over my usual port expander, the PCF8574. It's 16 bits wide, and you can drive it at 10Mz. the PCF8574 is a first-generation I2C device so it is limited to a 100Kz clock rate. This means that the MCP23S17's clock rate is 100 times faster!

Best of all, although it uses SPI, the MCP23S17 is addressable just like an I2C slave. (Indeed there is  a sister product MCP23017 with the same functionality but driven by I2C). You can have up to 8 individually addressable devices driven by the 3 SPI signals and a single chip select.

Most methods can access Port A or B depending on the port parameter value.

I've also changed the names of the _input _and _output _methods to _read _and _write_, so they will be more consistent with other libraries.

The latest library version supports 8-bit input and output, and also handles interrupt generation. You can

  • configure interrupts on both ports
  • turn interrupt mirroring on and off
  • set interrupt polarity
  • interrupt on change or difference from a specified value, and
  • configure pull-ups to be on or off for each input pin.

The API is nearly complete, but there are no doxygen comments yet. I will add them when the API has stabilised.

This test breadboard layout, courtesy of Fritzing, is slightly out of date; see comments in the test for the full list of connections

I'll update the diagram when the API is complete.

20 Aug 2010

Wonderful timing! I just designed that part into a new project. I've received the pcb's but it will still be a few weeks before I'll have time to start working on that project. Good luck and keep us updated!



20 Aug 2010

A potential library user - fantastic news!

This gives me a chance to ask for some feedback before I commit to a design.

The MCP23S17 has a surprisingly complex API for a port extender. I was particularly charmed by the ability to change the addresses of internal registers by setting a control bit :)

I'm proposing to keep things simple, and hide as much as possible. I'm thinking of a library API which lets you set the port direction, read inputs and write ouptuts, with 2 versions of each method; one set will use 16-bit values and affect both 8-bit ports; the other two will affect a single port. I'll also add methods to configure the interrupts.

I'll hide direct register access using protected methods. That way someone who really needs the low-level stuff can subclass the library.

How does that sound?

21 Aug 2010

That sounds great. I just figured out today I have to rev the pcb for my current project this weekend, which originally did not include the MCP23S17. Now it will, I needed to free up some mBed pins so I'm moving some simple output control lines over to the MCP23S17.

For this project Port A will be all outputs and Port B will be inputs. I'll tie the Interrupt line to the mBed, just in case, probably just the Int B line. Any thoughts on that? Should I tie both the interrupt lines together?

I should be working with the new boards in a couple of weeks, which is good since this project needs to go live in three weeks. It's a production test system for piston pumps. It just runs the pumps through a test to determine and record the pump displacement, and verifies that either an optical or hall sensor is functional and sends the results back to a PC. For some pumps with a reed switch, it also measure the reed switch contact resistance.

So I'm looking forward to testing.

21 Aug 2010 . Edited: 21 Aug 2010

I've made considerable progress, but manual testing is getting more tedious as I complete more of the API. Right now there's enough of the API to set up your inputs and outputs. No interrupt configuration yet, but that's next. I will add a method to tie the interrupt outputs together, although I don't think you will need this.

This weekend I'm going to move the code into a library and set up some automated tests, using the mbed both as an SPI master and a port driver/monitor. I'll publish the library and test code and the wiring as soon as I have working tests for the current API. From then on I will do test-driven development, i.e. I will only add code to the API where I have an automated test in place.

24 Aug 2010

Hi Romilly -

Does the API allow enabling the pull up resistors when the ports are set for input? I was just moving some inputs from the mBed over to the MCP23S17 and noticed they relied on the mBeds internal pull up resistors and will also need to have the pull ups enabled on the MCP23S17 or have external pull ups added.




24 Aug 2010

Hi Mike,

v 0.3 doesn't, but I'll put pull-up enabling in for v 0.4.

What do you think is the best way for me to to test that? Put a high-value (100k?) pull-down resistor between an input and ground, and make sure that the chip sees a high input only when the pull-ups are enabled?

Regards,  Romilly

24 Aug 2010

Hi Romilly -

Yes, that sounds like a good way to test. The internal pull ups are 100K, so when they are enabled the port should see about 2.5 volts, and a valid high input is > 0.8V. And when the pull ups are disabled the external 100K resistor will pull the input to ground.



28 Aug 2010

I've added the test; pull-up configuration now works.

05 Sep 2010

Hi Romilly -


Thanks for the update. My schedules slipped and I probably won't be able to give it a try for a few weeks now. You have to love shifting priorities!

None the less, thank you for this work. I'm sure it will end up saving me and others a great amount of work.



18 Dec 2010

Hi All,

I have just added a lib for the MCP23017. That device is very simular to the MCP23S17, but it uses I2C rather than SPI. The code is based on Romilly's lib and can be found here:



28 Jan 2011 . Edited: 28 Jan 2011

I used the library for a student lab here and posted a basic IO getting started demo program at

A couple of notes:

The chip has an internal power on reset and you can just tie the reset pin high (don't just leave it floating)  - per data sheet at it must be "externally biased". My chip would work a few minutes and die with a floating reset and it never failed once I pulled it high.

Make sure that you order the chip in a skinny DIP package it you want to plug it directly in the breadboard. It also comes in surface mount.

DigiKey stocks and sells both SPI and I2C versions in a DIP for around $1.50.

MCP2S317 - SPI 16 bit I/O port expander


MCP23017 - I2C 16 bit I/O port expander

1 comment on MCP23S17 addressable 16-Bit I/O Expander with SPI:

15 Jan 2017


So if I want to instantiate a pullup resistor on PORT_A for my chip, would this syntax work if placed inside main:

chip.configurePullUps(PORT_A, On);

Please log in to post comments.