;*********************************************************************************************************
;	Septiembre 9, 2010
;	Base de tiempo de 1 segundo encendiendo LED durante 500ms.
; 	Revision 0.0
;	Con base al tutorial del foro se hacen las siguientes consideraciones:
; 	Lo interesante de usar interrupción es que con el micro se puede estar ejecutando cualquier tarea
;	y no ocupar este tiempo en un bucle de demora.
;	Para determinar la temporización se necesita el tiempo de un ciclo de instrucción, (1 us para XT de 4MHz)
;	el valor del divisor de frecuencia, que seleccionamos con los bits: PS2, PS2 y PS0 y el complemento del
;	valor cargado en TMR0, (255 - TMR0).
;	Se usa el PIC 16F628 por disponibilidad pero cambiar al 16F628A por recomendación del fabricante.
	list p=16F628
	#include P16F628.inc
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_OFF
;*********************************************************************************************************
;   Definicion de variables ****
;*********************************************************************************************************
	CBLOCK		H'20'		; Seleccionamos en la memoria RAM (GPR)
Contador					; Contador para detectar desbordes de TMR0.
ContLED						; Contador para encender LED durante 50ms.
W_Temp						; Registro para guardar temporalmente W.
STATUS_Temp					; Registro para guardar temporalmete STATUS
	ENDC
LED		equ	0				; Definimos Led como el bit cero de un registro, PORTB.
;*********************************************************************************************************
;   Inicio del Micro 
;*********************************************************************************************************
	Reset	org	0x00				; Aquí comienza el micro.
	goto	Inicio			; Salto a inicio de mi programa.
;*********************************************************************************************************
;**** Vector de Interrupcion ****
;*********************************************************************************************************
	org	0x04				; Atiendo Interrupcion.
	goto	Inicio_ISR
;*********************************************************************************************************
;  	Programa Principal 
;	Configuración de puertos 
;*********************************************************************************************************
	org	0x05				; Origen del código de programa.
Inicio		
	bsf	STATUS,RP0 			; Pasamos de Banco 0 a Banco 1.
	movlw	b'11111110'		; RB0 como salida.
	movwf	TRISB
	movlw	b'00000111'		; Se selecciona TMR0 y preescaler de 256.
	movwf	OPTION_REG
	bcf	STATUS,RP0			; Paso del Banco 1 al Banco 0
	bcf	PORTB,LED			; El LED comienza apagado.
	movlw	0x3D			; Cargamos 61 en TMR0 para lograr aprox. 50ms.
	movwf	TMR0
	clrf	Contador		; Iniciamos contadores.
	clrf	ContLED			
	movlw	b'10100000'		; Habilitamos GIE y T0IE (interrupción del TMR0)
	movwf	INTCON
;*********************************************************************************************************
;	Control de Led 
;*********************************************************************************************************
Bucle		
	nop						; Aqui pondremos nuestro programa ya que el micro puede ejecutar otra tarea
	goto	Bucle			; sin necesidad de utilizar tiempo en un bucle de demora.
;*********************************************************************************************************
; 	Rutina de servicio de Interrupcion.
;*********************************************************************************************************
;  Guardado de registro W y STATUS.
;*********************************************************************************************************
Inicio_ISR
	movwf	W_Temp			; Copiamos W a un registro Temporario.
	swapf	STATUS, W		; Invertimos los nibles del registro STATUS.
	movwf	STATUS_Temp		; Guardamos STATUS en un registro temporal.
;*********************************************************************************************************
;	Interrupción por TMR0 
;*********************************************************************************************************
ISR
	btfss	INTCON,T0IF		; Consultamos si es por TMR0.
	goto	Fin_ISR			; No, entonces restauramos valores.
	incf	Contador		; Si, Incrementamos contador
	movlw	.10				; Consultamos si se han producido 10 desbordes
	subwf	Contador,0		; para obtener t deseado.
	btfss	STATUS,Z		;
	goto	PulsoLED		; No 
	goto	ResetContador	; Si
; Agrego estas etiquetas para después modificar el programa.
PulsoLED
	goto	Actualizo_TMR0	; No, cargo TMR0.
ResetContador
	clrf	Contador		; Si, reseteo Contador y controlo Led.
	btfss	PORTB,LED		; Si esta apagado, prendo y viseversa.
	goto	Prendo_led
	bcf		PORTB,LED		; Apago Led.
Actualizo_TMR0				; Actualizo TMR0 para obtener una temporizacion de 50 ms.
	movlw	0x3D			; d'61'
	movwf	TMR0
	bcf		INTCON,T0IF		; Borro bandera de control de Interrupcion.
	goto	Fin_ISR			; Restauro valores.
Prendo_led
	bsf		PORTB,LED		; Prendo Led.
	goto	Actualizo_TMR0
; Restauramos los valores de W y STATUS.
Fin_ISR
	swapf	STATUS_Temp,W	; Invertimos lo nibles de STATUS_Temp.
	movwf	STATUS
	swapf	W_Temp, f		; Invertimos los nibles y lo guardamos en el mismo registro.
	swapf 	W_Temp,W		; Invertimos los nibles nuevamente y lo guardamos en W.
	retfie					; Salimos de interrupción.
;..........................................

	end


