LIST P=16F88
#INCLUDE <P16F88.INC>
;Estas son las palabras de configuracion necesarias para este microconlador
__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
#define VALOR_TMR 61
;dentro de esta directiva CBLOCK se especifican las variables con las que voy a trabajar en el programa
CBLOCK 0X20
SEG ; Variables que contienen los datos a mostrar
MIN
HOR
d1 ; Registro para los delays
d2
d3
d4
FLAGS ; Registro para flags, solo en uso bit0 : Contando
W_TEMP ; Registro para guardar W en interrupcion
STATUS_TEMP ; Registro para guardar STATUS en interrupcion
CUENTA ; Variable para que determina la cantidad de interrupciones a contar
ENDC
ORG 0x00 ; Vector de reset
GOTO CONFIGURA
ORG 0x04 ; Vector de interrupcion
GOTO INTERRUPCION
;-------------------- CONFIGURACION INICIAL --------------------------------------
CONFIGURA
BANKSEL OSCCON ; Configuracion del oscilador
MOVLW 0X60 ; RELOJ INTERNO 4MHZ
MOVWF OSCCON
BANKSEL TXSTA ; Configuracion de los pines
CLRF ANSEL ; Todos digitales
MOVLW B'11110000'
MOVWF TRISA ; PORTA = EEEE SSSS
CLRF TRISB ; PORTB = SSSS SSSS
BANKSEL TXREG
MOVLW B'00000111' ; Configuramos timer, preescaler 1:256 , asignado a TMR0, Clock del oscilador interno, pull-ups portb individuales
MOVWF OPTION_REG
BSF INTCON,GIE ; Habilito interrupciones globales
MOVLW B'1001' ; Valores iniciales
MOVWF SEG
MOVWF MIN
MOVWF HOR
MOVLW D'21' ; Cargo 21 que son las veces que deberia entrar a la interrupcion, en realidad son 20 veces
MOVWF CUENTA
CLRF FLAGS
;----------------------------INTERRUPCION--------------------------------------
INTERRUPCION
MOVWF W_TEMP ; Reguardo la informacion para que siga bien el otro programa, es decir guardo W y STATUS
SWAPF STATUS,W ; En W_TEMP y STATUS_TEMP , se usa SWAPF y MOVWF por que no modifican banderas del STATUS.
CLRF STATUS
MOVWF STATUS_TEMP
BTFSS INTCON,TMR0IF ; Pregunto si fue por el TMR0
GOTO SALIR_INT ; De no haber sido por el TMR0 entonces salga
BCF INTCON,TMR0IF ; Borro flag de interrupcion
MOVLW VALOR_TMR ; Cargo valor al timer
MOVWF TMR0
DECFSZ CUENTA,F ; Decremento y salto si es 0
GOTO SALIR_INT ; De no llegar a 0 salgo de la interrupcion
MOVLW D'21' ; Se lograron las 20 entradas? eso significa que paso 20 * 0.04992s , aproximadamente 1 segundo
MOVWF CUENTA ; Cargo el contador para que vuelva a contar 20 veces y comienzo a restar
; Procedo a restar
MOVLW B'1001' ; Cargo 9 en W
DECF SEG,F ; Decremento seg, si se paso de largo es decir quedo 0xFF salta
BTFSS SEG,7
GOTO SALIR_INT ; Termine de restar, salgo
MOVWF SEG ; 9 -> SEG
DECF MIN,F ; Decremento MIN, si se paso de largo salta
BTFSS MIN,7
GOTO SALIR_INT ; Termine de restar, salgo
MOVWF MIN ; 9 -> MIN
DECF HOR ; Decremento HOR
BTFSS HOR,7 ; Si NO se paso de largo salta y vuelve
GOTO SALIR_INT ; No se paso de vuelta, asi que salgo
MOVWF HOR ; 9 -> HOR
BCF FLAGS,0 ; Si llego aca es por que son todos 999 , en resumen estaria haciendo uno de mas.
BCF INTCON,TMR0IE ; Asi que quito las interrupciones por que ya se completo lo que queria, y habilito nuevamente los botones START, INC y DEC
SALIR_INT
SWAPF STATUS_TEMP,W ; Dejo STATUS como estaba antes de entrar a la interrupcion
MOVWF STATUS
SWAPF W_TEMP,F ; Dejo W como estaba antes de entrar a la interrupcion
SWAPF W_TEMP,W
RETFIE
;--------------------------PROGRAMA PRINCIPAL----------------------------------
INICIO
BTFSC FLAGS,0 ;Pregunto si esta corriendo, si esta corriendo inhabilito los botones de incrementar, decrementar y START
GOTO INICIO2
CALL B_INCREMENTAR
CALL B_DECREMENTAR
CALL B_START
INICIO2
CALL B_RESET ; Mientras este corriendo solo habilita a que se presione Reset y que se muestre en los displays
CALL MUESTRA
GOTO INICIO
;--------------------------------RUTINAS---------------------------------------
B_INCREMENTAR
BTFSC PORTA,0 ; Compruebo boton
RETURN
CALL DELAY
BTFSC PORTA,0
RETURN
INCF SEG,F ; SEG = SEG + 1
MOVLW B'1010' ; SEG > 9 ?
SUBWF SEG,W
BTFSS STATUS,Z
RETURN ; NO es mayor a 9, vuelve
CLRF SEG ; Si es mayor a 9, SEG = 0 y MIN = MIN+1
INCF MIN,F
MOVLW B'1010'
SUBWF MIN,W ; MIN >9 ?
BTFSS STATUS,Z
RETURN ; NO, vuelve
CLRF MIN ; SI, MIN = 0 y HOR = HOR+1
INCF HOR,F
MOVLW B'1010'
SUBWF HOR,W ; HOR > 9?
BTFSC STATUS,Z
CLRF HOR ; SI, HOR = 0
RETURN ; NO, vuelvo
B_DECREMENTAR
BTFSC PORTA,1 ; Compruebo boton
RETURN
CALL DELAY
BTFSC PORTA,1
RETURN
MOVLW B'1001' ; Cargo 9 en W
DECF SEG,F ; Decremento seg, si se paso de largo es decir quedo 0xFF salta
BTFSS SEG,7
RETURN
MOVWF SEG ; 9 -> SEG
DECF MIN,F ; Decremento MIN, si se paso de largo salta
BTFSS MIN,7
RETURN
MOVWF MIN ; 9 -> MIN
DECF HOR ; Decremento HOR
BTFSC HOR,7 ; Si NO se paso de largo salta y vuelve
MOVWF HOR ; Si se paso de largo le pongo un 9 -> HOR
RETURN
B_START
BTFSC PORTA,2 ; Compruebo boton
RETURN
CALL DELAY
BTFSC PORTA,2
RETURN
; Antes de comenzar deberia asegurarme que los valores SEG,HOR y MIN sean distinto de 0, sino no tiene sentido contar 0.
MOVF HOR,W ; W = HOR
IORWF MIN,W ; W = HOR | MIN
IORWF SEG,W ; W = HOR | MIN | SEG ; Si hay alguno con algun valor, esto es imposible que de 0
BTFSC STATUS,Z ; Son todos 0???
RETURN ; SI, vuelve y no arranca el programa
; NO, continua y comieza a funcionar el programa
BCF INTCON,TMR0IF ; Borro flag de interrupcion
MOVLW VALOR_TMR ; Cargo valor al timer
MOVWF TMR0
BSF INTCON,TMR0IE ; Habilito las interrupciones del TMR0
BSF FLAGS,0 ; Pongo a 1 mi flag, indicando que comenzo el proceso
RETURN
B_RESET
BTFSC PORTA,3 ; Compruebo boton
RETURN
CALL DELAY
BTFSC PORTA,3
RETURN
BCF INTCON,TMR0IE ; Apago la interrupcion del TMR0
MOVLW B'1001' ; Vuelvo todos los valores a 9
MOVWF SEG
MOVWF MIN
MOVWF HOR
BCF FLAGS,0 ; Pongo a 0 mi flag, indicando que esta parado
RETURN
MUESTRA
MOVF SEG,W
MOVWF PORTB ; Valor de unidades
BSF PORTA,4 ; Activo catodo de unidades
CALL ESPERO ; Delay
BCF PORTA,4 ; Desactivo para cambiar de dato
MOVF MIN,W ; Valor de decenas
MOVWF PORTB
BSF PORTA,5 ; Activo catodo decenas
CALL ESPERO
BCF PORTA,5 ; Desactivo decenas
MOVF HOR,W
MOVWF PORTB ; Cargo centenas
BSF PORTA,6 ; Activo catodo centenas
CALL ESPERO
BCF PORTA,6 ; Desactivo centenas
RETURN
; ----------------------- RUTINAS AUXILIARES - DELAYS----------------------------------------------------
ESPERO
movlw 0x03
movwf d1
movlw 0x18
movwf d2
movlw 0x02
movwf d3
Delay_1
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_1
RETURN
DELAY
movlw 0xCF
movwf d1
movlw 0x08
movwf d2
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_0
RETURN