LCD por I2C no muestra texto

Para el comando limpiar usa 60us después de escribir la instrucción, porque si no lo pones
hará cosas raras.

Acá hice una librería que me funcionó bien, la envío a un registro y los retardos están por decirse ajustados al LCD porque si son menores o mayores empieza a escribir basura o simplemente nada.

Código:
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                        Mi_LCD_lib.C                               ////
////                                                                   ////
////          LIBRERIA GENERICA PARA MANEJAR UNA LCD16X2               ////
////                                                                   ////
////                     DAVID CASTILLO SEVERO                         ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////




/************* COMANDOS PARA LA LCD LA HOJA DE DATOD LA DICE****************/



///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////     PRIMERO QUE NADA HAY QUE DECLARAR LOS COMANDOS QUE            ////
////        HACEN QUE TRABAJE LA LCD, SEGUN LOS COMANDOS               ////
////          HACEN QUE EL LCD SE COMPORTE COMO QUEREMOS               ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////


#define LIMPIAR_LCD                       0x01         //Limpia el display y lo pone a la dirección 1
#define CURSOR_INICIO                     0x02         //Cursor la primera posicion (Dirección 1)
#define DEC_CURSOR                        0x04         //Decrementa el cursor
#define INC_CURSOR                        0x06         //Incrementa el cursor
#define DISPLAY_DER                       0x07         //Rota el display a la derecha
#define DISPLAY_IZQ                       0x05         //Rota el display a la izquierda
#define DSPLY_OFF_CRSR_OFF          0x08         //Apaga el display y el cursor
#define DSPLY_OFF_CRSR_BLNK         0x09         //Apaga el display y el cursor
#define DSPLY_OFF_CRSR_ON              0x0A         //Apaga el display y prende el cursor
#define DSPLY_ON_CRSR_OFF              0x0C         //Enciende el display y apaga el cursor
#define DSPLY_ON_CRSR_OFF_BLNK      0x0D         //Enciende el display y apaga el cursor
#define DSPLY_ON_CRSR_ON               0x0E         //Apaga el display y parpadea el cursor
#define DSPLY_ON_CRSR_BLINK         0x0F         //Enciende el display y parpadea el cursor
#define POSICION_CRSR_IZQ              0x10         //Retrocede el cursor una posición
#define POSICION_CRSR_DER              0x14         //Aumenta el cursor una posición
#define TODO_DISPLAY_IZQ               0x18         //Rota todo el display a la izquierda
#define TODO_DISPLAY_DER               0x1C         //Rota todo el display a la derecha
#define CURSOR_LINEA_1                 0x80         //Pone el cursor en la linea 1 posicion 1
#define CURSOR_LINEA_2                 0xC0         //Pone el cursor en la linea 2 posicion 1
#define BITS_8                               0x38         //Establece la interface de 2 lineas y caracteres de 5x7 puntos con 8 bits de datos
#define BITS_4                               0x28         //Establece la interface de 2 lineas y caracteres de 5x7 puntos con 4 bits de datos

/***************************************************************************/

//    1 tick es 4/FOSC 
//   4/48Mhz = 0.083us
//   1 tick = 0.083us
//   1 tick = Nop();


void delay_us(int num1)
{
   int inc;
   for(inc=0; inc!=num1 ;inc++)      //GENERA 1us
   {
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
      Nop();
   }

}


void delay_ms(int num)
{
   int inc;
   for(inc=0; inc!=num; inc++)
   {
      Delay1KTCYx(12) ;    //1ms = 5 k ticks
   }
      
}






void config_4bit(char CMD)
{
   unsigned char bit8;
  
   //MODO ESCRITUDA EN LA LCD
      //WE =0 
      //RS =0
   //HABILITO LA LCD
      //EN =1
   bit8=0b00000100;
   //ESCRIBO EL COMANDO
   bit8=bit8+CMD;
   gato(bit8);
   delay_us(45);
   //DESHABILITO LA LCD
      //EN= 0   
   bit8=0b00000000;
   bit8=bit8+CMD;
   gato(bit8);  
}


void COMANDO(char CMD)
{
   unsigned char bit8;
   
   char nible1=0;
   char nible2=0;
   
   nible2=CMD;            //EJEMPLO AB EN HEX SOLO TRABAJARE CON EL NIBLE ALTO [1111] [0000] EL NIBLE BAJO SE DESECHA
   
   nible2=nible2>>4;    //AB  ROTADO IZQ QUEDA 0A ,PARA ENVIARLO DEBE SER A LA DERECHA
   nible2=nible2<<4;    //ENTONCES QUEDARIA A0
   
   nible1=CMD<<4;         //AHORA EL NIBLE BAJO DE AB LO ROTO A LA IZQ QUEDARIA SOLO B0


   //ENVIO EL NIBLE ALTO
   //MODO ESCRITUDA EN LA LCD
      //WE =0 
      //RS =0
   //HABILITO LA LCD
      //EN =1
   bit8=0b00000100;
   //ESCRIBO EL COMANDO
   bit8=bit8+nible2;
   gato(bit8);
   delay_us(60);
   



//DESHABILITO LA LCD
      //EN= 0   
   bit8=0b00000000;
   bit8=bit8+nible2;
   gato(bit8);
   
   //ENVIO EL NIBLE BAJO
      //MODO ESCRITUDA EN LA LCD
      //WE =0 
      //RS =0
   //HABILITO LA LCD
      //EN =1
   bit8=0b00000100;
   //ESCRIBO EL COMANDO
   bit8=bit8+nible1;
   gato(bit8);
   delay_us(45);
   //DESHABILITO LA LCD
      //EN= 0   
   bit8=0b00000000;
   bit8=bit8+nible1;
   gato(bit8);
   
}


void dav_gotoxy(unsigned char x, unsigned char y)
{
   unsigned char direccion;
   if(y!=1)
      direccion=0x40;
   else
      direccion=0;
   direccion +=x-1;
   COMANDO(0x80 | direccion);
}



void dav_lcd(char c)
{
   unsigned char bit8;
   char nible1=0;
   char nible2=0;
   
   switch(c)
   {
      case '\f':
      COMANDO(LIMPIAR_LCD);
      delay_ms(2);
      break;
      
      
      case '\n':
      dav_gotoxy(1,2);
      break;
   
      default:
         nible2=c;            //EJEMPLO AB EN HEX SOLO TRABAJARE CON EL NIBLE ALTO [1111] [0000] EL NIBLE BAJO SE DESECHA
   
         nible2=nible2>>4;    //AB  ROTADO IZQ QUEDA 0A ,PARA ENVIARLO DEBE SER A LA DERECHA
         nible2=nible2<<4;    //ENTONCES QUEDARIA A0
   
         nible1=c<<4;         //AHORA EL NIBLE BAJO DE AB LO ROTO A LA IZQ QUEDARIA SOLO B0


         //MODO ESCRITURA
   
            //RS= 1
            //WE= 0
         bit8=0b00000001;
         gato(bit8);
   
         //HABILITO LA LCD
            //EN= 1   
   
         bit8=0b00000101;  
   
         //ENVIO EL NIBLE ALTO
   
         bit8=bit8+nible2;
         gato(bit8);
   
         delay_ms(1);
         //DESHABILITO LA LCD
            //EN= 0
         bit8=0b00000001;
         bit8=bit8+nible2;
         gato(bit8);
   
         delay_ms(1);
   
         //HABILITO LA LCD 
            //EN= 1
         bit8=0b00000101;
         bit8=bit8+nible2;
         gato(bit8);
   
   
         //ENVIO EL NIBLE BAJO
   
         bit8=0b00000101;
         bit8=bit8+nible1;
         gato(bit8);
         delay_ms(1);

         //DESHABILITO LA LCD
            //EN= 0
         bit8=0b00000001;
         bit8=bit8+nible1;
         gato(bit8);
      
      break;
   }
   
   

   
}
       

void lcd_cadena(char *cadena)
{
   char i=0;

   while(cadena[i]!='\0')
   {
      dav_lcd(cadena[i]);
      if(i==15)//cuando llega al maximo da un salto de linea
      {
         COMANDO(CURSOR_LINEA_2);
      }
      i++;
   }
}








void lcd_init()
{

   serial_init();

   //INICIO CON TODO APAGADO  
   gato(0x00);
   delay_ms(15);
   //inicializo el LCD por los 3 comandos de fabrica
   COMANDO(0x30);
   delay_ms(5);
   COMANDO(0x30);
   delay_ms(5);
   COMANDO(0x30);
   delay_ms(5);
   
   
   //inicializo que va a trabajar en 4 bits
   config_4bit(0x20);
     
   //comando 8 bits 0x38 y para 4 bits es 
   COMANDO(BITS_4);
   
   COMANDO(DSPLY_ON_CRSR_OFF);

   COMANDO(LIMPIAR_LCD);
   delay_ms(2);
}
Mi código es pésimo y tal vez redundante pero funcionó. :LOL:
 
Última edición por un moderador:
Gracias Trilo-Byte. Voy a mirar sobre todo el tema de los retardos, aunque como te digo me extraña que el problema esté ahí.
 
¿Tu LCD viene de origen con adaptador para I2C o le has conectado tu directamente al PCF8574?

En el primer caso sigue las instrucciones del manual del LCD.
En el segundo, tu debes manejar el PCF8574 con los datos a visualizar por un lado, y dirigir las líneas de control del LCD, por otro.
 
Hola EdoNork.
Pues mi lcd viene con el PCF8574(A) conectado al lcd .

EdoNork dijo:
En el segundo, tu debes manejar el PCF8574 con los datos a visualizar por un lado, y dirigir las líneas de control del LCD, por otro.

Mediante el PCF8574(A) voy a manejar los datos a visualizar y las lineas de control también, usando el modo de 4 bits del lcd.

Lo que yo tengo dudas es mas sobre el protocolo IIC.

Aún no tengo muy claro qué hay que escribir en el registro IICA( Registro de dirección del mñodulo IIC). Pienso que puede ser la dirección que le damos al microcontrolador para que sea direccionado por otro dispositivo,es decir, cuando actúa como esclavo.

También tengo otra duda, cuando vamos a escribir/leer en un/desde un dispositivo esclavo he leido que los pasos a seguir serían:
1. enviar la señar de start
2. enviar la dirección del esclavo con el bit de RW siendo éste el LSB del byte que enviamos.
3. esperar el ACK
4.
Hasta aquí todo bien pero he leido en algunos sitios que el siguiente paso sería enviar la dirección del registro donde se va a escribir o desde donde se va a leer el byte. ¿Esto es asi? EN caso afirmativo para mi caso podría omitirlo? ya que para escribir o leer de un resgistro en un lcd va todo por medio de comandos.

Lo del registro IICD ya no tengo ninguna duda
 
mermer dijo:
Mediante el PCF8574(A) voy a manejar los datos a visualizar y las lineas de control también, usando el modo de 4 bits del lcd.
Tal vez este programa que escribió Shawn Johnson, te pueda servir.

El programa controla un LCD 16x2 con el IC PCF8574.

Saludos.
 

Adjuntos

  • ex02_PCF8574_lcd.rar
    14.5 KB · Visitas: 83
Una cosa que cabe mencionar, y que a mí me pasó:

Cuando quieras dejar de leer datos, cosa que no creo necesaria para un LCD (que no sé usar), tenés que mandar un NAK (not acknowledge). En CCS se pone "i2c_read(0);" yo perdí un monton de tiempo por ese error.

Espero que te sirva.
 
una duda.
Si conecto la salida SDA de mi micro a un osciloscopio debería ver los datos que voy enviando(la señal start, la dirección los datos..), mediante la comunicación i2c,en el osciloscopio no?
Es que lo he intentado y no aparece nada..
¿Alguien sabe si se puede comprobar con el simulador del codewarrior? y ¿cómo?
 
Buenas tardes.
Escribo por que estoy intentando encender un lcd que va conectado en paralelo a un microcontrolador.
No sé por qué al alimentar el lcd no se ilumina la pantalla. Estoy conectando su patilla Vdd a 5v Vss a 0v y VO a 5V, e independientemente si el código que he escrito para controlarlo funcionase o no, al alimentarlo debería iluminarse no?
¿Sabeis qué puede fallar?
Un saludo y gracias

datasheet:http://www.datasheetarchive.com/dl/Datasheets-SW3/DSASW0048484.pdf ...
 
Hola!
Os comento el problema que tengo. Estoy intentando conectar el arduino uno a una pantalla lcd que tiene un extensor i2c PCF8574 conectado. El lcd que tengo es este:
http://www.ebay.com/itm/IIC-I2C-TWI-SP-I-Serial-Interface2004-20X4-Character-LCD-Module-Display-Blue-/310575296583?

La dirección del lcd es 0x20.

En esta página se pueden descargar la librería para conectar el lcd via i2c:
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads pero no sé cual de todas las librerías tengo que usar. Aun así he intentado las 3 y no me funciona y no entiendo por qué.

En la página de arduino http://playground.arduino.cc/Code/LCDi2c también encontramos una librería para este caso (PCF8574-HD44780 LiquidCrystal_I2C.zip) que se corresponde con la versión ,de la página anterior, que se encuentra dentro de la carpeta LiquidCrystal_v1.2.0.zip



He probado con este sketch que encontré en esta página ( mi lcd es el de la versión 3)http://arduino-info.wikispaces.com/LCD-Blue-I2C#v3 y la librería que os he comentado en el último parrafo, la que he encontrado en la página de arduino,
Código:
/* YourDuino.com Example Software Sketch
 20 character 4 line I2C Display
 Backpack Interface labelled "LCM1602 IIC  A0 A1 A2"
 terry@yourduino.com */

/*-----( Import needed libraries )-----*/
#include <Wire.h>  // Comes with Arduino IDE
// Get the LCD I2C Library here: 
// https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
// Move any other LCD libraries to another folder or delete them
// See Library "Docs" folder for possible commands etc.
#include <LiquidCrystal_I2C.h>

/*-----( Declare Constants )-----*/
//none
/*-----( Declare objects )-----*/
// set the LCD address to 0x20 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


/*-----( Declare Variables )-----*/
//none

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
  Serial.begin(9600);  // Used to type in characters

  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines and turn on backlight

// ------- Quick 3 blinks of backlight  -------------
  for(int i = 0; i< 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on  
  
//-------- Write characters on the display ----------------
// NOTE: Cursor Position: CHAR, LINE) start at 0  
  lcd.setCursor(3,0); //Start at character 4 on line 0
  lcd.print("Hello, world!");
  delay(1000);
  lcd.setCursor(2,1);
  lcd.print("From YourDuino");
  delay(1000);  
  lcd.setCursor(0,2);
  lcd.print("20 by 4 Line Display");
  lcd.setCursor(0,3);
  delay(2000);   
  lcd.print("http://YourDuino.com");
  delay(8000);
// Wait and then tell user they can start the Serial Monitor and type in characters to
// Display. (Set Serial Monitor option to "No Line Ending")
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("Start Serial Monitor");
  lcd.setCursor(0,1);
  lcd.print("Type chars 2 display");   


}/*--(end setup )---*/


void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  {
    // when characters arrive over the serial port...
    if (Serial.available()) {
      // wait a bit for the entire message to arrive
      delay(100);
      // clear the screen
      lcd.clear();
      // read all the available characters
      while (Serial.available() > 0) {
        // display each character to the LCD
        lcd.write(Serial.read());
      }
    }
  }

}/* --(end main loop )-- */


/* ( THE END ) */

pero me sale este error LCD1:20: error: 'POSITIVE' was not declared in this scope



aun que sí cambió la linea
Código:
LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

por

Código:
LiquidCrystal_I2C lcd(0x20,20,4);  // Set the LCD I2C address

ya no se sale ningún error,pero al cargarlo en el lcd no aparece nada.

¿Alguien sabe por qué?
Gracias de antemano
 
Hola Mermer. No se si lo has solucionado ya, pero más vale tarde que nunca.
El módulo I2C que has comprado (o al menos en la que aparece en la página de Ebay) tiene la dirección 0x27, no la 0x20. Los que he utilizado yo me han funcionado con 0x27.
En mi caso yo tuve un problema con la tensión de alimentación del LCD (Lo puse a 3'3V, mi analizador mostraba bien la entrada de datos al LCD porque el módulo I2C puede funcionar a estas dos tensiones, pero sin embargo el LCD no era capaz de mostrar nada).
Por otro lado, en mi caso (No se si sucede lo mismo con Arduino) hay que añadir unas resistencias Pull-Up tanto en SDL como en SDA para no tener problemas. (http://www.chibios.org/dokuwiki/doku.php?id=chibios:community:guides:i2c_trouble_shooting).

Un saludo.
 
Atrás
Arriba