Expansor de E/S PCF8574

Ejemplo de uso del expansor de E/S PCF8574 con varios microcontroladores.

MICROCONTROLADORES

Biblioman

5/3/20135 min read

El PCF8574 es un expansor de E/S compatible con la mayoría de microcontroladores, permite una comunicación bidireccional, necesitando para ello solo dos líneas a través del bus I2C.

Características del módulo
  • Tensión de alimentación de 2.5 a 6 V CC.

  • Bajo consumo en standby (máximo 10 microamperios).

  • Conversión de datos de I2C a paralelo y viceversa.

  • Un Pin de interrupción de salida a drenador abierto (necesita resistencia pul-up).

  • Un puerto cuasi-bidireccional de ocho bits (necesitan resistencias pul-up).

  • Tres pines disponible para configurar por hardware la dirección del dispositivo.

  • Disponible en encapsulados DIP y SMD.

Diagrama de bloques
Direccionamiento

Este módulo dispone de dos modelos (PCF8574 y PCF8574A) cuya única diferencia es su dirección.

Los primeros cuatro bits vienen configurados de fábrica y los tres últimos son configurables por hardware, por lo que podemos tener 8 módulos conectados al mismo bus I2C (y si combinamos ambas versiones hasta 16).

Funcionamiento

Como cualquier dispositivo I2C la comunicación es a través de dos líneas:

  • SDA: línea serie para los datos.

  • SCL: para la señal de reloj.


Ambas líneas deben de estar conectadas a una alimentación positiva a través de una resistencia pul-up.

El microcontrolador es el que está configurado como maestro y él o los módulos PCF8574 que estén conectados al bus se configuran como esclavos, el maestro es el que realiza las peticiones de lectura o escritura sobre los módulos y controla la señal de reloj (SCL).

La transferencia de datos puede ser inicializada solo cuando el bus no está ocupado.

Una trama de datos en una transmisión consta de:

  • Un bit de inicio de la comunicación.

  • Un byte formado por siete bits que identifican la dirección del esclavo + un bit para indicar si se va hacer una lectura (R/W=1) o escritura (R/W=0) en el módulo.

  • Los datos en sí (de transmisión o recepción); el número de bytes de datos a transmitir o recibir entre el comienzo de la comunicación y la condición de fin de transmisión (bit de parada) no está limitada.

  • Un ACK de reconocimiento. A cada byte transmitido le sigue un bit de reconocimiento, cuando el esclavo recibe un byte este envía el ACK para indicarle al maestro que lo ha recibido correctamente, cuando la petición del maestro al esclavo es de lectura este debe de enviar un ACK al esclavo para indicarle que ha recibido el byte correctamente.

  • Un bit de parada. La condición de parada (P) ocurre cuando la línea SDA cambia de nivel alto a bajo mientras la línea de reloj se encuentra a nivel alto y es controlada por el dispositivo maestro (en nuestro caso el microcontrolador).


Nota: en el segundo vídeo se muestra la explicación sobre el datagrama.


Ejemplos

Los ejemplos están basados en el siguiente módulo que se puede adquirir fácilmente por Internet y que incluye en una pequeña placa el integrado PCF8574 listo para usar:

Ejemplo LCD I2C con Arduino

Vídeo de la demo:

Código fuente de la demo:

/*
** Example Arduino sketch for SainSmart I2C LCD Screen 16x2
** based on https://bitbucket.org/celem/sainsmart-i2c-lcd/src/3adf8e0d2443/sainlcdtest.ino
** by
** Edward Comer
** LICENSE: GNU General Public License, version 3 (GPL-3.0)

** This example uses F Malpartida's NewLiquidCrystal library. Obtain from:
** https://bitbucket.org/fmalpartida/new-liquidcrystal

** Modificado por Biblioman

** NOTE: Tested on Arduino Uno whose I2C pins are A4==SDA, A5==SCL

*/
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR 0x3f // <<-Dirección del esclavo
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

int n = 1;

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

void setup()
{
lcd.begin (16,2); // <<--- LCD 16x2


// Enciende el backlight
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

}

void loop()
{
lcd.setCursor (0,0); // va al comienzo de la 1ª línea LCD
lcd.print("Aquihayapuntes");
lcd.setCursor (0,1); // va al comienzo de la 2ª línea LCD
lcd.print("LCD I2C.......");
delay(3000);

lcd.setCursor (0,0); // va al comienzo de la 1ª línea LCD
lcd.print("LCD I2C.......");
lcd.setCursor (0,1); // va al comienzo de la 2ª línea LCD
lcd.print("Aquihayapuntes");
delay(3000);
}

1º Ejemplo con PICs: Decodificador de binario a hexadecimal

Esquema:

Vídeo de la demo:

Código fuente:

/*--------------------------------------------*\
| Ejemplo uso de bus expansor de 8 bits PC8574 |
| autor: biblioman |
| www.aquihayapuntes.com |
\*---------------------------------------------*/

#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay(clock=4000000)
#use i2c(master,sda=pin_C4,scl=pin_C3,force_hw)

int array[16] = {0xFF,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xA7,0xA1,0x86,0x8E};
int valor=0b11111111;

#int_EXT
void EXT_isr(void){

//Lectura Bus I2C
int tmp=0;
i2c_start(); // Start I2C
i2c_write(0x4F); // Direccion del dispositivo PCF8574 + bit modo lectura
tmp = i2c_read(); //Asigno el valor leído en la variable tmp
tmp=~tmp;//
valor=array[tmp];
i2c_stop(); // Stop

}
void main() {

enable_interrupts(GLOBAL);//habilito interrupción global
enable_interrupts(INT_EXT);//habilito interrupción externa
ext_int_edge(H_TO_L);//interrupción activa a nivel bajo

while(true){
delay_ms(500);
//Escritura del valor en el Bus
i2c_start(); // Inicio
i2c_write(0x42); // Dirección del dispositivo PCF8574 + bit modo escritura
i2c_write(valor);
i2c_stop(); // Stop I2C
}
}

Ejemplo LCD I2C con PIC

Esquema:

Vídeo de la demo:

Código fuente:

/*---------------------------*\
| Ejemplo LCD I2C con PIC |
| autor: biblioman |
| www.aquihayapuntes.com |
\*---------------------------*/

#include <16f877.h>
#use delay(clock=4000000)

#FUSES XT,NOPROTECT,NOWRT,PUT,NOWDT,NOLVP,NOCPD

#include "lcd_i2c.h"

void main()
{

lcd_init();
While(true){
delay_ms(3000);
lcd_gotoxy(1,1);
printf(lcd_putc, "Aquihayapuntes");
lcd_gotoxy(1,2);
printf(lcd_putc, "LCD I2C PIC ");
delay_ms(3000);
lcd_gotoxy(1,1);
printf(lcd_putc, "LCD I2C PIC ");
lcd_gotoxy(1,2);
printf(lcd_putc, "Aquihayapuntes");
}
}

Fuente de la información


Un saludo y hasta la próxima