Mira, te hice un programa un tanto sencillo para mostrarte como debe modificarse tu programa.
; Este programa lo único que hace es contar desde 20 minutos hasta 0,
; es decir, no puede ajustarse, a menos que se edite el programa.
LIST P=16F84A
INCLUDE "P16F84A.INC"
CBLOCK 0CH
Reg_50ms, Tiempo_H, Tiempo_L
ENDC
; Ojo: En vez de usar una variable llamada TIEMPO debes usar dos:
; - Una para almacenar el byte alto de la cantidad de segundos,
; llamada Tiempo_H.
; - Una para almacenar el byte bajo de la cantidad de segundos,
; llamada Tiempo_L.
;
; ¿Por qué 2 bytes? Pues porque para temporizar hasta 20 minutos se
; requieren hasta 20 x 60 = 1200 segundos. La cantidad 1200 se representa
; con mínimo 2 bytes.
#DEFINE Alarma PORTB,0
ORG 00H
goto Inicio
ORG 04H
goto Interrupcion
Inicio
bcf Alarma
bsf STATUS,RP0
movlw b'11000111'
movwf OPTION_REG
bcf Alarma
bcf STATUS,RP0
call LCD_Inicializa
movlw high(.1200) ; Carga el byte alto del tiempo en la variable
movwf Tiempo_H ; Tiempo_H.
movlw low(.1200) ; Carga el byte bajo del tiempo en la variable
movwf Tiempo_L ; Tiempo_L.
call Visualiza_Tiempo ; Visualiza el tiempo en la pantalla.
movlw .20 ; Se prepara para temporizar.
movwf Reg_50ms
movlw .60
movwf TMR0
bcf INTCON,T0IF
bsf INTCON,T0IE
bsf INTCON,GIE ; Habilita interrupciones.
Ciclo
goto Ciclo
; Rutina de servicio a la interrupción.
Interrupcion
movlw .60
movwf TMR0 ; Recarga el TMR0.
decfsz Reg_50ms ; ¿Ya pasó 1 segundo?
goto Fin_Interrupcion
movlw .20 ; Sí, entonces recarga el registro.
movwf Reg_50ms
; Ojo: Aquí se va a realizar el decremento del tiempo, pero
; es un decremento de 16 bits.
decf Tiempo_L,F ; Decrementa en 1 el byte bajo.
movlw 0xFF
subwf Tiempo_L,W
btfsc STATUS,Z ; ¿El resultado es negativo?
decf Tiempo_H,F ; Sí, entonces decrementa en 1 el byte alto.
call Visualiza_Tiempo ; Visualiza el tiempo en la pantalla.
; Atención: Anteriormente sólo decrementamos el tiempo, pero NO
; verificamos si llegó al valor 0. Aquí se realiza esto. Si los
; dos bytes del tiempo valen 0 significa que el tiempo terminó.
movf Tiempo_H,F
btfss STATUS,Z ; ¿Vale 0 el byte alto?
goto Fin_Interrupcion ; No, pues sale de la interrupción.
movf Tiempo_L,F
btfss STATUS,Z ; ¿Vale 0 el byte bajo?
goto Fin_Interrupcion ; No, pues sale de la interrupción.
; Llegamos aquí porque los dos bytes valen 0, es decir, el tiempo terminó.
bsf Alarma ; Activa la alarma
call Retardo_2s ; durante un corto tiempo.
bcf Alarma
bcf INTCON,T0IE ; Prohibe la interrupción del TMR0
; Para que detener el conteo.
Fin_Interrupcion
bcf INTCON,T0IF ; Borra la bandera de interrupción
retfie ; y retorna.
; Subrutina Visualiza_Tiempo.
;
; Observa que antes sólo se hacía:
;
; movf TIEMPO,W
; call MinutosSegundos
;
; Pues ahora el tiempo es de dos bytes y debe hacerse como sigue.
Visualiza_Tiempo
call LCD_Borra
; Debes hacerlo así para que funcione. La rutina MinutosSegundos
; modificada maneja los registros MinutosSegundos_TiempoH y
; MinutosSegundos_TiempoL.
movf Tiempo_H,W
movwf MinutosSegundos_TiempoH
movf Tiempo_L,W
movwf MinutosSegundos_TiempoL
call MinutosSegundos ; Convierte de segundos a minutos y
; segundos.
movf Minutos,W
call BIN_BCD
call LCD_ByteCompleto
movlw ':'
call LCD_Caracter
movf Segundos,W
call BIN_BCD
call LCD_ByteCompleto
return
; La rutina BIN_BCD yo la hice, pero puedes usar la que tú tienes.
; Lo que pasa es que la hice porque no la tengo.
; Insisto, puedes usar la que tú tienes.
BIN_BCD
CBLOCK
Unidades, Decenas, Centenas
ENDC
movwf Unidades
clrf Decenas
clrf Centenas
BIN_BCD_Resta10
movlw .10
subwf Unidades,F
btfss STATUS,C
goto Fin_BIN_BCD
incf Decenas,F
movlw .10
subwf Decenas,W
btfss STATUS,C
goto BIN_BCD_Resta10
clrf Decenas
incf Centenas,F
goto BIN_BCD_Resta10
Fin_BIN_BCD
movlw .10
addwf Unidades,F
movf Unidades,W
swapf Decenas,F
iorwf Decenas,W
swapf Decenas,F
return
; Aquí está la subrutina MinutosSegundos modificada para manejar
; números de 2 bytes. Ésta sí úsala en lugar de la otra.
MinutosSegundos
CBLOCK
Segundos, Minutos
MinutosSegundos_TiempoH
MinutosSegundos_TiempoL
ENDC
clrf Minutos ; Borra los minutos.
; Le resta 60 al tiempo que está almacenado en las variables
; MinutosSegundos_TiempoH y MinutosSegundos_TiempoL.
MinutosSegundos_Resta60
movlw .60
subwf MinutosSegundos_TiempoL,F ; Resta 60 del byte bajo.
btfss STATUS,C ; ¿Es negativo?
decf MinutosSegundos_TiempoH,F ; Sí, entonces decrementa en
; 1 el byte alto.
btfsc MinutosSegundos_TiempoH,7 ; ¿El resultado es negativo?
goto Fin_MinutosSegundos ; Sí, pues ya terminamos de convertir.
incf Minutos,F ; Incrementa en 1 la cantidad de minutos.
goto MinutosSegundos_Resta60 ; Sigue revisando si hay más minutos.
Fin_MinutosSegundos
movlw .60 ; Le suma 60 a la cantidad de tiempo ya que
; previamente se le restó 60 y el resultado
; fue negativo.
addwf MinutosSegundos_TiempoL,W
movwf Segundos
return
INCLUDE "LCD_4BIT.INC"
INCLUDE "RETARDOS.INC"
END
Bien, en el programa podrás darte cuenta que cargué un valor en las variables Tiempo_H y Tiempo_L:
movlw high(.1200) ; Carga el byte alto del tiempo en la variable
movwf Tiempo_H ; Tiempo_H.
movlw low(.1200) ; Carga el byte bajo del tiempo en la variable
movwf Tiempo_L ; Tiempo_L.
Pero tú en tu programa quieres darle incrementos. Estos incrementos deben ser ahora un tanto diferentes:
; Incrementar la variable de tiempo.
movlw IncrementoTiempo ; Le suma un valor de incremento al
addwf Tiempo_L,F ; byte bajo.
btfsc STATUS,C ; ¿Hubo acarreo?
incf Tiempo_H,F ; Sí, entonces se lo suma al byte alto.
Edito -------------------
Te mandé al correo la carpeta con el programa y el circuito en proteus.
Nos vemos.