aki te dejo una q suelo usar... no se de donde la saké asiq no puedo citar la fuente

es totalmente configurable y no tiene pata de R/W (hay q ponerla a masa)... x lo q no podrás leer del LCD (q pocas veces se hace

, está preparada para 4Mhz, si vas a usar un clock mayor tendrás que ajustar los tiempos

//include LCD para CCS
// La ventaja de este codigo es que puedes trabajar si lo quieres con pines
// dispersos es decir no estas sujeto a la mitad de un puerto
// Registros de Puertos A
#define PORTC 0xf82 // PortC
#define TRISC 0xf94 // TrisC
// Definición de Puertos Pantalla LCD 40x20 Hitachi 44780
#bit lcd_en = PORTC.0
#bit tris_lcd_en = TRISC.0
#bit lcd_rs = PORTC.1
#bit tris_lcd_rs = TRISC.1
#bit lcd_db4 = PORTC.4
#bit tris_lcd_db4 = TRISC.4
#bit lcd_db5 = PORTC.5
#bit tris_lcd_db5 = TRISC.5
#bit lcd_db6 = PORTC.6
#bit tris_lcd_db6 = TRISC.6
#bit lcd_db7 = PORTC.7
#bit tris_lcd_db7 = TRISC.7
// lcd_init() Inicialización del LCD (debe utilizarse al principio,
// antes de trabajar con el LCD).
//
// lcd_putc(c) Imprime un caracter en el LCD.
//
// lcd_gotoxy(x,y) Selecciona la nueva posicion de escritura en el LCD.
// (la esquina superior izquierda es 1,1)
//
// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del LCD.
//
// void lcd_erase_line(x) Borra una cantidad de caracter hacia la derecha
// Conexion a la pantalla LCD 40x4
// RA0 <---> LCD DB4
// RA1 <---> LCD DB5
// RA2 <---> LCD DB6
// RA3 <---> LCD DB7
// RA5 <---> LCD ENABLE
// RA4 <---> LCD RS
//
#define LCD_DATO 1
#define LCD_INST 0
#define LCD_LINEA1 0x80 // Direccion de memoria para la 1 linea
#define LCD_LINEA2 0xc0 // Direccion de memoria para la 2 linea
#define LCD_LINEA3 0x94 // Direccion de memoria para la 3 linea
#define LCD_LINEA4 0xd4 // Direccion de memoria para la 4 linea
// 7 6 5 4 3 2 1 0
// Function Set 0b 0 0 1 B L F 0 0
// Bus size, B:0=4 bits, B:1=8 bits
// Line Number, L:0=1 Line, L:1=2 Lines
// Font size F:0=5x8, F:1=5x10
#define LCD_FUNCTION_SET 0b00101000 // Bus=4bit, Line=2 & Font=5x8
// 7 6 5 4 3 2 1 0
// Display/Cursor 0b 0 0 0 0 1 D U B
// Set Display on/off, D:0=off, D:1=on
// Underline cursor, U:0=off, U:1=on
// Blinking cursor, B:0=off, B:1=on
#define LCD_DISPLAY_CURSOR 0b00001100 // Display=on, Scroll=off, Blinkin=off
// 7 6 5 4 3 2 1 0
// Entry Mode 0b 0 0 0 0 0 1 M S
// Cursor direction, M:0=left, 1=right
// Display Scroll, S:0=no scroll, S:1=scroll
#define LCD_ENTRY_MODE 0b00000110 // Increment cursor, no disp shift
#define LCD_CLEAR_DISPLAY 0b00000001 // Clear Display
void lcd_set_write()
{
tris_lcd_db4 = 0; //
tris_lcd_db5 = 0; //
tris_lcd_db6 = 0; //
tris_lcd_db7 = 0; //---> Set PORTC RA0-RA3 mode output
}
void lcd_send_nibble(int8 n)
{
if (bit_test(n,0)) //
lcd_db4 = 1; //
else //
lcd_db4 = 0; //
if (bit_test(n,1)) //
lcd_db5 = 1; //
else //
lcd_db5 = 0; //
if (bit_test(n,2)) //
lcd_db6 = 1; //
else //
lcd_db6 = 0; //
if (bit_test(n,3)) //
lcd_db7 = 1; //
else //
lcd_db7 = 0; //---> Set data nibble
delay_cycles(1); // nop
lcd_en = 1; // Habilita LCD Enable __
delay_us(2); // Espera 2 uSeg. | |
lcd_en = 0; // Desabilita LCD Enable __| |__
}
void lcd_send_byte (int1 select, int8 n)
{
lcd_rs = 0; // Modo de instruccion
delay_us(10);
lcd_rs = select; // Escoje entre RS=0 : Instruccion & RS=1 : Data
delay_cycles(1); // nop // 5 original
lcd_en = 0; // Desabilita LCD Eneable
lcd_send_nibble(n >> 4); // Envia los datos superiores MSB
lcd_send_nibble(n); // Envia los datos inferiores LSB
}
void lcd_init()
{
int8 i, count=0;
lcd_set_write(); // Prepara el puerto DB4-DB7 como salida
tris_lcd_en = 0; //
tris_lcd_rs = 0; //---> Set PORTC RA0, RA1 & RA2 mode output
lcd_en = 0; //
lcd_rs = 0; //---> Clear LCD_EN, LCD_RW & LCD_RS
delay_ms(15);
// retry:
for(i=1; i<=3; ++i)
{
lcd_send_nibble(0b0011); // 8 bit mode 3 times
delay_ms(5);
}
lcd_send_nibble(0b0010); // 4 bit mode
lcd_send_byte(LCD_INST, LCD_FUNCTION_SET); // Function Set
lcd_send_byte(LCD_INST, LCD_DISPLAY_CURSOR); // Display Cursor
lcd_send_byte(LCD_INST, LCD_ENTRY_MODE); // Entry Mode
lcd_send_byte(LCD_INST, LCD_CLEAR_DISPLAY); // Clear Display
}
void lcd_gotoxy(int8 x, int8 y)
{
int8 const address[4]={LCD_LINEA1,LCD_LINEA2,LCD_LINEA3,LCD_LINEA4};
int8 pos;
pos=address[y-1]+(x-1);
lcd_send_byte (LCD_INST, pos);
}
void lcd_putc(char c)
{
switch (c)
{
case "f" : lcd_send_byte(0,1); //Limpia la pantalla
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); //Coloca puntero en 1ª posicion de la 2ª línea
break;
case "" : lcd_send_byte(LCD_INST,0x10); //Retrocede una posición el cursor
break;
case " " : lcd_send_byte(LCD_INST,0x14); //Avanza una posición el cursor
break;
case "" : lcd_send_byte(LCD_INST,0x18); //Retrocede una posición la pantalla visible
break;
case "v" : lcd_send_byte(LCD_INST,0x1C); //Avanza una posición la pantalla visible
break;
default : lcd_send_byte(LCD_DATO,c); //Envía caracter a DDRAM,
break; //Si es una tira, los envía todos uno a uno
}
}
void lcd_clear()
{
lcd_send_byte(LCD_INST,0x01);
}
void lcd_home()
{
lcd_send_byte(LCD_INST,0x02);
}
void lcd_erase_line(int8 x)
{
int8 i;
for(i=1;i<=x;++i)
{
lcd_send_byte(LCD_DATO,32);
}
}
Saludos!