Parts: 8bit IO Expander (PCF8574)


Sometimes a project has more sensors, buttons, or LEDs than your microcontroller has pins. The PCF8574 is an easy way to add 8 low-speed input or output pins to a microcontroller. A configurable address lets multiple PCF8574s exist on the same bus, so two microcontroller pins can control dozens of IO pins. We’ll show you how to use this chip below.


TI PCF8574 I2C 8bit IO expander (Mouser #595-PCF8574N, $1.86)

We found PCB footprints for this chip in i2c.lbr and micro-phillips.lbr on the Cadsoft Eagle library download page. The PCF8574 is controlled with the 2 wire I2C protocol, so we used our Bus Pirate universal serial interface to demonstrate this chip. The same basic operations will apply to any microcontroller.

The schematic shows our simple test circuit for the PCF8574, here’s the datasheet (PDF). We powered the chip with 5volts, and used a 0.1uF decoupling capacitor (C1) between the power and ground pins. R1  and R2 hold the I2C clock and data bus at 5volts. We’ll use an LED to test the chip’s output features; P0 is connected to LED1 through current limiting resistor R3 (330+ ohms). P6 and P7 are tied to known states so we can easily test the chip’s input capabilities.

The PCF8574’s I2C address is 0100xxxy, with three bits (x) determined by the state of the address pins A2-0, and a final bit (y) that sets the read (1) or write (0) mode. Many PFC8574s can share an I2C bus by using different address pin settings. Since we tied the address pins to ground, the write address is 01000000 (0x40).


The LED on P0 is controlled by writing a 1 (on) or 0 (off) to bit 0 of the byte following the write address.

I2C>{0x40 0b00000001} <–command
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0x01 GOT ACK: YES<–output value

{ issues an I2C start condition, followed by the write address, 0x40. The output value, 0b00000001, sets P0 high and the remaining bits low. } sends the I2C bus stop condition, ending the transaction. When the corresponding bit is set high, the LED turns on.

To turn the LED off, repeat the sequence with the corresponding output bit set to 0.

I2C>{0x40 0b00000000}<–command
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0x00 GOT ACK: YES<–output value

With P0 now set to ground, the LED turns off.


Pins set to output high can also be used as inputs (datasheet page 1).  In the example, P6 is held high (+5 volts) and P7 is held low (ground), but these could also be buttons, sensors, or other digital logic. The other pins are left floating and don’t represent valid data.

I2C>{0x40 0b11000000}<–command
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0xC0 GOT ACK: YES<–output value

First, we set the desired input pins to output high by writing 1 to the corresponding bits in the output value. Bits 6 and 7 set P6 and P7 to output high.

Now, we can read the pin.  We did this operation with the Bus Pirate’s output set to binary mode so that the pin values are immediately obvious.

I2C>{0x41 r}<–command
220 I2C WRITE: 0b01000001 GOT ACK: YES<–address
230 I2C READ: 0b01000000<–pin state

{ issues an I2C start condition, 0x41 is the read address, and r reads one byte from the device. } sends the I2C bus stop condition, ending the transaction.

The reply, 01000000, represents the state of the input pins. The most significant bit is 0 because P7 is tied to ground. The next bit is 1 because P6 is held high The other bits (0) are garbage data.

This is far from the only IO expander IC. Have you used another chip?

Don’t forget to catch up on any parts posts you may have missed.

28 thoughts on “Parts: 8bit IO Expander (PCF8574)

  1. That’s an interesting IC, but I question its usefulness, when something like a PIC18F25J10 is $2.08 on mouser. With something like that, not only do you get 21 high speed gpios (vs the 8 this ic provides), but you can do processing on the input, which can make your life a lot easier, especially if the data is time-sensitive.

    So, meh. For another $0.22, I’d rather get that.

  2. yay :) Nice chip, and very nice introduction. Maybe the right one for my LED-Clock vision.. It’s hard to find a throughhole AVR with 84 io pins. Is there also a version with more ios available? like, 12 or 16?

  3. I have been thinking about how to solve a project of mine over christmas, i have a working version with 14 outputs already, but there is a new requirement to have 35 outputs… I’m already using i2c for a real-time clock and LCD display, and this little chip sounds like its just what i need! I’m using a PICaxe 40×1 and i was thinking about using an old clunky PIA which would suck up output pins to adress more, but this chip looks to me like it has a decent control pin to output pin ratio to me!
    As hex4def6 posted earlier, i don’t think this chip is for everyone, but you know what, there are oodles of chips to choose from out there, its finding the right one for your purpose that is the key, and for low-speed applications like mine, its perfect.
    So thankyou hackaday for (potentially) solving my festive dilemma!

  4. can you guys do a writeup on the maxim 7219? i got a couple as samples, but i’m unsure what other parts i really need to run a full grid of LEDs.

    i know there are some other howtos, but it’d be neat to see the bus pirate doing it.

  5. Don’t forget about the PCF8574’s bigger brother, the PCF8575, which is a remote 16-bit I2C and SMBus I/O expander
    with interrupt output. It has a few more pins to play with, which may be helpful in some cases.

  6. hex4def6:

    I/O expanders are more popular for large production items since they’re cheaper than fullsized microcontrollers. This specific part can be had for $0.90 in large quantities. Also, it can come in a dinky 16 QFN package, saving valuable board space if all you need is a few extra low-speed logic lines.

    For the hobby/hacker market, just buy an arduino mini for $20 and get all the expansion you’d want with no hassle :p.

  7. Have used this chip in the past, worked well ;) two others that I keep a good stock of are


    great for quick projects that pop up.

    A bit pricy, but this came in handy a few times


    Hope someone else finds these useful

  8. brianbek-
    thanks but if you’re trying to help someone not familiar with these chips then you might want to give a little more info.

    8 channel source driver. 80v / 500ma max.

    7 channel darlington array. 50v / 500ma.

    11 channel, 12bit adc

  9. I have used (actually, built) this one, ED1021:—io-expander-with-uart-interface/

    Additionally to the general purpose I/O pins, it can read an analog signal from almost any pin and it has a calibrated internal reference, which means you can read voltages from 0 to around 2.5V with precision of a few mV. It can also connect almost directly (2 resistors required) to most (if not all) typical PC UART ports.

    Feel free to give me improvements/changes suggestions :)!

  10. @joel:
    i agree. i use avr’s and stay far away from i2c. i’m currently working on a pretty big project with and i’ve made sure to use all spi ic’s in the design. just reading about i2c makes my head spin. i can see it being *really* nice for those ucontrollers with hardware support for it, but the avr is not one of them.

  11. Software i2c on an avr/pic is quite simple IMO. Here is the first avr example I found:

    Hardware is definitely more complex, but also offers a lot more features (see atmel appnote AVR315). Also see “two-wire serial interface” in most avr’s datasheets to understand the hardware behind it.

    Anyway, as for the micro vs. a custom IC: think of ease of design (writing/testing firmware), and ease of manufacturing when used commercially.

  12. If you need lots of low-speed digital inputs/outputs, you might consider using chained shift registers, eg. 4094’s. They’re cheap, widely available and easy to interface with.

    Using I²C on AVRs is quite simple using this library:

    I really like it, since it enables you to use the TWI or a software implementation of the protocol via the same interface. Didn’t try the TWI-based stuff, but the software-only part worked great. Just include the header file, add the assembler file to your makefile, adjust the delay routine if necessary and you’re done.

  13. There’s a hidden gotcha with this part which I just encountered (unfortunately after having PC boards fabricated). The outputs can’t actually source much current. The statement on the data sheet that says “latched outputs with high-current drive capability for directly driving leds” actually refers to inverse-logic current sinking, not sourcing. If you look at the current ratings on the Absolute Maximum Ratings table you’ll see that they seem to be “backwards” if you’re thinking in terms of a positive-logic current-sourcing configuration.

    The schematic for this article shows a current-sourcing configuration. Personally I can’t get this chip to drive even a single LED as shown in this schematic, but it works fine in a current-sink configuration.

    See for further discussion.

  14. 4094 is also a good option, I’ve use a pair of them in a project. “low-speed”? What’s low-speed for you, heretic? In my project I had it running at ~302.5KBit/s, including the routine’s RET instruction and non-optimized code&algorithm.

    i2c looks “pretty”, but I actually don’t like it much. The problem is that, even if you have a hardware peripheral for that, you need a lot of code to handle it correctly, when compared to SPI or UART.

  15. I use the MCP23008 (8 bit) and MCP23016 (16 bit) from Microchip. They’re available in SPI variants as well (I find I2C simpler to use, and it uses quite a bit less uC IO too) as MCP23Sxx. The 16 bit version is around the same price as this TI chip, it comes in DIP, SOIC or SSOP (or QFN if you’re insane) and it can source/sink 25mA on every pin. Pretty much nicer in every way ;)

  16. Hi

    I have a project and want to help. I need to have an assembly which connects 4 channels PCF8574 output port 8-bit ( ‘output x8), connected to an I2C bus operated by the 16F877.

    Contact me if you enjoy it on my email directly. Ramzi.bk @

    thank you in advance.

  17. As Adam Schabtach on Dec 28th, 2008 already mentioned, the chip can drive only ~20mA for a LED in pull-down mode. So the schematic is wrong.

    please fix it, or (unskilled) readers of hack a day will produce more electronic waste …

    2nd hint: if you use Arduino, the pull-ups on SCL/SDA are not nessescary, because the Wire lib activates the internal pullups of the atmega.



  18. Hello everyone,

    I am trying to find solutions to my present project, I have msp430f147 ucontroller and I would like to expand the number of ports for my analog inputs. All general purpose i/o pins have been used already. How can I do about this? Thanks for your help.


  19. Just wanted to post.

    TI’s PCF8574(A) is a bit different than NXP/Phillip’s original PCF8574(A).

    The TI can drive up to 100ma per pin, but it lacks 5v tolerant when powered by 3.0/3.3v. The NXP version has the opposite. Crap current restrictions, 5v tolerant at 3.0/3.3v. Now if only there was a 8bit DIP i2c quasi-bidirectional chip with both options…

  20. hi i’m using PCF8574p and I’ve connected LED’s at pin numbers 4,5,6 and 7 i.e p0,p1,p2 and p3 i’m writing to the LED by giving slave address as 0x40 and the data to be sent for glowing the LED is 0x30 making p2 and p3 high when I power on the device all LED’s are high when I dump the code to the controller with the above conditions all LED’s are glowing,
    can anyone suggest me to fix this bug.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.