Autor Tema: Al programar un LCD se me queda bloqueada la ejecucion  (Leído 2013 veces)

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

Desconectado MichaelKnight

  • PIC16
  • ***
  • Mensajes: 154
Al programar un LCD se me queda bloqueada la ejecucion
« en: 22 de Abril de 2012, 19:09:00 »
Hola a todos. He adquirido un display 8x2 compatible con Hitachi para jugar un poco con el e ir adiestrandome en el uso de las pantallas, pero me estoy tropezando continuamente por el camino.

Leyendo el foro y la web uControl todo parecia facilisimo, pero debo de hacer algo sumamente mal porque no consigo atinar. He probado tanto la flex_lcd como la lcd incluida en ccs y sigo experimentando el mismo problema.

Esta es la flex_lcd que estoy usando:

Código: [Seleccionar]
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#define LCD_RS    PIN_A0
//#define LCD_RW    PIN_C1
#define LCD_E     PIN_A1

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW   1

//========================================

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));
 output_bit(LCD_DB7, !!(nibble & 8));

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);

 delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);

    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_LCD_RW
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
   address = lcd_line_two;
else
   address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;

    case '\n':
       lcd_gotoxy(1,2);
       break;

    case '\b':
       lcd_send_byte(0,0x10);
       break;

    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif

void lcd_setcursor_vb(short visible, short blink) {
  lcd_send_byte(0, 0xC|(visible<<1)|blink);

Y este es el codigo simple que he escrito para probar:

Código: [Seleccionar]
#include <16f628a.h> // Selecciona el PIC
#fuses INTRC_IO, NOMCLR, NOWDT, NOBROWNOUT
#use delay(clock=4000000) // Velocidad del reloj : 4 Mhz

#include <flex_lcd.c>

void main(){
   
   delay_ms(3000);
   output_high(PIN_A2);
   
   lcd_init();
   output_high(PIN_A3);
   
   lcd_putc("HOLA");
   output_high(PIN_A4);

}


He puesto unos led para que me informe de cada paso que avanza y he descubierto que, pese a compilar al 100% ok, el problema comienza en la inicializacion del lcd. He hecho diferentes pruebas siendo las mas interesantes en la que comento toda linea por debajo de "output_high(PIN_A2);" y el primer led se me enciende. En la siguiente descomento las dos proximas lineas de codigo y es cuando compila 100% pero no hace absolutamente nada de nada. Ni me enciende led alguno ni interactua con el display (esto ultimo aun no ha llegado a ocurrir en toda la tarde).

¿Alguna pista de donde puedo estar equivocandome?

Saludos y gracias por adelantado.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #1 en: 22 de Abril de 2012, 21:18:29 »
Estas conectando correctamente el LCD? Puede ser que se queda esperando el Busy del LCD
No contesto mensajes privados, las consultas en el foro

Desconectado MichaelKnight

  • PIC16
  • ***
  • Mensajes: 154
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #2 en: 22 de Abril de 2012, 21:52:03 »
lo he conectado y desconectado mil veces sin exito. Ya no se si dudar de la protoboard, del conexionado... Porque por tu respuesta entiendo que el codigo esta bien.

Aun asi hay algo que no debo de hacer bien porque he tratado de simularlo mediante un simulador que tambien incluye display y no solo no me muestra texto alguno en la simulaciom, sino que obsevo que entra en bucle infinito.

Otra cosa que tampoco funciono fue el poner la declaracion de los pines en el codigo del programa en lugar de modificar la libreria. Con esta operacion pasaba lo mismo; no encendia ni tan solo un led y la pantalla vacia.

Por la mañana tratare de  hacer nuevas pruebas con lo que dices, pero con tantas repeticiones de conexionado me extraña que siempre fallase el mismo cable.

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #3 en: 22 de Abril de 2012, 22:37:39 »
Porque no pones aqui el esquema de conexion de tu placa??
Es probable que podamos ayudar mas con esa informacion...
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado MichaelKnight

  • PIC16
  • ***
  • Mensajes: 154
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #4 en: 23 de Abril de 2012, 15:54:20 »
Buenas noticias. Por fin se ha conseguido visualizar texto en el lcd. El problema era una soberana estupidez, el potenciometro para regular el contraste estaba roto. En fin, estas cosas pasan y hasta que no le ocurre a uno parece que no. En realidad siempre se estuvo mostrando el texto, la unica pega era que el contraste estaba mal regulado y no se apreciaba nada dado que el display es negro con cristal polarizado y has de acertar con el punto adecuado de contraste porque te pasas o no llegas facilmente.

Mi codigo lo he retocado para que la declaracion de pines se quede fuera de la libreria que es como debe ser:

Código: [Seleccionar]
#include <16f628a.h> // Selecciona el PIC
#fuses INTRC, NOMCLR, NOWDT, NOBROWNOUT
#use delay(clock=4000000) // Velocidad del reloj : 4 Mhz

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#define LCD_RS    PIN_A0
#define LCD_E     PIN_A1

#include <flex_lcd.c>

void main(){
   
   delay_ms(3000);
   output_high(PIN_A2);
   
   lcd_init();
   output_high(PIN_A3);
   
   lcd_putc("HOLA\n12345678");
   output_high(PIN_A4);

}


De todos modos siguen sin encenderse los led. Es mas, ando desesperado porque algo tan simple no me lo hace. He quitado el LCD visto que ya funciona y he implementado algo tan simple como esto:

Código: [Seleccionar]
#include <16f628a.h> // Selecciona el PIC
#use delay(clock=4000000) // Velocidad del reloj : 4 Mhz

#fuses INTRC,NOMCLR, NOWDT, NOBROWNOUT

#define ENCIENDE1 output_high(PIN_A2);
#define ENCIENDE2 output_high(PIN_A3);
#define ENCIENDE3 output_high(PIN_A4);

void main(){
   
   delay_ms(3000);
   
   ENCIENDE1;
   ENCIENDE2;
   ENCIENDE3;

}

¿Estoy equivocandome en algo?

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #5 en: 23 de Abril de 2012, 17:18:04 »
Acuérdate que se debe colocar un bucle infinito, sino el microcontrolador se resetea al terminar las instrucciones.
No contesto mensajes privados, las consultas en el foro

Desconectado MichaelKnight

  • PIC16
  • ***
  • Mensajes: 154
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #6 en: 23 de Abril de 2012, 18:13:56 »
Acuérdate que se debe colocar un bucle infinito, sino el microcontrolador se resetea al terminar las instrucciones.

Madre mia, que fallo mas ridiculo. Efectivamente era eso. He procedido ahora a probar las salidas y me he encontrando con lo siguiente al aplicarle este codigo:

Código: [Seleccionar]
#include <16f628a.h> // Selecciona el PIC
#use delay(clock=4000000) // Velocidad del reloj : 4 Mhz

#fuses INTRC,NOMCLR, NOWDT, NOBROWNOUT



void main(){
   
   delay_ms(3000);
   
   while(1){
   
      output_high(PIN_A1);
      output_high(PIN_A2);
      output_high(PIN_A3);
      output_high(PIN_A4);
      output_high(PIN_A5);
      output_high(PIN_A6);
      output_high(PIN_A7);
     
      output_high(PIN_B1);
      output_high(PIN_B2);
      output_high(PIN_B3);
      output_high(PIN_B4);
      output_high(PIN_B5);
      output_high(PIN_B6);
      output_high(PIN_B7);
     
   }
}

Aclaro que he probado primero el puerto A y luego el B para no sobrecargar el PIC.

Como resultado se me han encendido todas menos 4 salidas:

- A0
- A4
- A5
- B0

La A5 es de solo entrada, asi que por tanto no hay problema. El resto en cambio son bidireccionales y no entiendo el motivo por el que no lucen los led.

PD: Siento que nos hayamos salido del proposito original del post.

 aunque en el A4 no me actua. Tengo que mirar

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #7 en: 23 de Abril de 2012, 18:17:49 »
A0 y B0 no lo prendes nunca xD A4 es colector abierto.
No contesto mensajes privados, las consultas en el foro

Desconectado MichaelKnight

  • PIC16
  • ***
  • Mensajes: 154
Re: Al programar un LCD se me queda bloqueada la ejecucion
« Respuesta #8 en: 23 de Abril de 2012, 18:32:50 »
A0 y B0 no lo prendes nunca xD A4 es colector abierto.

Estupendo, creo que se acaba de hacer evidente que estoy bajo medicacion por una contractura muscular y me deja KO, pero no sabia que a estos extremos pudiera afectarme.

Gracias y sobre todo perdon por las preguntas chorras propias de un mentecato que hice.

Por hoy no pienso tocar nada mas, es absurdo y no voy a atinar.