Overview
The PCF8574/PCF8574A is a TWI I/O expansion chip with an 8-bit quasi-bidirectional
bi-directional pin. Those two version PCF8574 and PCF8574A are identical in functionalities but they have a different slave address 0x40 (write) for the PCF8574 and 0x70 (write) for the PCF8574A. This chip is very easy to find due to a variety of manufactures such as NXP and Texas Instruments etc.
This chip is applicable for,
- LED signs and displays
- Servers
- Key pads
- Industrial control
- Medical equipment
- PLC
- Cellular telephones
- Mobile devices
- Gaming machines
- Instrumentation and test measurement.
For electronic hobbyists and students this chip is commonly found in an HD44780 LCD controller or even a matrix keypad.
Since it uses TWI its communication protocol could be done from scratch even using a micro-controller without a TWI module inside. Software bit banging is a preferred method for most of programmers since since they don't need to know about the detail of the device's communication protocol. It's user friendly to most hobbyists and students since it has ad DIP package. It's widely available both in a single DIP chip or even in a module at very low cost. Arduino is the most common micro-controller that's very easily to interface and program with this chip.
| A PCF8574AP DIP |
| A character LCD with a PCF8574T |
This 16-pin I2C device is very simple to use.
| Block diagram |
There a DIP and two SMD versions.
| Pinning information |
These pins are power supply pins, TWI pins, interrupt output pins and 8-bit I/O pin.
| Pin description |
We can use multiple PCF8574 series on a single TWI bus depends on the additional address selecting pins A2:A0.
| Device address |
Some master MCU use only a 7-bit address for example the Arduino.
| Address maps
|
| Address maps |
There are only devices slave address and I/O port register without additional data direction and control registers. Its I/O port is similar to the 8051 micro-controller series. The master MCU just need to read and write the I/O port.
| Writing to the port (Output mode)
|
| Reading from a port (Input mode)
|
The PCF8574/74A provides an open-drain output (INT) which can be fed to a corresponding input of the microcontroller. As soon as a port input ischanged, the INT will be active (LOW) and notify the microcontroller.
An interrupt is generated at any rising or falling edge of the port inputs.
After time tv(Q), the
signal INT is valid.
The interrupt will reset to HIGH when data on the port is changed to the original setting or data is read or written by the master.
In the Write mode, the interrupt may be reset (HIGH) on the rising edge of the acknowledge
bit of the address byte and also on the rising edge of the write to port pulse.
The interrupt will always be reset (HIGH) on the falling edge of the write to
port pulse. The interrupt is reset (HIGH) in the Read mode on the rising edge
of the read from port pulse .
During the interrupt reset, any I/O change close to the read or write pulse may
not generate an interrupt, or the interrupt will have a very short pulse. After
the interrupt is reset, any change in I/Os will be detected and transmitted as
an INT.
At power-on reset all ports are in Input mode and the initial state of the
ports is HIGH, therefore, for any port pin that is pulled LOW or driven LOW by
external source, the interrupt output will be active (output LOW).
| Interrupt output (INT) |
ATMega644 TWI and PCF8574AP
Using the PCF8574AP with an AVR micro-controller could be done from scratch via its TWI or software bit banging. However I have wrote some of its most commonly used routine of hardware TWI in previous post.
| AVR Experiment Board |
In this introductory example, the ATMega644P TWI master just send data to the PCF8574AP that its output port connects to LEDs.
Source Code:
- /*
- * 10-i2c_pcf8574ap.c
- *
- * Created: 2/1/2026 8:28:10 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const char pcf8574_w=0x40;
- const char pcf8574_r=0x41;
- const char pcf8574a_w=0x70;
- const char pcf8574a_r=0x71;
- void i2cInit(void){
- TWSR|=0x00; //Prescaler Selection Bit
- TWBR=0xF0; //Baud Rate Generator
- TWCR=(1<<TWEN); //Enable The TWI Module
- PORTC|=(1<<0);
- PORTC|=(1<<1);
- }
- void i2cStart(void){
- TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- void i2cWrite(unsigned char data){
- TWDR=data;
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- unsigned char i2cRead(char ACK){
- if(ACK==0)
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
- else
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- return TWDR;
- }
- void i2cStop(){
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
- _delay_us(10);
- }
- int main(void)
- {
- /* Replace with your application code */
- i2cInit();
- char temp=0;
- while (1)
- {
- i2cStart();
- i2cWrite(pcf8574a_w);
- i2cWrite(~temp);
- i2cStop();
- temp++;
- _delay_ms(250);
- }
- }
Schematic:
| Schematic and Simulation |
AVR Experiment Board:
| AVR Experiment Board |
| AVR Experiment Board |
I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.
![]() |
| 10 PCBs for only 5USD |
For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.
![]() |
| PCBWay Instant Quote |
However the I/O port of this chip is bi-directional. So we can use it read the input from any sensors or buttons. This example the master MCU read the input from the lower nibble of the PCF8574AP and display it back to the higher nibble of the PCF8574AP.
Source Code:
- /*
- * 10-i2c_pcf8574ap_r_w.c
- *
- * Created: 2/1/2026 8:49:04 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const char pcf8574_w=0x40;
- const char pcf8574_r=0x41;
- const char pcf8574a_w=0x70;
- const char pcf8574a_r=0x71;
- void i2cInit(void){
- TWSR|=0x00; //Prescaler Selection Bit
- TWBR=0xF0; //Baud Rate Generator
- TWCR=(1<<TWEN); //Enable The TWI Module
- PORTC|=(1<<0);
- PORTC|=(1<<1);
- }
- void i2cStart(void){
- TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- void i2cWrite(unsigned char data){
- TWDR=data;
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- unsigned char i2cRead(char ACK){
- if(ACK==0)
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
- else
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- return TWDR;
- }
- void i2cStop(){
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
- _delay_us(10);
- }
- int main(void)
- {
- /* Replace with your application code */
- i2cInit();
- char temp=0;
- i2cStart();
- i2cWrite(pcf8574a_w);
- i2cWrite(0x0F);
- i2cStop();
- while (1)
- {
- i2cStart();
- i2cWrite(pcf8574a_r);
- temp=i2cRead(1);
- i2cStop();
- temp<<=4;
- i2cStart();
- i2cWrite(pcf8574a_w);
- i2cWrite(temp|0x0F);
- i2cStop();
- }
- }
Schematic:
| Schematic and Simulation |
AVR Experiment Board:
| Program Test on my AVR Prototype Board |


No comments:
Post a Comment