No me deja enviarlo. Dice que no hay espacio suficiente, así que, aunque engorroso (lo siento), lo transcribo aquí directamente.
lcd.asm;Ejemplo para simulación y/o MicroPIC Trainer
;
;El manejo de la pantalla LCD
;
;Este ejemplo pretende introducirnos en el manejo de la pantalla LCD, para la visualización
;de diferentes mensajes (p.e. Hola).
;
;Debe recordarse que las líneas RA0-RA2 actúan ahora como salida de señales de control hacia
;el LCD. Al estar conectadas con sendos interruptores en la MicroPIC Trainer, estos deben
;estar a nivel lógico "1" permanentemente.
List p=16F84 ;Tipo de procesador
include "P16F84.INC" ;Definiciones de registros internos
Lcd_var equ 0x0c ;Variables (2) de las rutinas de manejo del LCD
org 0x00 ;Vector de Reset
goto Inicio
org 0x05 ;Salva vector de interrupción
include "LCD_Cxx.inc" ;Incluye las rutinas de manejo del LCD
Inicio clrf PORTB ;Borra los latch de salida
bsf STATUS,RP0 ;Selecciona banco 1
clrf TRISB ;Puerta B se configura como salida
movlw b"00011000"
movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradas
bcf STATUS,RP0 ;Selecciona banco 0
call LCD_INI ;Secuencia de inicio del LCD
movlw b"00001111"
call LCD_REG ;Envía instrucción: LCD ON, Cursor ON y blink ON
movlw "F"
call LCD_DATO ;Visualiza H
movlw "u"
call LCD_DATO ;Visualiza o
movlw "n"
call LCD_DATO ;Visualiza l
movlw "c"
call LCD_DATO ;Visualiza a
movlw "i"
call LCD_DATO ;Visualiza a
movlw "o"
call LCD_DATO ;Visualiza a
movlw "n"
call LCD_DATO ;Visualiza a
movlw "a"
call LCD_DATO ;Visualiza a
movlw " "
call LCD_DATO ;Visualiza blanco
Loop sleep ;Puesta en Standby
goto Loop ;Vuelta a standby
end ;Fin del programa fuente
LCD.c// Ejemplo para simulación y/o MicroPIC Trainer
// El manejo de la pantalla LCD.
// Este ejemplo pretende introducirnos en el manejo de la pantalla LCD, para la
// visualización de diferentes mensajes (p. ej. Hola).
// Debe recordarse que las líneas RA0-RA2 actúan ahora como salida de señales de control
// hacia el LCD. Al estar conectadas con sendos interruptores en la MicroPIC Trainer,
// estos deben estar a nivel lógico "1" permanentemente.
#include <16f84.h>
#use delay(clock=4000000)
#include <lcd2.c>
#fuses XT,NOWDT,NOPUT
#use fast_io(A)
#use fast_io(B)
main() {
set_tris_a(0x18); // 00011000
set_tris_b(0x00);
lcd_init(); // Comandos de inicialización del LCD.
while(1)
{
lcd_enviar(LCD_COMANDO,LCD_CLEAR); // Envía comando al LCD
lcd_enviar(LCD_COMANDO, LCD_HOME);
lcd_gotoxy(1,1);
lcd_putc(" Prueba "

;
lcd_putc("H"); // Envía caracter al LCD.
lcd_putc("o");
lcd_putc("l");
lcd_putc("a");
lcd_putc(" ");
delay_ms(1000);
}
}
Ahora pongo los archivos de manejo del LCD.
Lcd_cxx.inc;El conjunto de rutinas que se presentan a continuación permiten realizar las tareas básicas
;de control del módulo de visualización LCD. Este fichero se debe incluir en los futuros
;programas fuente mediante la directiva INCLUDE
;
;Permiten adaptarse a los nuevos tiempos de las nuevas pantallas LCD de Winteck
;
;Las rutinas están adaptadas a las velocidades más lentas de los nuevos módulo de winteck, en las
;cuales el tiempo de activación (Tc) de la señal ENABLE es de 40 uS.
#define ENABLE bsf PORTA,2 ;Activa señal E
#define DISABLE bcf PORTA,2 ;Desactiva señal E
#define LEER bsf PORTA,1 ;Pone LCD en Modo RD
#define ESCRIBIR bcf PORTA,1 ;Pone LCD en Modo WR
#define OFF_COMANDO bcf PORTA,0 ;Desactiva RS (modo comando)
#define ON_COMANDO bsf PORTA,0 ;Activa RS (modo dato
CBLOCK Lcd_var ;Inicio de las variables. Será la primera
Lcd_Temp_1 ;direccón libre disponible
Lcd_Temp_2
ENDC
;*************************************************************************
;UP_LCD: Configuración PIC para el LCD.
;
UP_LCD bsf STATUS,RP0 ;Banco 1
clrf PORTB ;RB <0-7> salidas digitales
movlw b"00011000"
movwf PORTA ;RA0-RA2 salidas, RA3-RA4 entradas
bcf STATUS,RP0 ;Banco 0
OFF_COMANDO ;RS=0
DISABLE ;E=0
return
;
;**************************************************************************
;LCD_BUSY: Lectura del Flag Busy y la dirección.
;
LCD_BUSY LEER ;Pone el LCD en Modo RD
bsf STATUS,RP0
movlw H"FF"
movwf PORTB ;Puerta B como entrada
bcf STATUS,RP0 ;Selecciona el banco 0
ENABLE ;Activa el LCD
nop
LCD_BUSY_1 btfsc PORTB,7 ;Chequea bit de Busy
goto LCD_BUSY_1 ;
DISABLE ;Desactiva LCD
bsf STATUS,RP0
clrf PORTB ;Puerta B salida
bcf STATUS,RP0
ESCRIBIR ;Pone LCD en modo WR
return
;**************************************************************************
;LCD_E: Pulso de Enable. En los nuevos LCD"s esta señal debe estar a "0" unos 40uS antes de
;volver a activarse a "1".
;
LCD_E ENABLE ;Activa E
nop
DISABLE ;Desactiva E
movlw .14
movwf Lcd_Temp_1
LCD_E_1 decfsz Lcd_Temp_1,F ;Pierde unos 40 uS para la constante de tiempo Tc
goto LCD_E_1 ;de los nuevos módulos LCD de winteck
return
;
;**************************************************************************
;LCD_DATO: Escritura de datos en DDRAM o CGRAM. Envía el dato presente en el W
;
LCD_DATO OFF_COMANDO ;Desactiva RS (modo comando)
movwf PORTB ;Valor ASCII a sacar por portb
call LCD_BUSY ;Espera a que se libere el LCD
ON_COMANDO ;Activa RS (modo dato).
goto LCD_E ;Genera pulso de E
;**************************************************************************
;LCD_REG: Escritura de comandos en el LCD. Envía el comando presente en el W
LCD_REG OFF_COMANDO ;Desactiva RS (modo comando)
movwf PORTB ;Código de comando.
call LCD_BUSY ;LCD libre?.
goto LCD_E ;SI.Genera pulso de E.
;***************************************************************************
;LCD_INI: inicialización del LCD enviando el comando "Function Set" 3 veces consecutivas
;con un intervalo de unos 5 mS. El LCD queda borrado y el cursor en la primera posición
LCD_INI movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00000001" ;Borra LCD y Home.
call LCD_REG
return
;*****************************************************************************
;LCD_DELAY: Rutina de temporización de unos 5 mS. Se emplean las variables Lcd_Temp_1
;y LCD_Temp_2 en lugar del TMR0. Este queda libre para las aplicaciones del usuario
LCD_DELAY: clrwdt
movlw .10
movwf Lcd_Temp_1
clrf Lcd_Temp_2
LCD_DELAY_1: decfsz Lcd_Temp_2,F
goto LCD_DELAY_1
decfsz Lcd_Temp_1,F
goto LCD_DELAY_1
return
lcd C// Funciones para la gestion del display LCD de la MicroPIC Trainer.
// lcd_init() Debe ser llamada antes que las otras funciones.
//
// lcd_putc(c) Visualiza c en la siguiente posición del display.
// Caracteres especiales de control:
// f Borrar display
//
Saltar a la segunda linea
// Retroceder una posición.
//
// lcd_gotoxy(x,y) Selecciona la nueva posicion de escritura en el display.
// (la esquina superior izquierda es 1,1)
//
// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del display.
#bit lcd_enable = 5.2
#bit lcd_rw = 5.1
#bit lcd_rs = 5.0
#byte lcd_a = 5
#byte lcd_b = 6
#define LCD_LINEA2 0x40 // Direccion de memoria para la segunda linea
#define LCD_DATO 1
#define LCD_COMANDO 0
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_DISPLAY_OFF 0x08
#define LCD_DISPLAY_ON 0x0C
#define LCD_CURSOR_ON 0x0E
#define LCD_CURSOR_BLINK 0x0F
#define LCD_CURSOR_SHIFT_RIGHT 0x10
#define LCD_CURSOR_SHIFT_LEFT 0x14
#define LCD_DISPLAY_SHIFT_RIGHT 0x18
#define LCD_DISPLAY_SHIFT_LEFT 0x1C
int lcd_leer()
{
int valor;
set_tris_a(0x18);
set_tris_b(0xFF);
lcd_rw = 1;
delay_cycles(1);
lcd_enable = 1;
delay_cycles(1);
valor = lcd_b;
lcd_enable = 0;
delay_us(40);
set_tris_b(0x00);
return valor;
}
void lcd_enviar(int dir, int valor)
{
set_tris_a(0x00);
set_tris_b(0x00);
lcd_rs = 0;
while( bit_test(lcd_leer(),7) );
lcd_rs = dir;
delay_cycles(1);
lcd_rw = 0;
delay_cycles(1);
lcd_enable = 0;
lcd_b = valor;
delay_cycles(1);
lcd_enable = 1;
delay_us(2);
lcd_enable = 0;
delay_us(40);
}
void lcd_init()
{
int i;
set_tris_a(0x18);
set_tris_b(0x00);
lcd_enable = 0;
lcd_rw = 0;
lcd_rs = 0;
delay_ms(300);//15
for(i=0; i<3; i++)
{
lcd_enviar(LCD_COMANDO,0x38);
delay_ms(50);//5
}
lcd_enviar(LCD_COMANDO,LCD_DISPLAY_ON);
lcd_enviar(LCD_COMANDO,0x06);
lcd_enviar(LCD_COMANDO,LCD_CLEAR);
lcd_enviar(LCD_COMANDO,LCD_HOME);
}
void lcd_gotoxy( byte x, byte y) {
byte dir;
if(y!=1)
dir=LCD_LINEA2;
else
dir=0;
dir+=x-1;
lcd_enviar(LCD_COMANDO,0x80|dir);
}
void lcd_putc( char c) {
switch (c) {
case "f" : lcd_enviar(LCD_COMANDO,0x01);
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); break;
case "" : lcd_enviar(LCD_COMANDO,0x10); break;
default : lcd_enviar(LCD_DATO,c); break;
}
}
char lcd_getc( int x, int y) {
char valor;
lcd_gotoxy(x,y);
lcd_rs = 1;
valor = lcd_leer();
lcd_rs = 0;
return valor;
}