Autor Tema: Problema Libreria Lcd  (Leído 3612 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Problema Libreria Lcd
« en: 26 de Mayo de 2020, 02:37:17 »
Buenas tardes a todos, estoy intentando adaptar una libreria para un lcd LM016L de 16x2, para usarla desde el bus i2c, primero estoy buscando que me funcione usando el PORTB pero no me termina de desplegar nada en la pantalla, ya estuve revisando bastante el codigo pero no logro encontrar el problema, estoy usando un micro atmel atmega328p. Agradeceria que alguien me pudiera echar un cable, saludos

Cabecera
Código: C
  1. #define LCD_PORT              PORTB
  2. #define LCD_DDDR              DDRB
  3. #define LCD_BACKLIGHT         0x08
  4. #define LCD_NOBACKLIGHT       0x00
  5. #define LCD_FIRST_ROW         0x80
  6. #define LCD_SECOND_ROW        0xC0
  7. #define LCD_THIRD_ROW         0x94
  8. #define LCD_FOURTH_ROW        0xD4
  9. #define LCD_CLEAR             0x01
  10. #define LCD_RETURN_HOME       0x02
  11. #define LCD_ENTRY_MODE_SET    0x04
  12. #define LCD_CURSOR_OFF        0x0C
  13. #define LCD_UNDERLINE_ON      0x0E
  14. #define LCD_BLINK_CURSOR_ON   0x0F
  15. #define LCD_MOVE_CURSOR_LEFT  0x10
  16. #define LCD_MOVE_CURSOR_RIGHT 0x14
  17. #define LCD_TURN_ON           0x0C
  18. #define LCD_TURN_OFF          0x08
  19. #define LCD_SHIFT_LEFT        0x18
  20. #define LCD_SHIFT_RIGHT       0x1E
  21. #define LCD_TYPE              2 // 0 -> 5x7 | 1 -> 5x10 | 2 -> 2 lines
  22.  
  23. //prototipos
  24.  
  25. //static void lcd_write_4bit(unsigned char Nibble);
  26. //static void lcd_cmd(unsigned char cmd);
  27. void lcd_write_char(unsigned char data);
  28. void lcd_write_string(char* str);
  29. void lcd_set_cursor(unsigned char row, unsigned char column);
  30. void lcd_clear();
  31. void lcd_init();

Archivo .c
Código: C
  1. #include "lcd_std.h"
  2.  
  3. unsigned char RS;
  4.  
  5. static void lcd_write_4bit(unsigned char Nibble)
  6. {
  7.         Nibble |= RS;
  8.         LCD_PORT = (Nibble | 0x04);          //bit EN en alto  00000100
  9.         _delay_us(50);
  10.         LCD_PORT = (Nibble | 0xFB);          //bit EN en bajo
  11.         _delay_us(50);
  12. }
  13.  
  14. static void lcd_cmd(unsigned char cmd)
  15. {
  16.         RS = 0;            //se enviara comando
  17.         lcd_write_4bit(cmd & 0xF0);                     //envia Nibble alto
  18.         lcd_write_4bit((cmd << 4) & 0xF0);              //envia Nibble bajo
  19. }
  20.  
  21. void lcd_write_char(unsigned char data)
  22. {
  23.         RS = 1;            //se enviara data
  24.         lcd_write_4bit(data & 0xF0);                     //envia Nibble alto
  25.         lcd_write_4bit((data << 4) & 0xF0);              //envia Nibble bajo
  26. }
  27.  
  28. void lcd_write_string(char* str)
  29. {
  30.         unsigned char i;
  31.         for (i = 0; str[i] != '\0'; i++)
  32.         {
  33.                 lcd_write_char(str[i]);
  34.         }
  35. }
  36.  
  37. void lcd_gotoxy(unsigned char row, unsigned char column)
  38. {
  39.         if (row == 1)
  40.         {
  41.                 lcd_cmd(0x80 + column - 1);
  42.         }
  43.         else
  44.         {
  45.                 lcd_cmd(0xC0 + column - 1);
  46.         }
  47. }
  48.  
  49. void lcd_clear()
  50. {
  51.         lcd_cmd(0x01);
  52.         _delay_us(40);
  53. }
  54.  
  55. void lcd_init()
  56. {
  57.         LCD_DDDR = 0xFF;           //PORTB como salida
  58.        
  59.    LCD_PORT = 0x00;
  60.   _delay_ms(30);
  61.   lcd_cmd(0x03);
  62.   _delay_ms(5);
  63.   lcd_cmd(0x03);
  64.   _delay_ms(5);
  65.   lcd_cmd(0x03);
  66.   _delay_ms(5);
  67.   lcd_cmd(LCD_RETURN_HOME);
  68.   _delay_ms(5);
  69.   lcd_cmd(0x20 | (LCD_TYPE << 2));
  70.   _delay_ms(50);
  71.   lcd_cmd(LCD_TURN_ON);
  72.   _delay_ms(50);
  73.   lcd_cmd(LCD_CLEAR);
  74.   _delay_ms(50);
  75.   lcd_cmd(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
  76.   _delay_ms(50);
  77. }

main.c
Código: C
  1. #define F_CPU 1000000UL
  2. #include <avr/io.h>
  3. #include <util/delay.h>
  4. #include "lcd_std.h"
  5.  
  6. int main(void)
  7. {
  8.     /* Replace with your application code */
  9.         lcd_init();
  10.         _delay_ms(1000);
  11.         lcd_clear();
  12.         lcd_gotoxy(1,1);
  13.         lcd_write_string("hola");
  14.        
  15.     while (1)
  16.     {
  17.                
  18.     }
  19. }
« Última modificación: 26 de Mayo de 2020, 16:31:25 por BroncoITC »

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re:Problema Libreria Lcd
« Respuesta #1 en: 26 de Mayo de 2020, 10:05:00 »
¿Qué lenguaje C estás usando?
Esta pregunta me delata, pero los lenguajes de alto nivel son parecidos a la hora de trabajar.

En otros lenguajes no se hace tantas cosas para trabajar con un LCD y estoy sospechando que no sabes usar las librerías.

Para adelantar, normalmente, se parte de un código. Se inicializan las cosas, luego se va al main o al bucle infinito y se comienza enviar datos; la espera de datos, procesar datos, ect.

A la hora de inicializar el LCD, se incluye la librería, se configura la librería con una función dedicada a ello y luego se le envía los datos.
Por ejemplo. Para configurar la librería, dicha librería tiene una función de configuración; donde se le indica en qué puerto está conectado el LCD, si los datos se envían por los 8 bit o en 4 bit, y algunas cosillas más. Luego, se inicializa el LCD para luego enviarle los datos.
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado Eduardo2

  • PIC24H
  • ******
  • Mensajes: 1004
Re:Problema Libreria Lcd
« Respuesta #2 en: 26 de Mayo de 2020, 13:26:30 »
Código: [Seleccionar]
void lcd_write_char(unsigned char data)
{
        RS = 1;            //se enviara data
        lcd_write_4bit(cmd & 0xF0);                     //envia Nibble alto
        lcd_write_4bit((cmd << 4) & 0xF0);              //envia Nibble bajo
}

Raro que te lo haya compilado pues cmd no está definido.

Debe ser
Código: [Seleccionar]
void lcd_write_char(unsigned char data)
{
        RS = 1;            //se enviara data
        lcd_write_4bit(data & 0xF0);                     //envia Nibble alto
        lcd_write_4bit((data << 4) & 0xF0);              //envia Nibble bajo
}

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Re:Problema Libreria Lcd
« Respuesta #3 en: 26 de Mayo de 2020, 16:39:40 »
¿Qué lenguaje C estás usando?
Esta pregunta me delata, pero los lenguajes de alto nivel son parecidos a la hora de trabajar.

En otros lenguajes no se hace tantas cosas para trabajar con un LCD y estoy sospechando que no sabes usar las librerías.

Para adelantar, normalmente, se parte de un código. Se inicializan las cosas, luego se va al main o al bucle infinito y se comienza enviar datos; la espera de datos, procesar datos, ect.

A la hora de inicializar el LCD, se incluye la librería, se configura la librería con una función dedicada a ello y luego se le envía los datos.
Por ejemplo. Para configurar la librería, dicha librería tiene una función de configuración; donde se le indica en qué puerto está conectado el LCD, si los datos se envían por los 8 bit o en 4 bit, y algunas cosillas más. Luego, se inicializa el LCD para luego enviarle los datos.

Hola, estoy usando el ide atmel studio 7 el compilador creo que es el avr gcc, desconozco el estándar de C que utilice si el ANSI o el C99 u otro.
Y tienes razón, apenas se usar las librerías.

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Re:Problema Libreria Lcd
« Respuesta #4 en: 26 de Mayo de 2020, 16:43:01 »
Código: [Seleccionar]
void lcd_write_char(unsigned char data)
{
        RS = 1;            //se enviara data
        lcd_write_4bit(cmd & 0xF0);                     //envia Nibble alto
        lcd_write_4bit((cmd << 4) & 0xF0);              //envia Nibble bajo
}

Raro que te lo haya compilado pues cmd no está definido.

Debe ser
Código: [Seleccionar]
void lcd_write_char(unsigned char data)
{
        RS = 1;            //se enviara data
        lcd_write_4bit(data & 0xF0);                     //envia Nibble alto
        lcd_write_4bit((data << 4) & 0xF0);              //envia Nibble bajo
}

Gracias Eduardo2, pero eso fue un error al copiar aqui una version del programa que no habia depurado bien, en realidad ya me habia percatado de eso antes de compilarlo.
Sospecho que el problema esta en la funcion lcd_write_4bit, donde hace esto : LCD_PORT = (Nibble | 0x04);
Pero solo es una corazonada... :(
« Última modificación: 26 de Mayo de 2020, 16:45:37 por BroncoITC »

Desconectado AleSergi

  • PIC16
  • ***
  • Mensajes: 214
Re:Problema Libreria Lcd
« Respuesta #5 en: 27 de Mayo de 2020, 01:00:09 »
hola, mira si andas en eso de entender finamente el funcionamiento de los lcd hitachi 44780 genéricos, te recomiendo que con la hoja de datos en mano veas los videos del U2, donde muestran como los manejan manualmente a fuerza de mini interruptores dip.
Luego te bajas y estudias las librerias de Donald Weiman, donde hace funcionar esos lcd, muy didacticamente.

http://web.alfredstate.edu/faculty/weimandn/index.html

Ahira de todo ésto y sabiendo como funcionan los integrados i2c pcf8574, podrás entender  como hacer tu propia librería versión i2c, o mejor usar una ya lista, como es el caso del greco Vassilis Serasidis, donde muestra hasta con video como controla varias cosas i2c...

https://www.serasidis.gr/circuits/i2c_sensors/I2C_sensors.htm

Hice todo lo que digo y llegue a buen puerto, y logre que me funcionen esas librerias i2c, que en realidad las escribio un tal Davide Gironi, y con el WinAvr, con el Studio 7, te ira mejor.

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re:Problema Libreria Lcd
« Respuesta #6 en: 27 de Mayo de 2020, 09:08:42 »
tienes razón, apenas se usar las librerías.

No te preocupes, te vamos a enseñar.

¿Podrías subir la librería lcd_std.h?
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Re:Problema Libreria Lcd
« Respuesta #7 en: 29 de Mayo de 2020, 01:28:54 »
Hola LeonPic, "lcd_std.h" es el archivo de cabecera, esto :
Código: C
  1. #define LCD_PORT              PORTB
  2. #define LCD_DDDR              DDRB
  3. #define LCD_BACKLIGHT         0x08
  4. #define LCD_NOBACKLIGHT       0x00
  5. #define LCD_FIRST_ROW         0x80
  6. #define LCD_SECOND_ROW        0xC0
  7. #define LCD_THIRD_ROW         0x94
  8. #define LCD_FOURTH_ROW        0xD4
  9. #define LCD_CLEAR             0x01
  10. #define LCD_RETURN_HOME       0x02
  11. #define LCD_ENTRY_MODE_SET    0x04
  12. #define LCD_CURSOR_OFF        0x0C
  13. #define LCD_UNDERLINE_ON      0x0E
  14. #define LCD_BLINK_CURSOR_ON   0x0F
  15. #define LCD_MOVE_CURSOR_LEFT  0x10
  16. #define LCD_MOVE_CURSOR_RIGHT 0x14
  17. #define LCD_TURN_ON           0x0C
  18. #define LCD_TURN_OFF          0x08
  19. #define LCD_SHIFT_LEFT        0x18
  20. #define LCD_SHIFT_RIGHT       0x1E
  21. #define LCD_TYPE              2 // 0 -> 5x7 | 1 -> 5x10 | 2 -> 2 lines
  22.  
  23. //prototipos
  24.  
  25. //static void lcd_write_4bit(unsigned char Nibble);
  26. //static void lcd_cmd(unsigned char cmd);
  27. void lcd_write_char(unsigned char data);
  28. void lcd_write_string(char* str);
  29. void lcd_set_cursor(unsigned char row, unsigned char column);
  30. void lcd_clear();
  31. void lcd_init();

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Re:Problema Libreria Lcd
« Respuesta #8 en: 29 de Mayo de 2020, 01:37:40 »
hola, mira si andas en eso de entender finamente el funcionamiento de los lcd hitachi 44780 genéricos, te recomiendo que con la hoja de datos en mano veas los videos del U2, donde muestran como los manejan manualmente a fuerza de mini interruptores dip.
Luego te bajas y estudias las librerias de Donald Weiman, donde hace funcionar esos lcd, muy didacticamente.

http://web.alfredstate.edu/faculty/weimandn/index.html

Ahira de todo ésto y sabiendo como funcionan los integrados i2c pcf8574, podrás entender  como hacer tu propia librería versión i2c, o mejor usar una ya lista, como es el caso del greco Vassilis Serasidis, donde muestra hasta con video como controla varias cosas i2c...

https://www.serasidis.gr/circuits/i2c_sensors/I2C_sensors.htm

Hice todo lo que digo y llegue a buen puerto, y logre que me funcionen esas librerias i2c, que en realidad las escribio un tal Davide Gironi, y con el WinAvr, con el Studio 7, te ira mejor.

Muchas gracias, me ha sido de gran utilidad, en este momento me estoy estudiando la libreria lcd_4bit de Donald Weiman, haber que saco de ella

Desconectado BroncoITC

  • PIC10
  • *
  • Mensajes: 7
Re:Problema Libreria Lcd
« Respuesta #9 en: 26 de Enero de 2021, 17:21:33 »
Han pasado varios meses desde que abri este hilo, pongo aqui el codigo funcionando :

lcd_i2c.h
Código: [Seleccionar]
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "i2c_lib.h"

#define LCD_BACKLIGHT         0x08
#define LCD_NOBACKLIGHT       0x00
#define LCD_FIRST_ROW         0x80
#define LCD_SECOND_ROW        0xC0
#define LCD_THIRD_ROW         0x94
#define LCD_FOURTH_ROW        0xD4
#define LCD_CLEAR             0x01
#define LCD_RETURN_HOME       0x02
#define LCD_ENTRY_MODE_SET    0x04
#define LCD_CURSOR_OFF        0x0C
#define LCD_UNDERLINE_ON      0x0E
#define LCD_BLINK_CURSOR_ON   0x0F
#define LCD_MOVE_CURSOR_LEFT  0x10
#define LCD_MOVE_CURSOR_RIGHT 0x14
#define LCD_TURN_ON           0x0C
#define LCD_TURN_OFF          0x08
#define LCD_SHIFT_LEFT        0x18
#define LCD_SHIFT_RIGHT       0x1E
#define LCD_TYPE              2 // 0 -> 5x7 | 1 -> 5x10 | 2 -> 2 lines



void LCD_Init();
void i2c_escribe(unsigned char Data);
void LCD_Write_4Bit(unsigned char Nibble);
void LCD_CMD(unsigned char CMD);
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL);
void LCD_Write_Char(char);
void LCD_Write_String(char*);
void Backlight();
void noBacklight();
void LCD_SR();
void LCD_SL();
void LCD_Clear();

unsigned char RS, BackLight_State = LCD_BACKLIGHT;
unsigned char i2c_add;

void LCD_Init()
{
  //i2c_add = I2C_Add;
  sei();
  i2c_iniciar();
  i2c_escribe(0x00);
  _delay_ms(30);
  LCD_CMD(0x03);
  _delay_ms(5);
  LCD_CMD(0x03);
  _delay_ms(5);
  LCD_CMD(0x03);
  _delay_ms(5);
  LCD_CMD(LCD_RETURN_HOME);
  _delay_ms(5);
  LCD_CMD(0x20 | (LCD_TYPE << 2));
  _delay_ms(50);
  LCD_CMD(LCD_TURN_ON);
  _delay_ms(50);
  LCD_CMD(LCD_CLEAR);
  _delay_ms(50);
  LCD_CMD(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
  _delay_ms(50);
}

void i2c_escribe(unsigned char Data)
{
i2c_inicia_com();
i2c_envia_dato(0b01001110);         //0b01110000   01001110
_delay_us(80);
i2c_envia_dato(Data | BackLight_State);
_delay_us(80);
i2c_detener();
}

 /*
void IO_Expander_Write(unsigned char Data)
{
  I2C_Master_Start();
  I2C_Master_Write(i2c_add);
  I2C_Master_Write(Data | BackLight_State);
  I2C_Master_Stop();
}*/
 
void LCD_Write_4Bit(unsigned char Nibble)
{
  // Get The RS Value To LSB OF Data
  Nibble |= RS;
  i2c_escribe(Nibble | 0x04);
  i2c_escribe(Nibble & 0xFB);
  _delay_us(50);
}
 
void LCD_CMD(unsigned char CMD)
{
  RS = 0; // Command Register Select
  LCD_Write_4Bit(CMD & 0xF0);
  LCD_Write_4Bit((CMD << 4) & 0xF0);
}
 
void LCD_Write_Char(char Data)
{
  RS = 1; // Data Register Select
  LCD_Write_4Bit(Data & 0xF0);
  LCD_Write_4Bit((Data << 4) & 0xF0);
}
 
void LCD_Write_String(char* Str)
{
  for(int i=0; Str[i]!='\0'; i++)
    LCD_Write_Char(Str[i]);
}
 
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL)
{
  switch(ROW)
  {
    case 2:
      LCD_CMD(0xC0 + COL-1);
      break;
    case 3:
      LCD_CMD(0x94 + COL-1);
      break;
    case 4:
      LCD_CMD(0xD4 + COL-1);
      break;
    // Case 1
    default:
      LCD_CMD(0x80 + COL-1);
  }
}

void LCD_SL()
{
  LCD_CMD(0x18);
  _delay_us(40);
}
 
void LCD_SR()
{
  LCD_CMD(0x1C);
  _delay_us(40);
}
 
void LCD_Clear()
{
  LCD_CMD(0x01);
  _delay_us(40);
}

i2c.h
Código: [Seleccionar]
#include <avr/io.h>

void i2c_iniciar();      //función para iniciar el módulo TWI I2C AVR
void i2c_espera();       //función de espera
void i2c_inicia_com();   //función que inicia la comunicación I2C AVR
void i2c_detener();      //función que detiene la comunicación I2C AVR
void i2c_envia_dato(unsigned char );   //función para enviar o escribir
//datos en el esclavo
unsigned char i2c_recibe_dato_ack();   //función para recibir o leer datos del esclavo
//enviando el bit ACK si se quiere leer mas datos
//después del último leído
unsigned char i2c_recibe_dato_nack();  //función para recibir o leer datos del esclavo
//sin enviar el bit ACK si no se quiere leer mas datos
//después del último leido
uint8_t i2c_estado_com();  //función para averiguar el estado de la comunicación I2C AVR
//útil para detectar errores

//void i2c_escribe(unsigned char data);         //funcion general para escribir

void i2c_iniciar()
{
//PORTC = (1<<4) | (1<<5);         //Activa las resistencias pull up de los pines de scl y sda
//TWBR = 17;                        //velocidad 400Khz, Fosc 8Mhz, prescaler de 1
//TWSR &=~ (1<<TWPS0);
//TWSR &=~ (1<<TWPS1);
TWBR = 17;
TWCR |= (1<<TWEN);               //módulo TWI iniciado
PRR &=~ (1<<PRTWI);
}

void i2c_espera()
{
while ((TWCR & (1<<TWINT)) == 0);
}

void i2c_inicia_com()
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//bandera de interrupción a 1, start, habilita I2C AVR
i2c_espera();       //espera mientras el bit TWINT sea 0
}

void i2c_detener()
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);//bandera de interrupción a 1, detener, habilita I2C AVR
}

void i2c_envia_dato(unsigned char dato) {
TWDR = dato;
TWCR = (1<<TWINT)|(1<<TWEN);//para empezar a enviar el dato
i2c_espera();//cuando TWINT se ponga a 1 se habrá terminado de enviar el dato
}

unsigned char i2c_recibe_dato_ack(){//maestro envia ack para seguir recibiendo
//mas  datos
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
i2c_espera();
return TWDR;
}

unsigned char i2c_recibe_dato_nack(){//maestro no envia ack para no seguir recibiendo
//mas  datos
TWCR = (1<<TWINT)|(1<<TWEN);
i2c_espera();
return TWDR;
}

uint8_t i2c_estado_com(){
uint8_t estado;        //variable donde se almacena el estado de la comunicación
//I2C AVR
estado = TWSR & 0xf8;  //en la variable estado se guarda el valor de los 5 bits de
//mas peso del registro TWSR seguidos de 3 ceros,
//el número obtenido indica
//el estado en que se encuentra la comunicación I2C AVR

return estado;         //la función retorna el estado de la comunicación
}

main.c
Código: [Seleccionar]
#include <avr/io.h>
#include <util/delay.h>
#include "lcd_i2c.h"
int main(void)
{
    LCD_Clear();
    LCD_Set_Cursor(1, 1);
    LCD_Write_String("hola");
}



 

anything