;Control de una LCD con el 16F84A con XTAL de 4MHz

	list p=16F84A
	radix	HEX

	__CONFIG H'3FFF'&H'3FFF'&H'3FFB'&H'3FFD'		;Configura CP, WDT y PWRTE en OFF y como oscilador XT
;************************* Declaración de Puertos y Variables**************************************

TMR_Opt	EQU	0x01
Estado	EQU	0x03
PA_TA	EQU	0x05
PB_TB	EQU	0x06
Intcon	EQU	0x0B

CHAR	EQU 0x0F
RAM		EQU 0x10
CMD		EQU	0x11
RETARDO	EQU	0x12

	#define	S_E	PA_TA,0		;llamamos E a PA0 configurado como la señal de activación del módulo LCD
	#define	RW	PA_TA,1		;llamamos RW a PA1 configurado como la señal lectura/escritura
	#define	RS	PA_TA,2		;llamamos RS a PA2 configurado como la señal se selcción del registro de control/registro de datos

BANCO0	macro   ;MACRO PARA EL CAMBIO AL BANCO 0
		bcf Estado,5
		bcf Estado,6 
		ENDm

BANCO1	macro   ;MACRO PARA EL CAMBIO AL BANCO 1
		bsf Estado,5
		bcf Estado,6
		ENDm

PB_SA	macro	;Macro para poner el PB en salidas
		BANCO1
		clrf PB_TB
		BANCO0
		ENDm

PA_SA	macro	;Macro para poner el PA en salidas
		BANCO1
		clrf PA_TA
		BANCO0
		ENDm

PB_EN	macro	;Macro para poner el PB en entradas
		BANCO1
		movlw	0xFF
		movwf	PB_TB
		BANCO0
		ENDm

PA_EN	macro	;Macro para poner el PA en entradas
		BANCO1
		movlw	0xFF
		movwf	PA_TA
		BANCO0
		ENDm

	org 0


;******************************** Programa *********************************************

		clrf	Intcon		;Prohibición de las interrupciones
		PB_SA
		PA_SA

inicio	movlw	0x3C		;Configura la LCD como bus de datos de 8 bits y dos líneas
		call	CONF		;llamada a la rutina de configuración

		movlw	0x01		;Borra la pantalla
		call	CONF		;llamada a la rutina de configuración

		movlw	0x0C		;Activa la pantalla, el cursor y desactiva el parpadeo
		call	CONF		;llamada a la rutina de configuración

		movlw	0x01		;Borra la pantalla
		call	CONF		;llamada a la rutina de configuración

		movlw	0x80			;Posiciona la RAM en la h00
		movwf	RAM
		movf	RAM,0
		call	CONF

;************************************* Escritura ********************************

		movlw	'P'			;Manda la letra P
		call	LETRA

		movlw	'r'			;Manda la letra r
		call	LETRA

		movlw	'u'			;Manda la letra u
		call	LETRA

		movlw	'e'			;Manda la letra e
		call	LETRA

		movlw	'b'			;Manda la letra b
		call	LETRA

		movlw	'a'			;Manda la letra a
		call	LETRA

		movlw	' '			;Manda un espacio
		call	LETRA

		movlw	b'11001000'		;Manda un simbolo japo
		call	LETRA

		

;************************************** Rutina Ocupado ***************************

OCUPADO	PB_EN				;Ponemos el puerto B en entrada
		bcf		RS			;Ponemos la señal RS=0 para leer el dato
		bsf		RW			;Ponemos la señal RW=1 para leer el dato

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

; ESTE PULSO SOLO FUNNCIONA EN PROTEUS
; AL IMPLEMENTAR DEBES SETEAR E, VERIFICAR BF Y LUEGO RESETEAR E

		bsf		S_E			;Ponemos la señal E=1 para activar la LCD
		NOP
		NOP
		bcf		S_E

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

		movf	PB_TB,0		;Comprobamos el valor de la PB7
		andlw	b'10000000'
		btfss	Estado,2
		goto	OCUPADO		;Como es 1 la LCD está ocupada, volvemos a chequear para ver si ya no lo está


; ESTA LINEA YA NO VA
;		bcf		S_E


		bcf		RW
		PB_SA
		return

;********************************** Rutina de configuración *********************************

CONF	movwf	CMD			;Guardamos el comando en la memoria
		call	OCUPADO		;Comprobamos que la LCD no esté ocupada
		bcf		RS			;Configuramos la LCD para que reciba el comando
		bcf		RW
		bsf		S_E
		movf	CMD,0		;Sacamos el comando por el bus de datos
		movwf	PB_TB
		call	Dly
	
		bcf		S_E			;Desacativamos la LCD
		return

;*********************************** Rutina de escritura de caracteres ************************

LETRA	movwf	CHAR		;Guardamos el caracter en la memoria
		call	OCUPADO		;Comprobamos que no esté ocupada la LCD
		bsf		RS			;Configuramos la LCD para que reciba un caracter
		bcf		RW


; ESTA LINEA YA NO VA
;		bsf		S_E

		movf	CHAR,0		;Llevamos el caracter a W
		movwf	PB_TB		;Sacamos el caracter por el bus de datos
		call	Dly


;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

; ESTE PULSO E, FUNCIONA BIEN EN PROTEUS Y EN LA IMPLEMENTACION REAL

		bsf		S_E
		nop
		nop
		bcf		S_E			;Desactivamos la LCD

;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

		return

;********************************** Rutina de retardo ********************************************

Dly		movlw	0x07
		movwf	RETARDO
ret		decfsz	RETARDO,1
		goto	ret
		return

;********************************** Selección de la DDRAM ****************************************

DDRAM	iorlw	0x80		;manda el código para seleccionar la DDRAM
		call	CONF
		return

;********************************** Selección de la CGRAM *****************************************

CGRAM	andlw	0x3F		;Seleccionamos los bits 0-5
		iorlw	0x40		;Indicamos que es la CGRAM
		call	CONF
		return


	END
