Autor Tema: Flex_lcd configurable RW  (Leído 3198 veces)

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

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Flex_lcd configurable RW
« en: 17 de Enero de 2010, 18:53:49 »
Hola como todos sabemos existe la muy buena librería flex_lcd que nos es muy útil para tener nuestro LCD con cualquier pin del micro funcionando a 4bits.

Ahora muchas veces he visto que en la librería existe el pin RW y cunado no se lo usa hay que comentar las líneas en esta librería, lo cual no me parece tan correcto.

Quisiera agregarle unas líneas de #ifdef u otro para hacer ello, habilitar el uso de ese pin y definir el mismo como los otros, pero no he podido lograrlo, como creen que debería ir ifdef?

tengo esto:
Código: C++
  1. #ifndef LCD_DB4
  2. #define LCD_DB4 PIN_C3
  3. #define LCD_DB5 PIN_C2
  4. #define LCD_DB6 PIN_C1
  5. #define LCD_DB7 PIN_C0
  6.  
  7. #define LCD_RS PIN_C5
  8. //#define LCD_RW PIN_C6
  9. #define LCD_E  PIN_C4
  10.  
  11. // If you only want a 6-pin interface to your LCD, then
  12. // connect the R/W pin on the LCD to ground, and comment
  13. // out the following line.
  14.  
  15. /*#ifndef USE_LCD_RW
  16. #define USE_LCD_RW FALSE
  17. #endif*/
  18. #endif

y más abajo esta función que hace uso de RW:
Código: C++
  1. #ifdef USE_LCD_RW
  2. int8 lcd_read_nibble(void)
  3. {
  4.   int8 retval;
  5.   // Create bit variables so that we can easily set
  6.   // individual bits in the retval variable.
  7.   #bit retval_0 = retval.0
  8.   #bit retval_1 = retval.1
  9.   #bit retval_2 = retval.2
  10.   #bit retval_3 = retval.3
  11.  
  12.   retval = 0;
  13.  
  14.   output_high(LCD_E);
  15.   delay_cycles(1);
  16.  
  17.   retval_0 = input(LCD_DB4);
  18.   retval_1 = input(LCD_DB5);
  19.   retval_2 = input(LCD_DB6);
  20.   retval_3 = input(LCD_DB7);
  21.  
  22.   output_low(LCD_E);
  23.  
  24.   return(retval);
  25. }
  26. #endif

Espero sus comentarios, muchas gracias saludos.
.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Flex_lcd configurable RW
« Respuesta #1 en: 17 de Enero de 2010, 20:52:58 »
Yo lo unico que cambiaria seria los:

Código: C
  1. #ifdef USE_LCD_RW
De las funciones y lo reemplazaria por:
Código: C
  1. #ifdef LCD_RW
Entonces si no esta definido el pin LCD_RW configura para no utilizar la lectura del LCD. Entonces con solo comentar #define LCD_RW PIN_C6 ya estaria solucionado el problema.

Por ejemplo una funcion quedaria así:

Código: C
  1. void lcd_send_byte(int8 address, int8 n){
  2.  
  3.   output_low(LCD_RS);
  4.  
  5. #ifdef LCD_RW
  6. while(bit_test(lcd_read_byte(),7)) ;
  7. #else
  8. delay_us(60);
  9. #endif
  10.  
  11.   if(address)
  12. ...

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Flex_lcd configurable RW
« Respuesta #2 en: 17 de Enero de 2010, 21:18:07 »
ok, gracias suky, he puesto:

Código: C++
  1. #ifdef LCD_RW
  2. #endif

en la librería y funciona como quiero, si se define RW pues lo usa, si no se define pin para RW funciona con RW conectado a GND.

lo dejo así o hay algo que debería colocar dentro del ifdef?
.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Flex_lcd configurable RW
« Respuesta #3 en: 18 de Enero de 2010, 01:38:09 »
La idea es que las funciones que utilizan el pin RW estén dentro del if, y sino, o no se utiliza o se reemplaza por la demora de 60us como en el pedazito de código que coloque en el mensaje anterior.

Adjunto libreria modificada.-

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Flex_lcd configurable RW
« Respuesta #4 en: 18 de Enero de 2010, 10:54:17 »
ok listo entonces no hace falta

#ifdef LCD_RW
#endif

directamente en los defines de pines y cambio a:

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

gracias suky :-/
.

Desconectado ASTROCAR

  • PIC24F
  • *****
  • Mensajes: 664
Re: Flex_lcd configurable RW
« Respuesta #5 en: 18 de Enero de 2010, 23:31:58 »
Hola cryn debi haber visto este post ante pero igual muy util y aprovecho para darte las gracias por la mano de hoy en cuando a la libreria de lcd4x20 ya resolvi el problema con su valiosa colaboracion.

Saludos y espero seguir contando con la valiosa colaboracion de este foro.
Atten.
Alexander Santana.
Venezuela-Barcelona.
EL APRENDER ES NADA; MEJOR ES COMPARTIR EL APRENDIZAJE

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Flex_lcd configurable RW
« Respuesta #6 en: 19 de Enero de 2010, 10:52:34 »
Hola Astrocar, que bueno que todo haya ido bien.

Yo preguntaba para la lcd_flex que es para LCD's de 2 filas, para usar una con 4 filas se necesita colocar direcciones extras, algunas modificaciones en la librería como podrás ver en las funciones lcd_gotoxy y en la \n son algo diferentes en un flex_lcd y en una flex_lcd420.

Haber si me da tiempo para tratar de colocar ambas dentro de una sola libreria...

Bueno estamos por ahí, saludos.
.

Desconectado PICPOWER

  • PIC10
  • *
  • Mensajes: 17
Re: Flex_lcd configurable RW
« Respuesta #7 en: 20 de Noviembre de 2011, 16:24:12 »
Bueno, muchas gracias por este driver para LCD. Me ha resultado muy, muy útil. Sólo hacer un pequeño aporte. Tengo unos sistemas instalados que funcionan 24 horas al día, 7 días a la semana. Nunca los apagan, salvo cuando fallan. Lo cual es raro, pero me parece que acabo de encontrar el problema. Mi sistema se queda pasmado aparentemente debido al LCD. Debido a cómo ocurre el problema, parece que es un problema de comunicación. Al principio creí que era un falso, pero cuando fabriqué más equipos me di cuenta que no. La simulación en ISIS marcaba un "Logic Contention", así que corrí la simulación paso a paso para ver dónde se originaba ese corto. Y pasaba en la siguiente parte de la simulación:

Código: [Seleccionar]
output_high(LCD_E);
delay_cycles(1);
 
retval_0 = input(LCD_DB4);            //Logic Contention a partir de aquí...
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

Después de que habilito al LCD (output_high(LCD_E)) alguno de los pines no se colocaba en alta impedancia a tiempo y chocaban ambas señales (LCD y uC). Aparentemente este corto era mi problema. De cualquier manera era un problema. El problema se soluciona si hacemos entradas a los pines del micro antes de que mandemos el output_high(LCD_E).

Otro error común que cometemos es creer que nuestros drivers van a funcionar a la velocidad adecuada para los LCDs. He visto más de una vez en el foro que los tiempos mal configurados en el driver hacen que los LCD no funcionen adecuadamente. Especialmente cuando usamos micros rápidos. Lo ideal sería checar tiempos de respuesta en la hoja de especificaciones del LCD, así lo hice al principio, pero con el tiempo me aburrí de hacer todos esos cambios. Así que por flojera, tomé el driver Flex_LCD y todo retardo de 1 ciclo (cuyo tiempo varía sergún el uC), lo modifiqué a un delay_us(2); , que es de tiempo constante. De seguro no es el mejor tiempo, pero sí lo más fácil.

Ambas modificaciones en el siguiente código. Idealmente, por el cambio de delay_cycles a delay_us, el código debería funcionar desde un 16F en muy baja frecuencia de CLK, hasta un 18F a alta frecuencia de CLK.

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_E     PIN_B0
#define LCD_RS    PIN_B1
#define LCD_RW    PIN_B2
 
// 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_us(2);
 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;
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
   
output_high(LCD_E);
delay_us(2);
 
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_us(2);
 
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_us(2);
 
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_us(2);
#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
 



Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Flex_lcd configurable RW
« Respuesta #8 en: 20 de Noviembre de 2011, 16:54:30 »
todo esto te lo puedes ahorrar si usas la RAM del pic, modificas la ram, y luego envias toda la ram al lcd, asi evitas tener que hacer lecturas, y el delay solo lo tienes que escribir en un sitio.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Flex_lcd configurable RW
« Respuesta #9 en: 20 de Noviembre de 2011, 17:52:39 »
todo esto te lo puedes ahorrar si usas la RAM del pic, modificas la ram, y luego envias toda la ram al lcd, asi evitas tener que hacer lecturas, y el delay solo lo tienes que escribir en un sitio.

 :z)

Bueno, muchas gracias por este driver para LCD. Me ha resultado muy, muy útil. Sólo hacer un pequeño aporte. Tengo unos sistemas instalados que funcionan 24 horas al día, 7 días a la semana. Nunca los apagan, salvo cuando fallan. Lo cual es raro, pero me parece que acabo de encontrar el problema. Mi sistema se queda pasmado aparentemente debido al LCD. Debido a cómo ocurre el problema, parece que es un problema de comunicación. Al principio creí que era un falso, pero cuando fabriqué más equipos me di cuenta que no. La simulación en ISIS marcaba un "Logic Contention", así que corrí la simulación paso a paso para ver dónde se originaba ese corto. Y pasaba en la siguiente parte de la simulación:

Código: [Seleccionar]
output_high(LCD_E);
delay_cycles(1);
 
retval_0 = input(LCD_DB4);            //Logic Contention a partir de aquí...
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

Puede que hayas configurado los pines de LCD_DB4 en modo Fast_io ? Porque de otra manera, la misma función input primero coloca el pin como entrada y luego lo lee  :tongue:


Saludos!
No contesto mensajes privados, las consultas en el foro


 

anything