;Curso básico de microcontroladores PIC. www.pictronic.com --- info@pictronic.com
;prac_21.asm - Grabación en la EEPROM de datos

;El siguiente ejercicio, es prácticamente idéntico al de la práctica 11, excepto que el valor binario 
;del contador up/down mostrado en el PORTB se guarda contínuamente en la posición 0x00 de 
;la EEPROM de datos, de forma que cada vez que se conecte la alimentación y aranque de nuevo 
;el programa se visualize el último valor del contador antes de apagarse la alimentación.

;Para la ejecución de esta práctica solo debe estar colocado el jumper J2.
;Los interruptores RA0 y RA1 deben estar permanentemente a 1 para que los pulsadores puedan 
;cambiar el estado de dichas entradas


	list		p=16F84		;indica al ensamblador el modelo de PIC
	include		"P16F84.inc" ;incluye librería de definiciones para el PIC16F84
	__config	_CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC ;palabra de configuración

CONTA	equ	0x0C		;registro para el bucle de pausa 

		org	0x00	;primera posición de la memoria de programa
		goto	INICIO	;salto a la etiqueta inicio
		org	0x05	;para pasar por encima del vector de interrupción

;**Subrutinas "LEER" y "GRABAR" en la memoria EEPROM. Obsérvese que siempre se 
;lee y se escribe en la dirección 0x00 de la EEPROM. 
;Para utilizar estas mismas subrutinas en otros programas donde se utilizen varias direcciones
;de la memoria, antes de llamarlas, debe cargarse previamente EEADR con la dirección 
;a la que se desee acceder cada vez.   
;La primera vez que arranque el programa se mostrará 11111111, ya que la dirección 0x00 de la
;EEPROM aún estará virgen y este es el valor "por defecto"

LEER		clrf		EEADR		;EAADR = 0, dirección 0 de la EEPROM
		bsf		STATUS,RP0 	;banco 0
		bsf		EECON1,RD	;activamos lectura
		bcf		STATUS,RP0	;volvemos al banco 0
		movf		EEDATA,W	;pasamos a W el dato leido
		return				;retorna de la llamada

GRABAR		movwf		EEDATA		;pasa a EEDATA el dato a escribir (estaba en W)
		clrf		EEADR		;EEADR = 0, dirección 0 de la EEPROM
		bsf		STATUS,RP0	;pasamos a banco 1
		bsf		EECON1,WREN	;permiso de escritura
		movlw		0x55		;secuencia de cargas en EECON2
		movwf		EECON2		;...
		movlw		0xAA		;...
		movwf		EECON2		;...
		bsf		EECON1,WR	;activamos escritura
ESPERA		btfss		EECON1,EEIF	;esperamos a que termine la escritura
		goto		ESPERA
		bcf		EECON1,EEIF	;ponemos a 0 bandera EEIF
		bcf		STATUS,RP0	;vuelve a banco 0
		return				;retorna de la llamada	
				




INICIO		bsf		STATUS,RP0	;selecciona banco 1 del área de datos
		clrf		TRISB		;configura PORTB todo salidas
		movlw		b'00011111'
		movwf		TRISA		;configura PORTA todo entradas
		bcf		STATUS,RP0	;vuelve a banco 0 del área de datos
				
;recupera de la EEPROM la ultimo dato guardado qque se mostraba en PORTB
;antes de apagar la alimentación la ultima vez

		call		LEER		;lee la EEPROM
		movwf		PORTB 		;muestra en PORTB el dato leido	

;programa principal

BUCLE		btfss		PORTA,0	;cambia a 0 RA0 ?
		goto		INC	;no ha brincado, RA0 = 0, goto INC  
		btfss		PORTA,1	;cambia a 0 RA1 ?
		goto		DEC	;no ha brincado, RA0 = 0, goto DEC 
		goto		BUCLE	;no ha habido 0 en RA0 ni RA1, goto bucle

INC		call		PAUSA	;pequeña pausa antirrebotes
		btfss		PORTA,0	;vuelve a 1 RA0 ?
		goto		INC	;NO, espera a soltar pulsador, goto INC
		incf		PORTB,F	;SÍ, incrementa PORTB
		call		PAUSA	;pequeña pausa antirebotes	
		movf		PORTB,W	;mueve a W el dato de PORTB
		call		GRABAR	;escribe en EEPROM dato de PORTB		
		goto		BUCLE

DEC		call		PAUSA	;pausa antirrebotes
		btfss		PORTA,1	;vuelve a 1 RA1 ?
		goto		DEC	;NO, espera a soltar pulsador, goto DEC
		decf		PORTB,F	;si, decrementa PORTB
		call		PAUSA	;pequeña pausa antirebotes	
		movf		PORTB,W
		call		GRABAR
		goto		BUCLE

;subrutina pausa de unos 767 microsegundos

PAUSA		decfsz		CONTA,F	;decrementa conta, guarda en conta (F) y brinca si es cero
		goto		PAUSA	;no es cero, vuelve a la etiqueta pausa
		return		;es cero, ha brincado, vuelvde de donde se la llamó

		end
