Autor Tema: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --  (Leído 9244 veces)

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

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« en: 15 de Septiembre de 2007, 06:05:07 »
Hola a todos... necesito ayuda para controlar un lcd 40x4. intenté utilizar las librerias que están  en el foro, pero este lcd es como si fuera 2 de 40x2. Para cambiar de la linea 1y2 a la 3 y 4. Se utilizan los dos enables que tiene, pero no se como hacer el cambio. Saludos a todos y gracias por la ayuda que puedan brindar.
« Última modificación: 16 de Septiembre de 2007, 18:28:38 por huichoman »

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: LCD 40x4 tiene dos enables ayuda
« Respuesta #1 en: 15 de Septiembre de 2007, 06:32:31 »
Hola huichoman. Es muy facil, deberas conectar los 2 enables al pic, lo que no se si pueden ir los 2 unidos a un solo pin del micro o van separados. Vamos hacer de cuenta que van separados, deberas hacer lo siguiente, en el momento de querer bajar de línea, solo habilitaras el pin correspondiente. Me explico, como sabrás cada línea del LCD tiene su propio banco de memoria, en el momento de cambiar de banco, desabilitaras un enable y habilitaras el otro.

Saludos.  :-/ :-/
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda
« Respuesta #2 en: 15 de Septiembre de 2007, 11:11:26 »
Hola León, te agradezco muchisimo la ayuda. Mira te paso el codigo que utilizo para probar el lcd. La librería que ocupo y la simulación en proteus. Lo que no me queda claro es como habilitar un enable y deshabilitar el otro, estoy utilizando una libreria para un lcd 20x4, supongo que tengo que modificarla, pero no tengo claro como. En este link encontré algo, pero no se como hacerle How to control a HD44780 based character lcd Saludos y gracias de nuevo por todo.

Codigo de prueba
Código: [Seleccionar]
#include <18F2525.h>
#use delay(clock=4000000)
#fuses XT, NOPROTECT, PUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#include <flex_lcd.c>


void main() {
   
   
   lcd_init();
         
          delay_ms(500);
          lcd_gotoxy(1,1);
          printf(lcd_putc,"123456789012345678901234567890123456789");
          delay_ms(500);
          lcd_gotoxy(1,2);
          printf(lcd_putc,"1HUMEDAD: 34.5 ----- TEMPERATURA: 60%% 40");
          delay_ms(3000);
          output_low(PIN_C5);
          while(true) {
       
           lcd_gotoxy(1,3);
           printf(lcd_putc,"Probando\n");
           
         
                     
            }
   }
 
   

Libreria del lcd
Código: [Seleccionar]
// Flex_LCD420.c

// These pins are for my Microchip PicDem2-Plus board,
// which I used to test this driver.
// An external 20x4 LCD is connected to these pins.
// Change these pins to match your own board's connections.

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

#define LCD_RS    PIN_B0
#define LCD_RW    PIN_B1
#define LCD_E     PIN_B2

/*
// To prove that the driver can be used with random
// pins, I also tested it with these pins:
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_B1
#define LCD_DB6   PIN_C5
#define LCD_DB7   PIN_B5

#define LCD_RS    PIN_E2
#define LCD_RW    PIN_B2
#define LCD_E     PIN_D6
*/

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
#define USE_RW_PIN   1     


// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x00
#define LCD_LINE_4_ADDRESS 0x40

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


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

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

int8 lcd_line;

int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2),  // Set mode: 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_RW_PIN
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_us(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);
delay_us(1);
   
return(retval);   
}   
#endif

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

#ifdef USE_RW_PIN
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_RW_PIN
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_RW_PIN
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;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);         

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 50 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

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

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


switch(y)
  {
   case 1:
     address = LCD_LINE_1_ADDRESS;
     break;

   case 2:
     address = LCD_LINE_2_ADDRESS;
     break;

   case 3:
     address = LCD_LINE_3_ADDRESS;
     break;

   case 4:
     address = LCD_LINE_4_ADDRESS;
     break;

   default:
     address = LCD_LINE_1_ADDRESS;
     break;
     
  }

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

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1, ++lcd_line);
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;
   
    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_RW_PIN
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

Adjunto el codigo fuente y la simulación de proteus.

Saludos a todos y gracias por toda la ayuda brindada.

PD. VIVA MÉXICO (15 de Septiembre Hoy y mañana se celebra nuestra independencia).

« Última modificación: 15 de Septiembre de 2007, 11:13:34 por huichoman »

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda
« Respuesta #3 en: 15 de Septiembre de 2007, 13:28:56 »
Hola de nuevo. Encontré una libreria para controlar un lcd de 40x4, pero no está en c de ccs. Voy a tratar de adaptarla. Si alguien tiene mas conocimiento, le estaría muy agradecido por ayudarme. Saludos y trabajando duro para domar este lcd. Código fuente sacado de aquí.

Código: [Seleccionar]
/************************************************************************/
//   routine per LCD da 40 x 4 by Sergio
/************************************************************************/

#define LCD_RS RB4 // Register select
#define LCD_EN1 RB5 // Enable
#define LCD_EN2 RB6
#define LCD_D4 RB0 // LCD data 4
#define LCD_D5 RB1 // LCD data 5
#define LCD_D6 RB2 // LCD data 6
#define LCD_D7 RB3 // LCD data 7

#define LCD_ROWS 2 // valid numbers are: 1,2
// (set to 2 for 2 or more rows)
#define LCD_COLS 40 // valid numbers are: 8,16,20

#define LCD_CLR 0x01 // Clear Display
#define LCD_HOME 0x02 // Cursor to Home position

/************************************************************************/
#define LCD_line1 0x80 // Line 1 position 1
#define LCD_line2 0xC0 // Line 2 position 1


/********************************************/
void LCD_STROBE1() //Strobe primo display
{
LCD_EN1 = 1;
DelayUs(1);
LCD_EN1=0;
}

/********************************************/
void LCD_STROBE2() //Strobe secondo display
{
LCD_EN2 = 1;
DelayUs(1);
LCD_EN2=0;
}
     
/****************************************/
void LCD_NIBBLE_OUT1 (unsigned char c ) //Write a nibble to the LCD 1
{
if ( c & 0b10000000 )
        LCD_D7=1;
else LCD_D7=0;
if ( c & 0b01000000 )
        LCD_D6=1;
else LCD_D6=0;
if ( c & 0b00100000 )
        LCD_D5=1;
else LCD_D5=0;
if ( c & 0b00010000 )
        LCD_D4=1;
else LCD_D4=0;
LCD_STROBE1();
}

/****************************************/
void LCD_NIBBLE_OUT2 (unsigned char c ) //Write a nibble to the LCD 2
{
if ( c & 0b10000000 )
        LCD_D7=1;
else LCD_D7=0;
if ( c & 0b01000000 )
        LCD_D6=1;
else LCD_D6=0;
if ( c & 0b00100000 )
        LCD_D5=1;
else LCD_D5=0;
if ( c & 0b00010000 )
        LCD_D4=1;
else LCD_D4=0;
LCD_STROBE2();
}

/****************************************/
void LCD_WRITE1 (unsigned char c) //Write a byte to the LCD1 (4 bit mode)
{
LCD_NIBBLE_OUT1(c);
c <<= 4;
LCD_NIBBLE_OUT1(c);
DelayUs(50);
}

/****************************************/
void LCD_WRITE2 (unsigned char c) //Write a byte to the LCD2 (4 bit mode)
{
LCD_NIBBLE_OUT2(c);
c <<= 4;
LCD_NIBBLE_OUT2(c);
DelayUs(50);
}

/****************************************/
void LCD_CMD1 (char c) //send a command to the LCD1
{
LCD_RS = 0; // write command
LCD_WRITE1(c);
}

/****************************************/
void LCD_CMD2 (char c) //send a command to the LCD2
{
LCD_RS = 0; // write command
LCD_WRITE2(c);
}

/****************************************/
void LCD_GOTO1 (char line,char pos) //GoTO specified line and position LCD1
{
switch(line)
{
case 1: LCD_CMD1((LCD_line1-1)+pos);
break;
case 2: LCD_CMD1((LCD_line2-1)+pos);
}
}

/****************************************/
void LCD_GOTO2 (char line,char pos) //GoTO specified line and position LCD2
{
switch(line)
{
case 1: LCD_CMD2((LCD_line1-1)+pos);
break;
case 2: LCD_CMD2((LCD_line2-1)+pos);
}
}


/****************************************/
void LCD_CLEAR1 (void) //Clear and Home LCD1
{
LCD_CMD1(LCD_CLR);
DelayMs(3);
}

/****************************************/
void LCD_CLEAR2 (void) //Clear and Home LCD2
{
LCD_CMD2(LCD_CLR);
DelayMs(3);
}


/****************************************/
void LCD_PUTCH1 (char c) //Write one character to the LCD1
{
LCD_RS = 1; // write characters
LCD_WRITE1(c);
}

/****************************************/
void LCD_PUTCH2 (char c) //Write one character to the LCD2
{
LCD_RS = 1; // write characters
LCD_WRITE2(c);
}

/****************************************/
void LCD_PUTUN1 (unsigned int c) //Write numbers to the LCD1
{
unsigned char t1,i,wrote;
unsigned int k;

wrote=0;
for (i=4;i>=1;i--)
{
switch(i){
case 4: k=10000;
break;
case 3: k=1000;
break;
case 2: k=100;
break;
case 1: k=10;
}
t1=c/k;
if((wrote)||(t1!=0))
{
LCD_PUTCH1(t1+'0');
wrote=1;
}
c-=(t1*k);
}
LCD_PUTCH1(c+'0');
}
/****************************************/
void LCD_PUTUN2 (unsigned int c) //Write numbers to the LCD2
{
unsigned char t1,i,wrote;
unsigned int k;

wrote=0;
for (i=4;i>=1;i--)
{
switch(i){
case 4: k=10000;
break;
case 3: k=1000;
break;
case 2: k=100;
break;
case 1: k=10;
}
t1=c/k;
if((wrote)||(t1!=0))
{
LCD_PUTCH2(t1+'0');
wrote=1;
}
c-=(t1*k);
}
LCD_PUTCH2(c+'0');
}
/****************************************/
void LCD_PUTSN1 (signed int c)
{
if(c<0)
{
LCD_PUTCH1('-');
c*=(-1);
}
LCD_PUTUN1(c);
}

/****************************************/
void LCD_PUTSN2 (signed int c)
{
if(c<0)
{
LCD_PUTCH2('-');
c*=(-1);
}
LCD_PUTUN2(c);
}
/****************************************/
void LCD_PUTS1 (const char * s) //Write a string to the LCD1
{
LCD_RS = 1; // write characters
while(*s)
LCD_WRITE1(*s++);
}

/****************************************/
void LCD_PUTS2 (const char * s) //Write a string to the LCD2
{
LCD_RS = 1; // write characters
while(*s)
LCD_WRITE2(*s++);
}

/****************************************/
void LCD_INIT1 (void) //Initialize LCD 1
{
LCD_RS = 0; // write control bytes
DelayMs(20); // power on delay
LCD_D4=1;
LCD_D5=1;
LCD_D6=0;
LCD_D7=0;
LCD_STROBE1();
DelayMs(7);
LCD_STROBE1();
DelayUs(120);
LCD_STROBE1();
DelayMs(7);
LCD_D4=0; // set 4 bit mode
LCD_STROBE1();
DelayUs(60);
LCD_WRITE1(0b00101000); // 4 bit mode, 2 or more lines, 5x8 font
LCD_WRITE1(0b00001000); // display off
LCD_WRITE1(0b00001100); // display on, curson off, blink off
LCD_WRITE1(0b00000110); // shift entry mode, display not shifted
}

/****************************************/
void LCD_INIT2 (void) //Initialize LCD 2
{
LCD_RS = 0; // write control bytes
DelayMs(20); // power on delay
LCD_D4=1;
LCD_D5=1;
LCD_D6=0;
LCD_D7=0;
LCD_STROBE2();
DelayMs(7);
LCD_STROBE2();
DelayUs(120);
LCD_STROBE2();
DelayMs(7);
LCD_D4=0; // set 4 bit mode
LCD_STROBE2();
DelayUs(60);
LCD_WRITE2(0b00101000); // 4 bit mode, 2 or more lines, 5x8 font
LCD_WRITE2(0b00001000); // display off
LCD_WRITE2(0b00001100); // display on, curson off, blink off
LCD_WRITE2(0b00000110); // shift entry mode, display not shifted
}

/************************************************************************/
#undef LCD_ROWS
#undef LCD_COLS
/************************************************************************/



Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: LCD 40x4 tiene dos enables ayuda
« Respuesta #4 en: 16 de Septiembre de 2007, 10:04:13 »
Lamentablemente, aún no trabajo en c.

Saludos.  :-/ :-/
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda (PRUEBA SUPERADA)
« Respuesta #5 en: 16 de Septiembre de 2007, 18:22:13 »
Hola, hice pequeñas modificaciones a  la librería flex_lcd.c para poder controlar el LCD 40x4. Les dejo el código fuente de la librería y del programa de prueba, así como la simulación en Proteus Isis.  Cualquier duda o detalle que encuentren me dicen, y espero que este pequeño aporte sea de utilidad. Saludos.

Simulación en Proteus





Código fuente libreria

Código: [Seleccionar]
//lcd_40x4_h.c by huichoman
//Modificación flex_LCD420.c
//JOSE LUIS SANTIAGO MORALES --Huichoman--
//Tuxtla Gutiérrez, Chiapas, México

// These pins are for my Microchip PicDem2-Plus board,
// which I used to test this driver.
// An external 20x4 LCD is connected to these pins.
// Change these pins to match your own board's connections.

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

#define LCD_RS    PIN_B0
#define LCD_RW    PIN_B1
#define LCD_E1    PIN_B2
#define LCD_E2    PIN_B3
/*
// To prove that the driver can be used with random
// pins, I also tested it with these pins:
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_B1
#define LCD_DB6   PIN_C5
#define LCD_DB7   PIN_B5

#define LCD_RS    PIN_E2
#define LCD_RW    PIN_B2
#define LCD_E1     PIN_D6
*/

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
#define USE_RW_PIN   1     


// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x80
#define LCD_LINE_2_ADDRESS 0xc0
#define LCD_LINE_3_ADDRESS 0x00
#define LCD_LINE_4_ADDRESS 0x40

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


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

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

int8 lcd_line;

int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
 0xc,                     // Display on
 1,                       // Clear display
 6                        // Increment cursor
 };
                             
//DISPLAY 1
//-------------------------------------
void lcd_send_nibble1(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_E1);
 delay_us(2);
 output_low(LCD_E1);
}

//DISPLAY 2
//-------------------------------------
void lcd_send_nibble2(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_E2);
 delay_us(2);
 output_low(LCD_E2);
}


//-----------------------------------
// 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_RW_PIN
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_E1);

delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E1);
delay_us(1);
   
return(retval);   
}   
#endif


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

#ifdef USE_RW_PIN
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

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

#ifdef USE_RW_PIN
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_RW_PIN
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E1);


lcd_send_nibble1(n >> 4);
lcd_send_nibble1(n & 0xf);
}
//----------------------------

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

#ifdef USE_RW_PIN
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_RW_PIN
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E2);


lcd_send_nibble2(n >> 4);
lcd_send_nibble2(n & 0xf);
}
//----------------------------

//DISPLAY 1
//----------------------------
void lcd_init1(void)
{
int8 i;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E1);



// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);         

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

lcd_send_nibble1(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte1(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 50 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

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

//DISPLAY 2
//----------------------------
void lcd_init2(void)
{
int8 i;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E2);


// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);         

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

lcd_send_nibble2(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte2(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 50 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

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



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


switch(y)
  {
   case 1:
     address = LCD_LINE_1_ADDRESS;
     break;

   case 2:
     address = LCD_LINE_2_ADDRESS;
     break;

   case 3:
     address = LCD_LINE_3_ADDRESS;
     break;

   case 4:
     address = LCD_LINE_4_ADDRESS;
     break;

   default:
     address = LCD_LINE_1_ADDRESS;
     break;
     
  }

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

// DISPLAY 1
//-----------------------------
void lcd_putc1(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte1(0,1);
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1, ++lcd_line);
       break;
   
    case '\b':
       lcd_send_byte1(0,0x10);
       break;
   
    default:
       lcd_send_byte1(1,c);
       break;
   }
}

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


//DISPLAY 2
//-----------------------------
void lcd_putc2(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte2(0,1);
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1, ++lcd_line);
       break;
   
    case '\b':
       lcd_send_byte2(0,0x10);
       break;
   
    default:
       lcd_send_byte2(1,c);
       break;
   }
}

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



#ifdef USE_RW_PIN
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


Código fuente programa de prueba

Código: [Seleccionar]
//lcd_40x4.c
//Test rutina lcd_40x4_h.c
//Huichoman

#include <18F2525.h>
#use delay(clock=4000000)
#fuses XT, NOPROTECT, PUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#include <lcd_40x4_h.c>


void main() {
   lcd_init1();
   delay_ms(2);
   lcd_init2();
   
          while(true) {
           
           
           //TEST 1
           //---------------------------------
           lcd_gotoxy(1,1);
           printf(lcd_putc1,"JOSE LUIS SANTIAGO MORALES");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc1,"HUICHOMAN");
           delay_ms(1500);
           lcd_gotoxy(1,1);
           printf(lcd_putc2,"TEST LCD 40X4");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc2,"PRUEBA SUPERADA");
           delay_ms(1000);
           lcd_putc1("\f");
           delay_ms(1500);
           lcd_putc2("\f");
           delay_ms(1500);
           //---------------------------------
           
           //TEST 1
           //---------------------------------
           lcd_gotoxy(1,1);
           printf(lcd_putc1,"LINEA 1 LCD1");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc1,"LINEA 2 LCD1");
           delay_ms(1500);
           lcd_gotoxy(1,1);
           printf(lcd_putc2,"LINEA 1 LCD2");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc2,"LINEA 2 LCD2");
           delay_ms(1500);
           lcd_gotoxy(1,1);
           printf(lcd_putc1,"LCD 1 LINEA 1");
           delay_ms(1500);
           lcd_gotoxy(1,1);
           printf(lcd_putc2,"LCD 2 LINEA 1");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc1,"LCD 1 LINEA 2");
           delay_ms(1500);
           lcd_gotoxy(1,2);
           printf(lcd_putc2,"LCD 2 LINEA 2");
           delay_ms(1500);
           lcd_putc1("\f");
           delay_ms(1500);
           lcd_putc2("\f");
           //---------------------------------
       
           
            }
   } 
 


No puedo adjuntar el rar con el código fuente y la siulación, me indica que el directorio de uploads está lleno.

Saludos.


Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #6 en: 17 de Septiembre de 2007, 12:51:21 »
Hola.

¿no crees que la línea 2 y la línea 4 estan mal?

Con lcd_gotoxy(1,2) debiera escribir al principio de la línea ¿no?

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #7 en: 17 de Septiembre de 2007, 18:39:33 »
Hola Pocher. Creo que es fallo de proteus con el lcd. No hay manera de ponerlo al inicio de columna. Probé el mismo código en proteus para un display de 40x2 y no hubo problema. Saludos.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #8 en: 18 de Septiembre de 2007, 01:24:20 »
Sí, después de mirar el código más detenidamente yo también creo que va a ser eso. Sería interesante como prueba final si alguién tiene la LCD físicamente que nos diga si funciona el código.

Un saludo

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #9 en: 18 de Septiembre de 2007, 01:39:31 »
Ya hice el pedido. Es para un proyecto que tengo en la universidad. Pedí un lcd 40x4  y uno de 20x4 por si tengo problemas con el primero, utilizo el segundo que ya está probado jeje. En cuanto llegué, lo pruebo y posteo algunas fotos. Saludos.

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda --¡¡ FOTOS !! --
« Respuesta #10 en: 12 de Octubre de 2007, 21:27:59 »
Lo prometido es deuda, aca están las fotos del LCD funcionando al 100% con la librería. Me tardé un poco en hacer la prueba porque ando con poco tiempo por la escuela. Además me tomé la molestia de hacer un adaptador del conector de doble fila de pines del LCD para poder conectarlo facilmente al protobard para las pruebas. Saludos.






Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #11 en: 13 de Octubre de 2007, 01:39:08 »
... estupendo, ahora a solucionar lo de la toma de datos para el invernadero.

Un saludo

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #12 en: 13 de Octubre de 2007, 12:58:54 »
Hola huichoman. Felicitaciones por lograr hacerlo andar, ademas te quedo re bueno.

Saludos.  :-/ :-/
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #13 en: 16 de Octubre de 2007, 01:08:11 »
... estupendo, ahora a solucionar lo de la toma de datos para el invernadero.

Un saludo

Gracias amigo pocher. Y si aun falta solucionar lo de la toma de datos, que es algo que aun no le veo por donde, estoy pensando cambiar de sensor de humedad por uno analógico. En breve pongo en el otro post como voy con el código para checar cual es el error. La idea es hacer una red de monitoreo, utilizando rs485. Aparte tener el circuito de control. Aun me falta la etapa de potencia, donde pretendo utilizar relés de estado sólido. Falta aun hacer el software de monitoreo para la pc, aun no me decido que lenguaje utilizar, y que tendré que aprender. Me interesa delphi. Aca en la universidad tenemos labview, pero no me gusta mucho. Saludos, y estaré en contacto.

Citar
Hola huichoman. Felicitaciones por lograr hacerlo andar, ademas te quedo re bueno.


Gracias leon, por el momento solo desplegué ese texto, aun me falta probar a fondo, para ver  si tiene algunos errores. Pero por el momento funciona bien. En proteus despliega mal la segunda  y tercer linea, pero fisicamente si funciona a toda madre. Saludos.

Por cierto, técnicamente, con esta librería se pueden utilizar dos lcds normales (que no tengan doble controlador como el de 40x4) con un solo pic. En breve haré algunas pruebas.

Saludos.


Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: LCD 40x4 tiene dos enables ayuda --Edito: ¡¡ FUNCIONANDO !! --
« Respuesta #14 en: 16 de Octubre de 2007, 02:00:48 »
Felicidades!!! Se ve muy bien!!!  :-/


 

anything