Here is the complete program
; EJERCICIO 18 : LCD con varios mensajes
; -----------------------------------
;
List p=16F870 ;Tipo de procesador
include "P16F870.INC" ;Definiciones de registros internos
Lcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCD
Delay_Cont equ 0x21 ;Variable para la temporización
Temporal_1 equ 0x22 ;Variable temporal
Temporal_2 equ 0x23 ;Variable temporal
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
;******************************************************************************************
;Según el valor contenido en el registro W, se devuelve el carácter a visualizar
Tabla_Mensajes movwf PCL ;Calcula el desplazamiento sobre la tabla
Mens_0 equ $ ;equ Mens_0 apunta al primer carácter del mensaje 0
retlw 'H'
retlw 'o'
retlw 'l'
retlw 'a'
retlw 0x00 ;Ultimo carácter del mensaje 0
Mens_1 equ $ ; Mens_1 apunta al primer carácter del mensaje 1
retlw 'A'
retlw 'd'
retlw 'i'
retlw 'o'
retlw 's'
retlw 0x00 ;Ultimo carácter del mensaje 1
;*********************************************************************************
;Delay_var: Esta rutina de propósito general realiza una temporización variable
;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195.
;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De
;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una
;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo
;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.)
;Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",
;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8"
;(Delay_cont=255).
Delay_var: bcf INTCON,T0IF ;Desconecta el flag de rebosamiento
movlw 0x3c ;Complemento hex. de 195
movwf TMR0 ;carga el TMR0
Intervalo clrwdt ;Refrescar el WDT
btfss INTCON,T0IF ;Rebasamiento del TMR0 ??
goto Intervalo ;Todavía no
decfsz Delay_Cont,F ;Decrementa contador de intervalos
goto Delay_var ;Repite el intervalo de 50 mS
return
;*************************************************************************************
;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está indicado en
;el acumulador. El fin de un mensaje se determina mediante el código 0x00
Mensaje movwf Temporal_1 ;Salva posición de la tabla
Mensaje_1 movf Temporal_1,W ;Recupera posición de la tabla
call Tabla_Mensajes ;Busca caracter de salida
movwf Temporal_2 ;Guarda el caracter
movf Temporal_2,F
btfss STATUS,Z ;Mira si es el último
goto No_es_ultimo
return
No_es_ultimo call LCD_DATO ;Visualiza en el LCD
incf Temporal_1,F ;Siguiente caracter
goto Mensaje_1
;**********************************************************************************
;
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
movlw b'00000110'
movwf ADCON1 ;Configuramos como salidas digitales
movlw b'00000111'
movwf OPTION_REG ;Preescaler de 256 para el TMR0
bcf STATUS,RP0 ;Selecciona banco 0
call LCD_INI ;Secuencia de inicio del LCD
movlw b'00001100'
call LCD_REG ;Envía instrucción: LCD ON, Cursor OFF y blink OFF
Loop movlw b'00000001'
call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)
movlw Mens_0
call Mensaje ;Visualiza el mensaje 0
movlw .20
movwf Delay_Cont
call Delay_var ;Temporiza 2 segundos
movlw b'00000001'
call LCD_REG ;Borra LCD y Home (colocar cursor en 1ª posición)
movlw Mens_1
call Mensaje ;Visualiza el mensaje 1
movlw .20
movwf Delay_Cont
call Delay_var ;Temporiza 2 segundos
goto Loop
END ;Fin del programa fuente
And here the include
; 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
#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
;
LCD_E ENABLE ;Activa E
nop
DISABLE ;Desactiva E
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
We need the statement " Mens_0 equ $ (programcounter) ;Mens_0 apunta al primer carácter del mensaje 0" in order to adress the lower byte of the list .
Try co compile the program and make (when possible; any suggestios how I couls access the first caracter of the list "Hola"
Thanks