Parts: 8bit IO Expander (PCF8574)

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.

pcf8574

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).

Output

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
210 I2C START CONDITION
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0x01 GOT ACK: YES<–output value
240 I2C STOP CONDITION
I2C>

{ 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
210 I2C START CONDITION
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0x00 GOT ACK: YES<–output value
240 I2C STOP CONDITION
I2C>

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

Input

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
210 I2C START CONDITION
220 I2C WRITE: 0x40 GOT ACK: YES<–write address
220 I2C WRITE: 0xC0 GOT ACK: YES<–output value
240 I2C STOP CONDITION
I2C>

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
210 I2C START CONDITION
220 I2C WRITE: 0b01000001 GOT ACK: YES<–address
230 I2C READ: 0b01000000<–pin state
240 I2C STOP CONDITION
I2C>

{ 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.

Comments

  1. hex4def6 says:

    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. jan says:

    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. vsnine says:

    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. Bau says:

    I2C is a biatch on AVR and probably on PIC platform as well. I can see the sexyness of an i2c io chip but really, what do you get in exchange of the added complexity and i2c timing drama?

  6. Tony says:

    Visine

    If you are using an Arduino check this out: http://www.arduino.cc/playground/Main/MAX72XXHardware

    Even if you aren’t it is pretty clearly explained. Hope that helps!

  7. Joel says:

    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.

  8. pc486 says:

    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.

  9. Brianbek says:

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

    UDN2981A
    ULN2003A

    great for quick projects that pop up.

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

    TLC2543CN

    Hope someone else finds these useful

  10. jimmys says:

    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.

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

    ULN2003A
    7 channel darlington array. 50v / 500ma.

    TLC2543CN
    11 channel, 12bit adc

  11. Njay says:

    I have used (actually, built) this one, ED1021:

    http://embeddeddreams.com/site/products-page/edchips/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 :)!

  12. andrew says:

    @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.

  13. andrew says:

    *woops, i meant @bau

  14. jproach says:

    Software i2c on an avr/pic is quite simple IMO. Here is the first avr example I found: http://google.com/codesearch/p?hl=en#u1hJZLnlbRM/lcd_i2c/i2c.c&q=i2c%20avr

    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.

  15. heretic says:

    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:

    http://homepage.hispeed.ch/peterfleury/avr-software.html

    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.

  16. Adam Schabtach says:

    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 http://www.picaxeforum.co.uk/showthread.php?p=81787 for further discussion.

  17. Njay says:

    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.

  18. jetblack says:

    thanks for the write up , good work keep them coming

  19. error404 says:

    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 ;)

  20. heretic says:

    @ njay:

    when i wrote “low-speed”, what i was thinking was “slower than the microcontrollers gpio pins”.
    It’s still very fast, yes.

  21. ramzi says:

    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 @ hotmail.com

    thank you in advance.

  22. Code says:

    Cleaning up my room, Found me Arduino back.
    Also already orderd a Bus-Pirate.

    And found a bag of samples (PCF8574) So i’m busy this Vacation :P

  23. rf says:

    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.

    greetz

    rf

  24. Sherwin says:

    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.

    Sherwin

  25. cde says:

    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…

  26. redwire says:

    CAUTION this chip powers up with all outputs high, which can cause some drama.

  27. shivaraj says:

    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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 96,710 other followers