CBLOCK
LCD_DATO
LCD_GuardaDato
LCD_Auxiliar1
LCD_Auxiliar2
ENDC
CHAR_X_LINEA EQU .16 ; Número de caracteres por línea de la pantalla.
#DEFINE RS PORTC,0
#DEFINE RE PORTC,1
#DEFINE LCD_BUS PORTB
INI_LCD
;*********************************************************
BANKSEL T1CON
MOVLW B'00110000' ; CONFIGURO TMR1
MOVWF T1CON ; PARA RETARDOS
;*********************************************************
BCF RE ; DESHABILITAMOS PIN
BCF RS ; ACTIVAMOS MODO COMANDO PONIENDO RS EN 0
CALL RET_10ms ; RETARDO PARA ESTABILIZACIÓN LCD
MOVLW B'00110000' ;
CALL LCD_WRITE ; ESCRIBIMOS DATO EN LCD
CALL RET_5ms
MOVLW B'00110000'
CALL LCD_WRITE
CALL RET_100us
MOVLW B'00110000'
CALL LCD_WRITE
CALL RET_100us ; Este retardo es necesario para simular en PROTEUS.
MOVLW B'00100000' ; Interface de 4 bits.
CALL LCD_WRITE
CALL RET_100us ; Este retardo es necesario para simular en PROTEUS.
CALL LCD_2Lineas4Bits5x7 ; LCD de 2 líneas y caracteres de 5x7 puntos.
CALL LCD_CLEAR ; Pantalla encendida y limpia. Cursor al principio
CALL LCD_C_OFF ; de la línea 1. Cursor apagado.
CALL LCD_CursorIncr ; Cursor en modo incrementar.
RETURN
LCD_WRITE
ANDLW B'11110000' ; Se queda con el nibble alto del dato que es el
MOVWF LCD_DATO ; que hay que enviar y lo guarda.
MOVF LCD_BUS,W ; Lee la información actual de la parte baja
ANDLW B'00001111' ; del Puerto B, que no se debe alterar.
IORWF LCD_DATO,F ; Enviará la parte alta del dato de entrada
MOVF LCD_DATO,W ; Recupera el dato a enviar.
MOVWF LCD_BUS ; Envía el dato al módulo LCD.
BSF RE ; Permite funcionamiento del LCD mediante un pequeño
BCF RE ; pulso y termina impidiendo el funcionamiento del LC
RETURN
LCD_CursorIncr ; Cursor en modo incrementar.
MOVLW B'00000110'
BRA LCD_CMD
LCD_L1 ; Cursor al principio de la Línea 1.
MOVLW B'10000000' ; Dirección 00h de la DDRAM
BRA LCD_CMD
LCD_L2 ; Cursor al principio de la Línea 2.
MOVLW B'11000000' ; Dirección 40h de la DDRAM
BRA LCD_CMD
LCD_L3 ; Cursor al principio de la Línea 3
MOVLW B'10010100' ; Dirección 14h de la DDRAM
BRA LCD_CMD
LCD_L4 ; Cursor al principio de la Línea 4
MOVLW B'11010100' ; Dirección 54h de la DDRAM
BRA LCD_CMD
LCD_PosicionLinea1 ; Cursor a posición de la Línea 1, a partir de la
IORLW b'10000000' ; dirección 00h de la DDRAM más el valor del
BRA LCD_CMD ; registro W.
LCD_PosicionLinea2 ; Cursor a posición de la Línea 2, a partir de la
IORLW b'11000000' ; dirección 40h de la DDRAM más el valor del
BRA LCD_CMD ; registro W.
LCD_OFF ; Pantalla apagada.
MOVLW B'00001000'
BRA LCD_CMD
LCD_C_ON ; Pantalla encendida y cursor encendido.
MOVLW B'00001110'
BRA LCD_CMD
LCD_C_OFF ; Pantalla encendida y cursor apagado.
MOVLW B'00001100'
BRA LCD_CMD
LCD_CLEAR ; Borra toda la pantalla, memoria DDRAM y pone el
MOVLW B'00000001' ; cursor a principio de la línea 1.
BRA LCD_CMD
LCD_2Lineas4Bits5x7 ; Define la pantalla de 2 líneas, con caracteres
MOVLW B'00101000' ; de 5x7 puntos y conexión al PIC mediante bus de
LCD_CMD
BCF RS ; Activa el Modo Comando, poniendo RS=0.
BRA LCD_Envia
ENVIAR_DATO
BSF RS ; Activa el "Modo Dato", poniendo RS=1.
CALL LCD_CodigoCGROM ; Obtiene el código para correcta visualización.
LCD_Envia
MOVWF LCD_GuardaDato ; Guarda el dato a enviar.
CALL LCD_WRITE ; Primero envía el nibble alto.
SWAPF LCD_GuardaDato,W ; Ahora envía el nibble bajo. Para ello pasa el
; nibble bajo del dato a enviar a parte alta del byte.
CALL LCD_WRITE ; Se envía al visualizador LCD.
BTFSS RS ; Debe garantizar una correcta escritura manteniendo
CALL RET_1ms ; 2 ms en modo comando y 50 µs en modo cáracter.
CALL RET_100us
RETURN
LCD_CodigoCGROM
MOVWF LCD_DATO ; Guarda el valor del carácter y comprueba si es
LCD_EnheMinuscula ; un carácter especial.
SUBLW 'ñ' ; ¿Es la "ñ"?
BTFSS STATUS,Z
GOTO LCD_EnheMayuscula ; No es "ñ".
MOVLW B'11101110' ; Código CGROM de la "ñ".
MOVWF LCD_DATO
GOTO LCD_FinCGROM
LCD_EnheMayuscula
MOVF LCD_DATO,W ; Recupera el código ASCII de entrada.
SUBLW 'Ñ' ; ¿Es la "Ñ"?
BTFSS STATUS,Z
GOTO LCD_Grado ; No es "Ñ".
MOVLW b'11101110' ; Código CGROM de la "ñ". (No hay símbolo para
MOVWF LCD_DATO ; la "Ñ" mayúscula en la CGROM).
GOTO LCD_FinCGROM
LCD_Grado
MOVF LCD_DATO,W ; Recupera el código ASCII de entrada.
SUBLW 'º' ; ¿Es el símbolo "º"?
BTFSS STATUS,Z
GOTO LCD_FinCGROM ; No es "º".
MOVLW b'11011111' ; Código CGROM del símbolo "º".
MOVWF LCD_DATO
LCD_FinCGROM
MOVF LCD_DATO,W ; En (W) el código buscado.
RETURN
LCD_LineaEnBlanco
MOVLW CHAR_X_LINEA
BRA LCD_EnviaBlancos
LCD_UnEspacioBlanco
MOVLW .1
BRA LCD_EnviaBlancos
LCD_DosEspaciosBlancos
MOVLW .2
BRA LCD_EnviaBlancos
LCD_TresEspaciosBlancos
MOVLW .3
LCD_EnviaBlancos
MOVWF LCD_Auxiliar1 ; (LCD_Auxiliar1) se utiliza como contador.
LCD_EnviaOtroBlanco
MOVLW ' ' ; Esto es un espacio en blanco.
CALL LCD_DATO ; Visualiza tanto espacios en blanco como se
DECFSZ LCD_Auxiliar1,F ; haya cargado en (LCD_Auxiliar1).
GOTO LCD_EnviaOtroBlanco
RETURN
; Subrutinas "LCD_ByteCompleto" y "LCD_Byte" --------------------------------------------
;
; Subrutina "LCD_ByteCompleto", visualiza el byte que almacena el registro W en el
; lugar actual de la pantalla. Por ejemplo, si (W)=b'10101110' visualiza "AE".
;
; Subrutina "LCD_Byte" igual que la anterior, pero en caso de que el nibble alto sea cero
; visualiza en su lugar un espacio en blanco. Por ejemplo si (W)=b'10101110' visualiza "AE"
; y si (W)=b'00001110', visualiza " E" (un espacio blanco delante).
;
; Utilizan la subrutina "LCD_Nibble" que se analiza más adelante.
LCD_Byte
movwf LCD_Auxiliar2 ; Guarda el valor de entrada.
andlw b'11110000' ; Analiza si el nibble alto es cero.
btfss STATUS,Z ; Si es cero lo apaga.
goto LCD_VisualizaAlto ; No es cero y lo visualiza.
movlw ' ' ; Visualiza un espacio en blanco.
call LCD_DATO
goto LCD_VisualizaBajo
LCD_ByteCompleto
movwf LCD_Auxiliar2 ; Guarda el valor de entrada.
LCD_VisualizaAlto
swapf LCD_Auxiliar2,W ; Pone el nibble alto en la parte baja.
call LCD_Nibble ; Lo visualiza.
LCD_VisualizaBajo
movf LCD_Auxiliar2,W ; Repite el proceso con el nibble bajo.
LCD_Nibble
andlw b'00001111' ; Se queda con la parte baja.
movwf LCD_Auxiliar1 ; Lo guarda.
sublw 0x09 ; Comprueba si hay que representarlo con letra.
btfss STATUS,C
goto LCD_EnviaByteLetra
movf LCD_Auxiliar1,W
addlw '0' ; El número se pasa a carácter ASCII sumándole
goto LCD_FinVisualizaDigito ; el ASCII del cero y lo visualiza.
LCD_EnviaByteLetra
movf LCD_Auxiliar1,W
addlw 'A'-0x0A ; Sí, por tanto, se le suma el ASCII de la 'A'.
LCD_FinVisualizaDigito
goto LCD_DATO ; Y visualiza el carácter. Se hace con un "goto"
; para no sobrecargar la pila.
RET_37us
BCF PIR1,TMR1IF
MOVLW 0XFF
MOVWF TMR1H
MOVLW 0XDC
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_100us
BCF PIR1,TMR1IF
MOVLW 0XFF
MOVWF TMR1H
MOVLW 0X9C
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_1ms
BCF PIR1,TMR1IF
MOVLW 0XFC
MOVWF TMR1H
MOVLW 0X18
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_5ms
BCF PIR1,TMR1IF
MOVLW 0XEC
MOVWF TMR1H
MOVLW 0X78
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_10ms
BCF PIR1,TMR1IF
MOVLW 0XD8
MOVWF TMR1H
MOVLW 0XF0
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_50ms
BCF PIR1,TMR1IF
MOVLW 0X3C
MOVWF TMR1H
MOVLW 0XB0
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_100ms
BCF PIR1,TMR1IF
MOVLW 0X3C
MOVWF TMR1H
MOVLW 0XB0
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
BCF PIR1,TMR1IF
MOVLW 0X3C
MOVWF TMR1H
MOVLW 0XB0
MOVWF TMR1L
BSF T1CON,TMR1ON
BTFSS PIR1,TMR1IF
GOTO $-1
BCF T1CON,TMR1ON
RETURN
RET_500ms
MOVLW .5
MOVWF TIME_AUX
CALL RET_100ms
DECFSZ TIME_AUX,F
GOTO $-2
RETURN
RET_1s
MOVLW .10
MOVWF TIME_AUX
CALL RET_100ms
DECFSZ TIME_AUX,F
GOTO $-2
RETURN