Autor Tema: LCD 16x2 se inicializa como quiere, a veces bien a veces mal  (Leído 7879 veces)

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

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« en: 08 de Mayo de 2014, 12:30:17 »
Hola, buen día,

tengo un 877a con un LCD de 16x2 con un controlador HD44780, a veces lo enciendo (de la fuente o del enchufe a 220 simulando un corte de corriente) y se inicializa bien, muestra lo que le escribo, pero otras veces lo enciendo y aparentemente se inicializa mal, no puedo dar con el problema, estoy pensando en poner pullups en los 4 puertos de datos,

cuando apago el display, queda unos segundos encendido como si tuviera un capacitor de 50 cm  :D



el proteus del 877a con el lcd y la fuente que tengo es este:



y el código compilado con XC8 es este:

Código: C#
  1. /*
  2.  * File:   main.c
  3.  */
  4.  
  5. //******************************************************************************
  6.  
  7. #include "main.h"
  8.  
  9. /******************************************************************************
  10.  ******************************************************************************
  11.  ******************************************************************************/
  12.  
  13. void pasaje_datos_lcd(void)
  14. {
  15.     LCD_E   = 1; // habilita la comunicacion para que procese el nibble
  16.     __delay_us( 10 ); // delay para garantizar el pasaje de datos al lcd
  17.     LCD_E   = 0; // deshabilita la comunicacion
  18. }
  19.  
  20. /******************************************************************************/
  21.  
  22. void enviaByteLCD( t_byte dato )
  23. {
  24.     // transmite el nibble alto al lcd
  25.     LCD_D7  = dato.b7;
  26.     LCD_D6  = dato.b6;
  27.     LCD_D5  = dato.b5;
  28.     LCD_D4  = dato.b4;
  29.  
  30.     pasaje_datos_lcd();
  31.  
  32.     // transmite el nibble bajo al lcd
  33.     LCD_D7  = dato.b3;
  34.     LCD_D6  = dato.b2;
  35.     LCD_D5  = dato.b1;
  36.     LCD_D4  = dato.b0;
  37.  
  38.     pasaje_datos_lcd();
  39.  
  40.     __delay_ms(5);
  41. }
  42.  
  43. /******************************************************************************/
  44.  
  45. // inicializacion del lcd con bus de 4 bits
  46. void inicializa_lcd(void)
  47. {
  48.     t_byte dato;
  49.     __delay_ms( 20 ); // espera a que el voltaje se estabilice
  50.  
  51.     LCD_RS  = 0; // aviso de envio de comando
  52.  
  53.     LCD_E   = 0; // deshabilita la comunicacion
  54.  
  55.     __delay_ms( 15 );
  56.  
  57.     //----------------------------------
  58.     dato.byte = 3;
  59.     for ( int i=0; i<3; i++ )
  60.         enviaByteLCD( dato );
  61.     dato.byte = 2;
  62.     enviaByteLCD( dato );
  63.     dato.byte = 2;
  64.     enviaByteLCD( dato );
  65.  
  66.     for ( int i=0; i<3; i++ )
  67.     {
  68.         dato.byte = 0x28;
  69.         enviaByteLCD( dato );
  70.         dato.byte = 0xC;
  71.         enviaByteLCD( dato );
  72.         dato.byte = 1;
  73.         enviaByteLCD( dato );
  74.         dato.byte = 6;
  75.         enviaByteLCD( dato );
  76.     }
  77. }
  78.  
  79. /******************************************************************************/
  80.  
  81. void enviaComandoLCD( t_byte comando )
  82. {
  83.     LCD_RS = 0; // aviso de envio de comando
  84.     enviaByteLCD( comando );
  85. }
  86.  
  87. /******************************************************************************/
  88.  
  89. void enviaDatoLCD( t_byte dato )
  90. {
  91.     LCD_RS = 1; // aviso de envio de datos
  92.     enviaByteLCD( dato );
  93. }
  94.  
  95. /******************************************************************************/
  96.  
  97. void enviaCadenaLCD(const unsigned char *car)
  98. {
  99.     while ( *car )
  100.     {
  101.         t_byte caracter;
  102.         caracter.byte = *car;
  103.  
  104.         enviaDatoLCD( caracter );
  105.  
  106.         car++;
  107.     }
  108. }
  109.  
  110. /******************************************************************************
  111.  ******************************************************************************
  112.  ******************************************************************************/
  113.  
  114. void activar_interrupciones_PORTB_TIMER(void)
  115. {
  116.     INTCONbits.RBIF = 1;
  117.     INTCONbits.INTF = 1;
  118.  
  119.     /**** INTERRUPCIONES ****/
  120.  
  121.     INTCONbits.PEIE  = 1; // Enables all unmasked peripheral interrupts
  122.     INTCONbits.RBIE  = 1; // Enables the RB port change interrupt
  123.  
  124.     // PORTB pull-ups are enabled by individual port latch values
  125.     OPTION_REGbits.nRBPU  = 1;
  126.     // Interrupt on rising (creciente) edge of RB0/INT pin
  127.     OPTION_REGbits.INTEDG = 1;
  128.  
  129.     INTCONbits.RBIF = 0;
  130.     INTCONbits.INTF = 0;
  131.  
  132.     INTCONbits.GIE   = 1; // Enables all unmasked interrupts
  133.  
  134.     //T1CONbits.TMR1ON  = 1; // Timer1 On bit
  135. }
  136.  
  137. /******************************************************************************/
  138.  
  139. void configurar_pic(void)
  140. {
  141.     /*****************************
  142.      ******** T I M E R 1 ********
  143.      *****************************/
  144.     // cronometro para el tiempo de las duchas
  145.     T1CONbits.TMR1CS  = 0; // Timer1 Clock Source - 0 Internal clock (FOSC/4)
  146.  
  147.     T1CONbits.T1CKPS1 = 1; // prescaler
  148.     T1CONbits.T1CKPS0 = 1; // 1:8
  149.  
  150.     TMR1H = VALOR_TMR1H; // 3036
  151.     TMR1L = VALOR_TMR1L; // 500 ms
  152.  
  153.     T1CONbits.TMR1ON  = 0; // Timer1 On bit
  154.  
  155.     PIE1bits.TMR1IE   = 1; // TMR1 Overflow Interrupt Enable bit
  156.  
  157.     /*********************
  158.      *** P U E R T O S ***
  159.      *********************/
  160.     /**** PORTD I/O ****/
  161.     TRISEbits.PSPMODE = 0; // PORTD functions in general purpose I/O mode
  162.  
  163.     /**** PORTE I/O ****/
  164.     TRISEbits.TRISE2  = 0; // Output
  165.     TRISEbits.TRISE1  = 0; // Output
  166.     TRISEbits.TRISE0  = 0; // Output
  167.  
  168.     /**** PORTA / PORTE I/O ****/
  169.     ADCON1 = 0b00000111; // RA5:RA0 y RE2:RE0 Digital
  170.  
  171.     TRISA = 0b00000000; // Salida
  172.     TRISC = 0b10000000; // Salida
  173.     TRISD = 0b00000000; // Salida
  174.     TRISE = 0b00000000; // Salida
  175.  
  176.     PORTA = 0b00000000;
  177.     PORTB = 0b00000000;
  178.     PORTC = 0b00000000;
  179.     PORTD = 0b00000000;
  180.     PORTE = 0b00000000;
  181.  
  182. }
  183.  
  184. /******************************************************************************
  185.  ******************************************************************************
  186.  ******************************************************************************/
  187.  
  188. int main(void)
  189. {
  190.     t_byte caracter;
  191.  
  192.     configurar_pic();
  193.  
  194.     activar_interrupciones_PORTB_TIMER();
  195.  
  196.     inicializa_lcd();
  197.     __delay_ms( 20 );
  198.  
  199.     caracter.byte = _LCD_CMND_LIMPIAR_;
  200.     enviaComandoLCD( caracter );
  201.  
  202.     caracter.byte = _LCD_L1_C_01_;
  203.     enviaComandoLCD( caracter );
  204.  
  205.     while ( 1 )
  206.     {
  207.         caracter.byte = _LCD_L1_C_01_;
  208.         enviaComandoLCD( caracter );
  209.         enviaCadenaLCD("Prueba de LCD");
  210.  
  211.         __delay_ms( 1000 );
  212.  
  213.         // mueve el cursor al primer caracter de la segunda linea
  214.         caracter.byte = _LCD_L2_C_01_; //0b11000000;
  215.         enviaComandoLCD( caracter );
  216.         enviaCadenaLCD("Texto de prueba");
  217.  
  218.         __delay_ms( 1000 );
  219.  
  220.         caracter.byte = _LCD_CMND_LIMPIAR_; // limpia la pantalla
  221.         enviaComandoLCD( caracter );
  222.  
  223.         __delay_ms( 200 );
  224.  
  225.         //--------------------------------------------------------------
  226.  
  227.         // mueve el cursor al primer caracter de la segunda linea
  228.         caracter.byte = _LCD_L1_C_01_; //0b11000000;
  229.         enviaComandoLCD( caracter );
  230.         enviaCadenaLCD("DSD");
  231.  
  232.         __delay_ms( 100 );
  233.  
  234.         // mueve el cursor al 12º caracter de la primer linea
  235.         caracter.byte = _LCD_L1_C_12_; //0b11000000;
  236.         enviaComandoLCD( caracter );
  237.         enviaCadenaLCD("CD-9");
  238.  
  239.         // mueve el cursor al primer caracter de la segunda linea
  240.         caracter.byte = _LCD_L2_C_01_; //0b11000000;
  241.         enviaComandoLCD( caracter );
  242.         enviaCadenaLCD("www.dysd.com.ar");
  243.  
  244.         __delay_ms( 1000 );
  245.  
  246.         caracter.byte = _LCD_CMND_LIMPIAR_; // limpia la pantalla
  247.         enviaComandoLCD( caracter );
  248.  
  249.         __delay_ms( 200 );
  250.     }
  251. }

Código: C#
  1. /*
  2.  * File:   definiciones.h
  3.  */
  4.  
  5. #ifndef MAIN_H
  6. #define MAIN_H
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <xc.h>
  11. #include <pic16f88.h>
  12. #include <pic16f877a.h>
  13. #include <stdbool.h>
  14. #include "variables.h"
  15.  
  16. //#########################
  17. // D E F I N I C I O N E S
  18. //#########################
  19.  
  20. #define _XTAL_FREQ 4000000 // Velocidad clock en Hz
  21.  
  22. #pragma config FOSC  = XT       // Oscillator Selection bits
  23.                                 // (XT oscillator)
  24.  
  25. #pragma config WDTE  = OFF      // Watchdog Timer Enable bit
  26.                                 // (WDT disabled)
  27.  
  28. #pragma config PWRTE = OFF      // Power-up Timer Enable bit
  29.                                 // (PWRT disabled)
  30.  
  31. #pragma config BOREN = ON       // Brown-out Reset Enable bit
  32.                                 // (BOR enabled)
  33.  
  34. #pragma config LVP   = OFF      // Low-Voltage (Single-Supply)
  35.                                 // In-Circuit Serial Programming
  36.                                 // Enable bit
  37.                                 // (RB3 is digital I/O, HV on MCLR
  38.                                 // must be usedfor programming)
  39.  
  40. #pragma config CPD   = OFF      // Data EEPROM Memory Code
  41.                                 // Protection bit
  42.                                 // (Data EEPROM code protection off)
  43.  
  44. #pragma config WRT   = OFF      // Flash Program Memory Write
  45.                                 // Enable bits
  46.                                 // (Write protection off;
  47.                                 // all program memory may be written
  48.                                 // to by EECON control)
  49.  
  50. #pragma config CP    = OFF      // Flash Program Memory
  51.                                 // Code Protection bit
  52.                                 // (Code protection off)
  53.  
  54. /**** Timer1 - para 10 seg ***********************/
  55. /**** Reloj a 4 MHz ****/
  56. #define VALOR_TMR1H                     0b01011101 // 23869
  57. #define VALOR_TMR1L                     0b00111101 // 500 ms
  58. #define NRO_INT_TIMER1_X_SEG            2 // 500 ms * 2 = 1 seg
  59.  
  60.  
  61. /**** LCD ****************************************/
  62. // 0 = comandos / 1 = datos
  63. #define LCD_RS              PORTCbits.RC0
  64. #define LCD_E               PORTCbits.RC1 // 0 = deshabilitar / 1 = habilitar
  65. //#define LCD_RW              PORTCbits.RC6 // 1 = leer / 0 = escribir
  66. #define LCD_BUSY            PORTCbits.RC7
  67.  
  68. #define LCD_D4              PORTCbits.RC2
  69. #define LCD_D5              PORTCbits.RC3
  70. #define LCD_D6              PORTCbits.RC4
  71. #define LCD_D7              PORTCbits.RC5
  72.  
  73. //#################### MACROS ####################
  74. /*** test to see if bit number, bit, in the integer, var, is set */
  75. #define testbit(var, bit)     ((var) & ((char)1 <<(bit)))
  76. #define bitset(var, bitno)    ((var) |= 1UL << (bitno))
  77. #define bitclr(var, bitno)    ((var) &= ~(1UL << (bitno)))
  78.  
  79. #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
  80. #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
  81.  
  82.  
  83.  
  84. #endif  /* MAIN_H */

Código: C#
  1. /*
  2.  * File:   variables.h
  3.  */
  4.  
  5. #ifndef VARIABLES_H
  6. #define VARIABLES_H
  7.  
  8. #ifdef  __cplusplus
  9. extern "C" {
  10. #endif
  11.  
  12. //------------------------------------------------------------------------------
  13.  
  14. #ifndef TYPEDEF_UNION_T_BYTE
  15. #define TYPEDEF_UNION_T_BYTE
  16.     typedef union
  17.     {
  18.         unsigned char byte;
  19.  
  20.         struct
  21.         {   //         MSB                                       LSB
  22.             //unsigned b7:1, b6:1, b5:1, b4:1, b3:1, b2:1, b1:1, b0:1;
  23.             unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
  24.         };
  25.     } t_byte;
  26. #endif /* TYPEDEF_UNION_T_BYTE */
  27.  
  28. //------------------------------------------------------------------------------
  29.  
  30.  
  31. #ifdef  __cplusplus
  32. }
  33. #endif
  34.  
  35. #endif  /* VARIABLES_H */

Muchas gracias por cualquier ayuda que me pueda sacar de esto
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #1 en: 08 de Mayo de 2014, 16:43:22 »
Hola compañero
tu error suena a que le falta un retardo una vez llamas a la funcion de inicializado del lcd,
si lo inicializas y le mandas datos te hara cosas raras, debes de dejarle el tiempo suficiente
para que termine de realizar las operaciones.

Otra cosa..
 en tu codigo veo que le cargas dos pic seria bueno que solo le cargaras uno me refiero al fichero definiciones.h
el pic que no uses lo comentas con //.

un saludo.

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #2 en: 08 de Mayo de 2014, 16:50:09 »
hola pajaro, buenas tardes,

Hola compañero
tu error suena a que le falta un retardo una vez llamas a la funcion de inicializado del lcd,
si lo inicializas y le mandas datos te hara cosas raras, debes de dejarle el tiempo suficiente
para que termine de realizar las operaciones.

tiene 35 ms de retardo, lo he subido a 100 y los errores son más frecuentes, eso me resulta extraño,

saludos y gracias por responder,
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #3 en: 08 de Mayo de 2014, 23:47:58 »
  Lucas, yo creo que tienes mal la rutina de inicialización. Trataré de explicarme porque de mi creencia.

  Dentro de tu rutina, llamas a tres veces a enviaByte con el valor 3. Luego tres veces con el valor 2. Luego nuevamente tres veces pero ahora con los valores 0x28, 0xC, 1 y finalmente el 6.

  Obviamente tu rutina envíaByte, separa el dato en dos nibbles y los envía -ya que estás utilizando protocolo de 4 bits-, podríamos decir que eso está perfecto, si no fuera porque en los primeros datos de inicialización (cuando debes enviar el valor 3 y el valor 2) el LCD sólo necesita recibir 4 bits y no los 8 bits que genera tu rutina enviaByte. O sea, en tu caso, el LCD está recibiendo los valores 3 y 0 cada vez que quieres enviar el 3.

  Tal vez me cueste hacerme entender.... a ver si con una tabla se comprende mejor


Código: C
  1. //Dato a enviar (solo 4 bits)                      Datos que tu envias (siempre son 8 bits)
  2.    0x3                                              0x30
  3.    0x3                                              0x30
  4.    0x3                                              0x30
  5.    0x2                                              0x20
  6.    0x2                                              0x20
  7.  
  8. // apartir de aqui si hay que enviar 8 bits,
  9. // pero solo se envian una vez cada byte y no tres veces como lo haces tu
  10.    0x28                                             0x28
  11.    0x0C                                             0x0C
  12.    0x01                                             0x01
  13.    0x06                                             0x06
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #4 en: 09 de Mayo de 2014, 14:53:02 »
buenas tardes pajaro y AngelGris,

en la primer prueba, cambié la inicialización sin repetir, pero siguio el problema

Código: C#
  1. void inicializa_lcd(void)
  2. {
  3.     t_byte dato;
  4.     __delay_ms( 20 ); // espera a que el voltaje se estabilice
  5.  
  6.     LCD_RS  = 0; // aviso de envio de comando
  7.  
  8.     LCD_E   = 0; // deshabilita la comunicacion
  9.  
  10.     LCD_D7 = 0;
  11.     LCD_D6 = 0;
  12.     LCD_D5 = 1; // modo seteo
  13.     LCD_D4 = 1; // bus de 4 bits
  14.  
  15.     LCD_E  = 1; // habilita la comunicacion
  16.  
  17.     __delay_ms( 15 );
  18.  
  19.     //----------------------------------
  20.     dato.byte = 3;
  21.     enviaByteLCD( dato );
  22.  
  23.     dato.byte = 2;
  24.     enviaByteLCD( dato );
  25.  
  26.     dato.byte = 0x28;
  27.     enviaByteLCD( dato );
  28.  
  29.     dato.byte = 0xC;
  30.     enviaByteLCD( dato );
  31.  
  32.     dato.byte = 1;
  33.     enviaByteLCD( dato );
  34.  
  35.     dato.byte = 6;
  36.     enviaByteLCD( dato );
  37. }

en las siguientes pruebas, cambié la inicialización respetando los pasos (pdf pag 46) y los tiempos (pdf pag 24) de la hoja de datos del hd44780 (http://www.dysd.com.ar/electronica/HD44780.pdf) y empeoró, ahora la mayor parte de los encendidos no muestra nada y a veces muestra caracteres incomprensibles,

la inicialización quedó así

Código: C#
  1. void inicializa_lcd(void)
  2. {
  3.     t_byte dato;
  4.  
  5.     __delay_ms( 300 ); // espera a que el voltaje se estabilice
  6.  
  7.     LCD_E  = 0; // deshabilita la comunicacion ·································
  8.  
  9.     LCD_RS = 0; // aviso de envio de comando
  10.     LCD_RW = 0; // 1 = leer / 0 = escribir
  11.     LCD_D7 = 0;
  12.     LCD_D6 = 0;
  13.     LCD_D5 = 1;
  14.     LCD_D4 = 1;
  15.  
  16. //    LCD_E  = 1; // habilita la comunicacion ····································
  17.  
  18.     __delay_ms( 10 );
  19.  
  20. //    LCD_E  = 0; // deshabilita la comunicacion ·································
  21.  
  22.     LCD_RS = 0; // aviso de envio de comando
  23.     LCD_RW = 0; // 1 = leer / 0 = escribir
  24.     LCD_D7 = 0;
  25.     LCD_D6 = 0;
  26.     LCD_D5 = 1;
  27.     LCD_D4 = 1;
  28.  
  29. //    LCD_E  = 1; // habilita la comunicacion ····································
  30.  
  31.     __delay_us( 250 );
  32.  
  33. //    LCD_E  = 0; // deshabilita la comunicacion ·································
  34.  
  35.     LCD_RS = 0; // aviso de envio de comando
  36.     LCD_RW = 0; // 1 = leer / 0 = escribir
  37.     LCD_D7 = 0;
  38.     LCD_D6 = 0;
  39.     LCD_D5 = 1; // COMANDO: bus de datos de 4 bits
  40.     LCD_D4 = 0;
  41.  
  42. //    LCD_E  = 1; // habilita la comunicacion ····································
  43.  
  44.     __delay_us( 100 );
  45.  
  46.     dato.byte = 0x2c; // 2 lineas - fuente 5x10
  47.     enviaByteLCD( dato );
  48.  
  49.     __delay_us( 100 );
  50.  
  51.     dato.byte = 0x8; // apaga el display
  52.     enviaByteLCD( dato );
  53.  
  54.     __delay_us( 100 );
  55.  
  56.     dato.byte = 0x1; // limpia el display
  57.     enviaByteLCD( dato );
  58.  
  59.     __delay_ms( 1 );
  60.  
  61.     dato.byte = 0x4; // modo de entrada
  62.     enviaByteLCD( dato );
  63.  
  64.     __delay_us( 100 );
  65. }

el LCD_E está comentado porque lo probé de las dos maneras,

en el main lo llamo así

Código: C#
  1. inicializa_lcd();
  2.    
  3. __delay_ms( 500 );

obviamente todo esto en el proteus funciona,

no se que más probar,

muchas gracias por la ayuda

Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #5 en: 09 de Mayo de 2014, 17:40:59 »
  El último ejemplo que colocaste está mal, ya que sólo envías dos veces el valor 3 cuando deberías enviarlo tres veces. Además de ello no estás habilitando el LCD. 

  La idea sería...

  envías 3
  activas pin EN
  esperas 1us
  desactivas pin EN

  Tu código tiene líneas comentadas que justamente habilitan y deshabilitan el pin EN.

  Aquí tienes una librería que hice, si es que no la quieres utilizar al menos te puede servir como guía para la rutina de inicialización.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #6 en: 09 de Mayo de 2014, 19:10:00 »
hola AngelGris,

  Aquí tienes una librería que hice, si es que no la quieres utilizar al menos te puede servir como guía para la rutina de inicialización.

¿faltó la librería?

muchas gracias,

saludos
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #7 en: 09 de Mayo de 2014, 19:14:59 »
hola AngelGris,

  Aquí tienes una librería que hice, si es que no la quieres utilizar al menos te puede servir como guía para la rutina de inicialización.

¿faltó la librería?

muchas gracias,

saludos

   :oops: se me olvido el link.... http://www.todopic.com.ar/foros/index.php?topic=40649.180

  En los últimos dos mensajes tienes la librería y un ejemplo de utilización. Incluso esto creando el caracter "ñ"
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #8 en: 09 de Mayo de 2014, 20:07:44 »
hola AngelGris,

lamentablemente la librería no funcionón con mi lcd  :?  :5]

voy a tener que ajustar los delay con pruebas

gracias por las respuestas,

saludos
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #9 en: 09 de Mayo de 2014, 20:19:55 »
  Si es que usaste la librería que compartí, ¿usaste el ejemplo que coloqué o trataste de adaptar tu programa?
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #10 en: 09 de Mayo de 2014, 20:29:22 »
AngelGris, gracias por responder,

usé el mismo ejemplo y comenté el envío de la ñ,

volviendo al inicio, esto en el proteus funciona perfecto, y como es la costumbre del display, en el protoboard funciona cuando no está deprimido, que cada vez se deprime menos,

Código: C#
  1. void inicializa_lcd(void)
  2. {
  3.     t_byte dato;
  4.     __delay_ms( 20 ); // espera a que el voltaje se estabilice
  5.  
  6.     LCD_RS  = 0; // aviso de envio de comando
  7.  
  8.     for ( char i=0; i<3; i++ )
  9.     {
  10.         LCD_E  = 0; // deshabilita la comunicacion
  11.         LCD_D7 = 0;
  12.         LCD_D6 = 0;
  13.         LCD_D5 = 1; // modo seteo
  14.         LCD_D4 = 1; // bus de 4 bits
  15.         LCD_E  = 1; // habilita la comunicacion
  16.  
  17.         __delay_ms( 15 );
  18.     }
  19.  
  20.     //----------------------------------
  21.     dato.byte = 3;
  22.     enviaByteLCD( dato );
  23.  
  24.     dato.byte = 2;
  25.     enviaByteLCD( dato );
  26.  
  27.     dato.byte = 0x28;
  28.     enviaByteLCD( dato );
  29.  
  30.     dato.byte = 0xC;
  31.     enviaByteLCD( dato );
  32.  
  33.     dato.byte = 1;
  34.     enviaByteLCD( dato );
  35.  
  36.     dato.byte = 6;
  37.     enviaByteLCD( dato );
  38. }

gracias por tu atención,

saludos,
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #11 en: 10 de Mayo de 2014, 09:34:10 »
AngelGris, gracias por responder,

usé el mismo ejemplo y comenté el envío de la ñ,

volviendo al inicio, esto en el proteus funciona perfecto, y como es la costumbre del display, en el protoboard funciona cuando no está deprimido, que cada vez se deprime menos,

Código: C#
  1. void inicializa_lcd(void)
  2. {
  3.     t_byte dato;
  4.     __delay_ms( 20 ); // espera a que el voltaje se estabilice
  5.  
  6.     LCD_RS  = 0; // aviso de envio de comando
  7.  
  8.     for ( char i=0; i<3; i++ )
  9.     {
  10.         LCD_E  = 0; // deshabilita la comunicacion
  11.         LCD_D7 = 0;
  12.         LCD_D6 = 0;
  13.         LCD_D5 = 1; // modo seteo
  14.         LCD_D4 = 1; // bus de 4 bits
  15.         LCD_E  = 1; // habilita la comunicacion
  16.  
  17.         __delay_ms( 15 );
  18.     }
  19.  
  20.     //----------------------------------
  21.     dato.byte = 3;
  22.     enviaByteLCD( dato );
  23.  
  24.     dato.byte = 2;
  25.     enviaByteLCD( dato );
  26.  
  27.     dato.byte = 0x28;
  28.     enviaByteLCD( dato );
  29.  
  30.     dato.byte = 0xC;
  31.     enviaByteLCD( dato );
  32.  
  33.     dato.byte = 1;
  34.     enviaByteLCD( dato );
  35.  
  36.     dato.byte = 6;
  37.     enviaByteLCD( dato );
  38. }

gracias por tu atención,

saludos,

  Tal vez sean falsos contactos entre el display y el protoboard
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado HJG

  • PIC12
  • **
  • Mensajes: 77
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #12 en: 10 de Mayo de 2014, 10:23:49 »
cuando apago el display, queda unos segundos encendido como si tuviera un capacitor de 50 cm
En el circuito veo que tienes un capacitor de 1uF en el MCLR, es un valor muy grande, coloca uno de 100n como máximo, incluso prueba sin poner nada.

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #13 en: 10 de Mayo de 2014, 14:30:12 »
cuando apago el display, queda unos segundos encendido como si tuviera un capacitor de 50 cm
En el circuito veo que tienes un capacitor de 1uF en el MCLR, es un valor muy grande, coloca uno de 100n como máximo, incluso prueba sin poner nada.

ahora no está, desapareció :D le dejé nada más que la resistencia y el capacitor se lo puse entre masa y 5v para descargar cualquier corriente al apagarlo

lo voy a pasar a un cobre porque yo también sospecho de los cablecitos de la proto,

también pensé en algún ruido que pueda meter la fuente,

este tema me tiene desconcertado, hace varias semanas que estoy con esto, probé cerca de 10 ejemplos de código para implementarlo y terminé con el primer código que puse que es un rejuntado a prueba y error de todo lo que probé,

el primer código que implementé lo escribí según este data HD44780 siguiendo los pasos de inicialización de la pag 46 con los tiempos de la tabla de la pag 24 pero ni siquiera encendía

todos los ejemplos que probé como te decía en el proteus andan pero en la práctica no, incluso hasta probé con un display que tiene el contraste a 5v en lugar de a masa, por eso reemplacé la resistencia del contraste por una variable, te muestro como quedó

esta es la resist variable


y esta es la proto completa


también probé de poner los 4 pines D0~D4 a masa pero así no muestra nada, como si no se inicializara,

otra cosa que no pude solucionar es la lectura del busy en d7, pero no tiene mucha importancia, primero tengo que lograr que ande el lcd,
lo que hice es que cada vez que mando un comando, pongo enable a 1, trisc rc5 como entrada y un while(rc5) ; para ver cuando termina de procesar pero el proteus me dice que estoy mandando datos cuando el lcd está ocupado, y en la práctica no funciona,

Código: C#
  1. LCD_E = 1;
  2. TRISCbits.TRISC5 = 1;
  3. while(PORTCbits.RC5) ;
  4. TRISCbits.TRISC5 = 0;
  5. LCD_E = 0;

saludos,
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/

Desconectado LucasBols

  • PIC16
  • ***
  • Mensajes: 129
    • Desarrollos y Servicios Digitales
Re: LCD 16x2 se inicializa como quiere, a veces bien a veces mal
« Respuesta #14 en: 13 de Mayo de 2014, 14:41:51 »
hola, buenas tardes,

primero gracias a todos por la ayuda,

logré que los lcd se inicialicen correctamente,

como era obvio que el problema estaba en la inicialización, noté que si ponía el contraste al máximo, cuando lo encendía los cuadraditos negros de la primer fila (se inicializan por hard como 1 línea) tardaban más de 2 segundos en ponerse negros, entonces supuse que debería darle un tiempo similar para que el voltaje llegue a los 4.5v requeridos,

después de varias pruebas llegué a los 2500 mseg y encendía mucho mejor, pero si lo apagaba y lo volvía a encender sin esperar que se descargue la fuente y el cristal, volvían los errores, entonces le puse un transistor a la alimentación del lcd (entre los 5v de la fuente y la alimentación del lcd) para que corte a los 4.5v y no le siga llegando alimentación de la fuente mientras esta se descarga, con esto desaparecieron todos los errores,

hice algunos otros ajustes, como reducir el tiempo de escritura de comandos y caracteres, les dejo el .c y el .h para bus de 4 bits y en este enlace les dejo el pdf del lcd, un CCM-1620CSL,

lcd16x2.h
Código: C#
  1. /*
  2.  * File:   lcd16x2.h
  3.  * Author: Darío Nasta
  4.  *
  5.  * Created on 13 de mayo de 2014, 13:43
  6.  */
  7.  
  8. #ifndef LCD16X2_H
  9. #define LCD16X2_H
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <xc.h>
  14. #include <pic16f877a.h>
  15. #include <stdbool.h>
  16.  
  17. //******************************************************************************
  18.  
  19. #define LCD_RS              PORTCbits.RC0 // 0 = comandos / 1 = datos
  20. #define LCD_E               PORTCbits.RC1 // 0 = deshabilitar / 1 = habilitar
  21.  
  22. #define LCD_D4              PORTCbits.RC2
  23. #define LCD_D5              PORTCbits.RC3
  24. #define LCD_D6              PORTCbits.RC4
  25. #define LCD_D7              PORTCbits.RC5
  26.  
  27. #define LCD_RW              PORTCbits.RC6 // 1 = leer / 0 = escribir
  28.  
  29. //******************************************************************************
  30.  
  31. #define _LCD_CMND_LIMPIAR_  0b00000001
  32.  
  33. //******************************************************************************
  34.  
  35. /* posiciones del display */
  36. /*
  37.  *  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
  38.  * 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  1º linea
  39.  * 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F  2º linea
  40.  *
  41.  * En HEX con 0b1 como comando -------------------
  42.  *  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
  43.  * 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
  44.  * C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
  45.  */
  46.  
  47. #define _LCD_L1_C_01_     0b10000000
  48. #define _LCD_L1_C_02_     0b10000001
  49. #define _LCD_L1_C_03_     0b10000010
  50. #define _LCD_L1_C_04_     0b10000011
  51. #define _LCD_L1_C_05_     0b10000100
  52. #define _LCD_L1_C_06_     0b10000101
  53. #define _LCD_L1_C_07_     0b10000110
  54. #define _LCD_L1_C_08_     0b10000111
  55. #define _LCD_L1_C_09_     0b10001000
  56. #define _LCD_L1_C_10_     0b10001001
  57. #define _LCD_L1_C_11_     0b10001010
  58. #define _LCD_L1_C_12_     0b10001011
  59. #define _LCD_L1_C_13_     0b10001100
  60. #define _LCD_L1_C_14_     0b10001101
  61. #define _LCD_L1_C_15_     0b10001110
  62. #define _LCD_L1_C_16_     0b10001111
  63.  
  64. #define _LCD_L2_C_01_     0b11000000
  65. #define _LCD_L2_C_02_     0b11000001
  66. #define _LCD_L2_C_03_     0b11000010
  67. #define _LCD_L2_C_04_     0b11000011
  68. #define _LCD_L2_C_05_     0b11000100
  69. #define _LCD_L2_C_06_     0b11000101
  70. #define _LCD_L2_C_07_     0b11000110
  71. #define _LCD_L2_C_08_     0b11000111
  72. #define _LCD_L2_C_09_     0b11001000
  73. #define _LCD_L2_C_10_     0b11001001
  74. #define _LCD_L2_C_11_     0b11001010
  75. #define _LCD_L2_C_12_     0b11001011
  76. #define _LCD_L2_C_13_     0b11001100
  77. #define _LCD_L2_C_14_     0b11001101
  78. #define _LCD_L2_C_15_     0b11001110
  79. #define _LCD_L2_C_16_     0b11001111
  80.  
  81. //******************************************************************************
  82.  
  83. #ifndef TYPEDEF_UNION_T_BYTE
  84. #define TYPEDEF_UNION_T_BYTE
  85.     typedef union
  86.     {
  87.         unsigned char byte;
  88.  
  89.         struct
  90.         {   //         MSB                                       LSB
  91.             //unsigned b7:1, b6:1, b5:1, b4:1, b3:1, b2:1, b1:1, b0:1;
  92.             unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
  93.         };
  94.     } t_byte;
  95. #endif /* TYPEDEF_UNION_T_BYTE */
  96.  
  97. //******************************************************************************
  98.  
  99. #ifndef _XTAL_FREQ
  100.     #define _XTAL_FREQ 4000000 // Velocidad clock en Hz
  101. #endif
  102.  
  103. #ifndef __DELAYS__
  104. #define __DELAYS__
  105.     #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
  106.     #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
  107. #endif
  108.  
  109. //******************************************************************************
  110.  
  111. void inicializaLCD(void);
  112. void escribeLineaLCD( const unsigned char *cadena, unsigned int num );
  113. void enviaComandoLCD( t_byte comando );
  114. void enviaDatoLCD( t_byte dato );
  115. void enviaByteLCD( t_byte dato );
  116.  
  117. //******************************************************************************
  118.  
  119. #endif  /* LCD16X2_H */

lcd16x2.c
Código: C#
  1. #include "lcd16x2.h"
  2.  
  3. /******************************************************************************/
  4.  
  5. // inicializacion del lcd con bus de 4 bits
  6. void inicializaLCD(void)
  7. {
  8.     t_byte dato;
  9.     __delay_ms( 2500 ); // espera a que el voltaje se estabilice
  10.  
  11.     LCD_RS  = 0; // aviso de envio de comando
  12.  
  13.     LCD_E   = 0; // deshabilita la comunicacion
  14.  
  15.     LCD_D7 = 0;
  16.     LCD_D6 = 0;
  17.     LCD_D5 = 1; // modo seteo
  18.     LCD_D4 = 1; // bus de 4 bits
  19.  
  20.     __delay_ms( 15 );
  21.  
  22.     LCD_E  = 1; // habilita la comunicacion
  23.  
  24.     __delay_ms( 15 );
  25.  
  26.     LCD_E   = 0; // deshabilita la comunicacion
  27.  
  28.     __delay_ms( 15 );
  29.  
  30.     //----------------------------------
  31.     dato.byte = 3;
  32.     enviaByteLCD( dato );
  33.  
  34.     dato.byte = 2;
  35.     enviaByteLCD( dato );
  36.  
  37.     dato.byte = 0x28;
  38.     enviaByteLCD( dato );
  39.  
  40.     dato.byte = 0xC;
  41.     enviaByteLCD( dato );
  42.  
  43.     dato.byte = 1;
  44.     enviaByteLCD( dato );
  45.  
  46.     dato.byte = 6;
  47.     enviaByteLCD( dato );
  48.  
  49.     __delay_ms( 500 );
  50.  
  51.     dato.byte = _LCD_CMND_LIMPIAR_;
  52.     enviaComandoLCD( dato );
  53. }
  54.  
  55. /******************************************************************************/
  56.  
  57. void escribeLineaLCD( const unsigned char *cadena, unsigned int num )
  58. {
  59.     t_byte caracter;
  60.  
  61.     while ( *cadena )
  62.     {
  63.         if ( *cadena == '%' )
  64.         {
  65.             char uni, dec, cen;
  66.  
  67.             cen = (num/100)%10; // centenas
  68.             dec = (num/10)%10; // decenas
  69.             uni = num%10; // unidades
  70.  
  71.             if ( cen )
  72.             {
  73.                 caracter.byte = cen+48;
  74.                 enviaDatoLCD( caracter );
  75.                 caracter.byte = dec+48;
  76.                 enviaDatoLCD( caracter );
  77.             }
  78.             else if ( dec )
  79.             {
  80.                 caracter.byte = dec+48;
  81.                 enviaDatoLCD( caracter );
  82.             }
  83.  
  84.             caracter.byte = uni+48;
  85.             enviaDatoLCD( caracter );
  86.  
  87.         }
  88.         else
  89.         {
  90.             caracter.byte = *cadena;
  91.             enviaDatoLCD( caracter );
  92.         }
  93.  
  94.         *cadena++;
  95.     }
  96. }
  97.  
  98. /******************************************************************************/
  99.  
  100. void enviaComandoLCD( t_byte comando )
  101. {
  102.     LCD_RS = 0; // aviso de envio de comando
  103.     enviaByteLCD( comando );
  104. }
  105.  
  106. /******************************************************************************/
  107.  
  108. void enviaDatoLCD( t_byte dato )
  109. {
  110.     LCD_RS = 1; // aviso de envio de datos
  111.     enviaByteLCD( dato );
  112. }
  113.  
  114. /******************************************************************************/
  115.  
  116. void pasaje_datos_lcd(void)
  117. {
  118.     LCD_E   = 1; // habilita la comunicacion para que procese el nibble
  119.     __delay_us( 10 ); // delay para garantizar el pasaje de datos al lcd
  120.     LCD_E   = 0; // deshabilita la comunicacion
  121. }
  122.  
  123. /******************************************************************************/
  124.  
  125. void enviaByteLCD( t_byte dato )
  126. {
  127.     // transmite el nibble alto al lcd
  128.     LCD_D7  = dato.b7;
  129.     LCD_D6  = dato.b6;
  130.     LCD_D5  = dato.b5;
  131.     LCD_D4  = dato.b4;
  132.  
  133.     pasaje_datos_lcd();
  134.  
  135.     // transmite el nibble bajo al lcd
  136.     LCD_D7  = dato.b3;
  137.     LCD_D6  = dato.b2;
  138.     LCD_D5  = dato.b1;
  139.     LCD_D4  = dato.b0;
  140.  
  141.     pasaje_datos_lcd();
  142.  
  143.     __delay_ms(1);
  144. }
  145.  
  146. /******************************************************************************/

ahora estoy probando con un truly mcc162-2a1-e que tiene el contraste al reves, pero no me preocupa porque son escasos, el más común en el mercado es el otro,

muchas gracias a todos,

saludos,
Un experto es alguien que te explica algo sencillo de forma confusa de tal manera que te hace pensar que la confusión sea culpa tuya.

DSD http://www.dysd.com.ar/