Hola:
Quiero hacer un temporizador para una insoladora. Me he puesto con el famoso PIC16F84A pero tiene sus limitaciones.
(http://www.pic16f84a.org/images/stories/proteus/Fig1802_Cuadradas_y_otros.GIF)
Usa vez que lo usas sólo puedes ejecutar la cuenta atrás como máximo 4:15. (4 minutos, 15 segundos). Usa el Timer de 8 Bits. He pensarlo en adaptarlo del 16F84A al 16F88 ya que tiene un Timer de 16 bit que significa mejor tiempo.
Quiero saber ya que saben mucho más que yo en temas de temporizadores, si el Timer de 16 bits puede lograr algo. Por ejemplo: Quiero saber cuánto tiempo máximo me deja poner en el LCD y que funcione. Prefiero algo así: 99:99. Con 20 minutos está bien. Que lo vaya a usar para insoladora es mucho tiempo, el mismo circuito lo montaré para otras cosas, por eso quiero saber lo del temporizador.
Estaba pensando es unsar un reloj-calendario en tiempo real llamado DS1307. Muy preciso, pero lleva más electrónica, más caro y complicado de usar en asm.
; Programa de control para un temporizador digital de precisión. La programación del tiempo
; de temporización se realiza mediante dos pulsadores: "AJUSTE" y "ON/INCREM". Funcionamiento:
; - En estado de reposo la salida del temporizador está apagada y el pantalla aparece el
; tiempo deseado para la próxima temporización.
; - Si se pulsa "ON/INCREM" comienza la temporización.
; - Cuando acaba la temporización pasa otra vez a reposo.
; - Si pulsa "AJUSTE" antes que haya acabado el tiempo de temporización actúa como pulsador
; de paro: interrumpe la temporización, apaga la carga y pasa al estado de reposo.
;
; Para ajustar la temporización al tiempo deseado.
; - Pulsa "AJUSTE" y ajusta el tiempo deseado mediante el pulsador "ON/INCREM".
; - Se vuelve a pulsar "AJUSTE" y pasa a modo de reposo.
;
; Al apagar el sistema debe conservar el tiempo de temporización deseado para la próxima vez
; que se encienda.
;
; ZONA DE DATOS **********************************************************************
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
CBLOCK 0x0C
TiempoDeseado ; El tiempo deseado de temporización.
Tiempo ; Tiempo que resta de temporización.
FlagsModos ; Guarda los flags con los diferentes
ENDC ; modos de funcionamiento.
ORG 0x2100 ; Corresponde a la dirección 0 de la zona
; EEPROM de datos. Aquí se va a guardar el
DE 0x00 ; tiempo de temporización deseado.
#DEFINE F_Temporizador_ON FlagsModos,2
#DEFINE F_Temporizador_Ajuste FlagsModos,1
#DEFINE F_Temporizador_OFF FlagsModos,0
#DEFINE SalidaTemporizador PORTB,1 ; Salida donde se conecta la carga.
#DEFINE Zumbador PORTB,2 ; Salida donde se conecta el zumbador.
#DEFINE AjustePulsador PORTB,7 ; Los pulsadores están conectados a estas
#DEFINE IncrementarPulsador PORTB,6 ; líneas del Puerto B.
; ZONA DE CÓDIGOS ********************************************************************
ORG 0
goto Inicio
ORG 4
goto ServicioInterrupcion
Mensajes
addwf PCL,F
Mensaje_ON
DT " En MARCHA", 0x00
Mensaje_Ajuste
DT "Tiempo deseado:", 0x00
Mensaje_OFF
DT " PARADO", 0x00
; Instrucciones de inicialización. ------------------------------------------------------
;
Inicio
call LCD_Inicializa
bsf STATUS,RP0
movlw b'10000111' ; Prescaler de 256 asignado al TMR0.
movwf OPTION_REG
bsf AjustePulsador ; Configurados como entradas.
bsf IncrementarPulsador
bcf SalidaTemporizador ; Configurados como salidas.
bcf Zumbador
bcf STATUS,RP0
clrw ; Lee la posición 0x00 de memoria EEPROM de datos
call EEPROM_LeeDato ; donde se guarda el tiempo deseado de la última vez
movwf TiempoDeseado ; que se ajustó.
call ModoTemporizador_OFF ; Modo de funcionamiento inicial.
movlw b'10001000' ; Activa interrupciones RBI.
movwf INTCON
Principal
goto Principal
; Subrutina "ServicioInterrupcion" ------------------------------------------------------
;
; Detecta qué ha producido la interrupción y ejecuta la subrutina de atención correspondiente.
ServicioInterrupcion
btfsc INTCON,T0IF
call Temporizador
btfss INTCON,RBIF ; Si es una interrupción RBI lee los pulsadores.
goto FinInterrupcion
btfss AjustePulsador ; ¿Está presionado el pulsador de "AJUSTE"?.
call CambiarModo ; Sí, pues salta a la subrutina correspondiente.
btfsc IncrementarPulsador ; ¿Pulsado "ON/INCREM"?.
goto FinInterrupcion ; No, pues salta al final y sale.
;
call Retardo_20ms ; Espera que se estabilice el nivel de tensión.
btfsc IncrementarPulsador ; Si es un rebote del pulsador "ON/INCREM" sale fuera.
goto FinInterrupcion
btfsc F_Temporizador_OFF ; ¿Estaba en reposo cuando pulsó "ON/INCREM"?
call ModoTemporizador_ON ; Sí, pues comienza la temporización.
btfsc F_Temporizador_Ajuste ; ¿Estaba ajustando tiempo?
call IncrementarTiempoDeseado ; Sí, pues pasa a incrementar el tiempo deseado.
FinInterrupcion
bcf INTCON,RBIF ; Limpia los flags de reconocimiento.
bcf INTCON,T0IF
retfie
; Subrutinas "CambiarModo" y todas las de MODO de funcionamiento ------------------------
;
; Subrutina de atención a la interrupción producida al presionar el pulsador "AJUSTE" que
; cambia el modo de funcionamiento.
; Hay identificados tres modos de funcionamiento que se diferencian mediante los tres flags:
; A) Modo "Temporizador_OFF" o estado inicial. A él se pasa en el estado inicial cada vez
; que termina una temporización o cuando se aborta la temporización sin esperar a que
; finalice. Reconocido por el flag F_Temporizador_OFF, bit 0 del registro FlagsModos.
; una temporización o cada vez que se aborta la temporización sin esperar a que finalice.
; B) Modo "Temporizador_Ajuste", donde se ajusta la temporización deseada cuando funcione
; como temporizador. Reconocido por el flag F_Temporizador_Ajuste, bit 1 del FlagsModos.
; C) Modo "Temporizador_ON", la salida está activada mientras dure la temporización.
; Reconocido por el flag F_Temporización_ON, que es el bit 2 del registro FlagsModos.
;
; El programa consigue que esté activado uno sólo de los flags anteriores.
; El contenido del registro (FlagsModos) diferencia los siguientes modos de funcionamiento:
; - (FlagsModos)=b'00000001'. Está en el modo "Temporizador_OFF", en reposo.
; - (FlagsModos)=b'00000010'. Está en el modo "Temporizador_Ajuste", ajustando tiempo deseado.
; - (FlagsModos)=b'00000100'. Está en el modo "Temporizador_ON", activa la carga y temporizador.
;
; Al pulsar "AJUSTE" pueden darse tres casos:
; - Si estaba en modo "Temporizador_OFF", pasa a modo "Temporizador_Ajuste".
; - Si estaba en modo "Temporizador_Ajuste", pasa a modo "Temporizador_OFF", pero antes salva
; el tiempo de temporización deseado en la EEPROM de datos.
; - Si estaba en modo "Temporizador_ON", pasa a modo "Temporizador_OFF". (Interrumpe la
; temporización).
CambiarModo
call PitidoCorto ; Cada vez que pulsa origina un pitido.
btfsc AjustePulsador ; Si es un rebote sale fuera.
goto EsperaDejePulsar
btfsc F_Temporizador_OFF ; ¿Está en reposo?
goto ModoTemporizador_Ajuste ; Sí, pues pasa a ajustar la temporización.
btfss F_Temporizador_Ajuste ; ¿Está ajustando?
goto ModoTemporizador_OFF ; No, pues pasa a reposo.
; Sí, pues antes de pasar a reposo salva en la
clrw ; posición 00h de memoria EEPROM de datos el tiempo
movwf EEADR ; de temporización deseado. Se conserva aunque se
movf TiempoDeseado,W ; apague la alimentación.
call EEPROM_EscribeDato
ModoTemporizador_OFF
bcf SalidaTemporizador ; Apaga la carga y resetea tiempo deseado.
call Pitido
movlw b'00000001' ; Actualiza el registro FlagsModos pasando al
movwf FlagsModos ; modo inicial "Temporizador_OFF".
bcf INTCON,T0IE ; Prohíbe las interrupciones del TMR0.
movf TiempoDeseado,W ; Repone otra vez el tiempo que se desea para la
movwf Tiempo ; próxima temporización.
call LCD_Borra ; Borra la pantalla.
movlw Mensaje_OFF ; En pantalla el mensaje correspondiente.
goto FinCambiarModo
ModoTemporizador_Ajuste
bcf SalidaTemporizador ; Apaga la carga
movlw b'00000010' ; Actualiza el registro FlagsModos pasando al
movwf FlagsModos ; modo "Temporizador_Ajuste".
clrf Tiempo ; Resetea el tiempo.
clrf TiempoDeseado
bcf INTCON,T0IE ; Prohíbe las interrupciones del TMR0.
call LCD_Borra
movlw Mensaje_Ajuste ; En pantalla el mensaje correspondiente.
goto FinCambiarModo
ModoTemporizador_ON
movf TiempoDeseado,W ; Si el tiempo deseado es cero pasa a modo
btfsc STATUS,Z ; de trabajo "Temporizador_OFF".
goto ModoTemporizador_OFF
movwf Tiempo
call PitidoCorto
movlw b'00000100' ; Actualiza el registro FlagsModos pasando al
movwf FlagsModos ; modo "Temporizador_ON".
movlw TMR0_Carga50ms ; Carga el TMR0.
movwf TMR0
movlw CARGA_1s ; Y el registro cuyo decremento contará los
movwf Registro50ms ; segundos.
bsf INTCON,T0IE ; Autoriza las interrupciones de TMR0.
call LCD_Borra
bsf SalidaTemporizador ; Enciende la carga.
movlw Mensaje_ON ; En pantalla el mensaje correspondiente.
FinCambiarModo
call LCD_Mensaje
call VisualizaTiempo
EsperaDejePulsar
btfss AjustePulsador ; Espera deje de pulsar.
goto EsperaDejePulsar
return
; Subrutina "Temporizador" ----------------------------------------------------------------
;
; Esta subrutina va decrementando el tiempo de temporización y visualizándolo en la pantalla.
; Se ejecuta debido a la petición de interrupción del Timer 0 cada 50 ms exactos, comprobado
; experimentalmente con la ventana "Stopwatch" del simulador del MPLAB.
CBLOCK
Registro50ms ; Guarda los incrementos cada 50 ms.
ENDC
TMR0_Carga50ms EQU d'256'-d'195' ; Para conseguir la interrupción cada 50 ms.
CARGA_1s EQU d'20' ; Leerá cada segundo (20 x 50ms = 1000 ms).
Temporizador
call Retardo_50micros ; Ajuste fino de 71 microsegundos para
call Retardo_20micros ; ajustar a 50 milisegundos exactos.
nop
movlw TMR0_Carga50ms ; Carga el Timer0.
movwf TMR0
decfsz Registro50ms,F ; Decrementa el contador.
goto FinTemporizador ; No ha pasado 1 segundo y por tanto sale.
movlw CARGA_1s ; Repone el contador nuevamente.
movwf Registro50ms
btfss F_Temporizador_ON ; Si no está en modo "Temporizador_ON" sale
goto FinTemporizador ; fuera.
decfsz Tiempo,F
goto VisualizaContador ; Visualiza el tiempo restante.
bcf SalidaTemporizador ; Apaga la salida
call VisualizaTiempo ; Visualiza cero segundos en la pantalla.
call Pitido ; Tres pitidos indican final de la temporización.
call Retardo_500ms
call Pitido
call Retardo_500ms
call PitidoLargo
call Retardo_500ms
call ModoTemporizador_OFF ; Acabó la temporización.
goto FinTemporizador
VisualizaContador
call VisualizaTiempo
FinTemporizador
return
; Subrutina "VisualizaTiempo" -----------------------------------------------------------------
;
; Visualiza el registro Tiempo en formato "Minutos:Segundos". Así por ejemplo, si
; (Tiempo)=124 segundos en la segunda línea de la pantalla visualiza " 2:04", ya que 124
; segundos es igual a 2 minutos más 4 segundos.
;
VisualizaTiempo
movlw .5 ; Para centrar visualización en la
call LCD_PosicionLinea2 ; segunda línea.
movf Tiempo,W ; Convierte el tiempo deseado (y expresado sólo en
call MinutosSegundos ; segundos) a minutos y segundos.
movf TemporizadorMinutos,W ; Visualiza los minutos.
call BIN_a_BCD ; Lo pasa a BCD.
call LCD_Byte
movlw ':' ; Visualiza dos puntos.
call LCD_Caracter
movf TemporizadorSegundos,W ; Visualiza los segundos.
call BIN_a_BCD ; Lo pasa a BCD.
goto LCD_ByteCompleto
return
; Subrutina "MinutosSegundos" -----------------------------------------------------------
;
; Una cantidad expresada exclusivamente en segundos y contenida en el registro W es
; convertida a minutos y segundos. El resultado se guarda en dos posiciones de memoria
; llamadas TemporizadorMinutos y TemporizadorSegundos.
;
; El máximo número a convertir será el 255 que es el máximo valor que puede adquirir el
; número binario de entrada de 8 bits. (255 segundos = 4 minutos + 15 segundos)
;
; El procedimiento utilizado es mediante restas de 60 tal como se explica en el siguiente
; ejemplo que trata de la conversión del 124 segundos a minutos y segundos.
; 124 segundos = 2 minutos + 4 segundos.
;
; Minutos Segundos ¿(Segundos)<60?
; ------- -------- ------------------------------------------------
; 0 124 NO. Resta 60 a (Segundos) e incrementa (Minutos).
; 1 64 NO. Resta 60 e (Segundos) e incrementa (Minutos).
; 2 4 Sí, se acabó.
;
; Entrada: En el registro W el número de segundos a convertir.
; Salidas: En (TemporizadorMinutos) y (TemporizadorSegundos) el resultado.
CBLOCK
TemporizadorMinutos
TemporizadorSegundos
ENDC
;
MinutosSegundos
movwf TemporizadorSegundos ; Carga el número de segundos a convertir.
clrf TemporizadorMinutos ; Carga los registros con el resultado inicial.
Resta60
movlw .60 ; Resta 60 en cada pasada.
subwf TemporizadorSegundos,W ; (W)=(TemporizadorSegundos)-60.
btfss STATUS,C ; ¿(W) positivo?, ¿(TemporizadorSegundos)>=60?.
goto FinMinutosSegundos ; No, es menor de 60. Acabó.
movwf TemporizadorSegundos ; Sí, por tanto, recupera lo que queda por restar.
incf TemporizadorMinutos,F ; Incrementa los minutos.
goto Resta60 ; Y vuelve a dar otra pasada.
FinMinutosSegundos
return
; Subrutina "IncrementarTiempoDeseado" --------------------------------------------------
;
; Subrutina de atención a la interrupción por cambio de la línea RB6 a la cual se ha
; conectado el pulsador "INCREMENTAR".
; Estando en el modo "Temporizador_Ajustar" incrementa el valor del tiempo deseado
; expresado en segundos en intervalos de 5 segundos y hasta un máximo de 255 segundos.
;
SALTO_INCR EQU .5
IncrementarTiempoDeseado
call PitidoCorto ; Cada vez que pulsa se oye un pitido.
movlw SALTO_INCR ; Incrementa el tiempo deseado de temporización
addwf Tiempo,F ; saltos de SALTO_INCR segundos.
btfsc STATUS,C ; Si pasa del valor máximo lo inicializa.
clrf Tiempo
call VisualizaTiempo ; Visualiza mientras espera que deje de pulsar.
call Retardo_200ms
btfss IncrementarPulsador ; Mientras permanezca pulsado,
goto IncrementarTiempoDeseado ; incrementa el dígito.
movf Tiempo,W ; Actualiza el tiempo deseado.
movwf TiempoDeseado ; Este es el tiempo deseado.
return
; Subrutinas "PitidoLargo", "Pitido" y "PitidoCorto" -------------------------------------
;
PitidoLargo
bsf Zumbador
call Retardo_500ms
Pitido
bsf Zumbador
call Retardo_200ms
PitidoCorto
bsf Zumbador
call Retardo_20ms
bcf Zumbador
return
;
INCLUDE <RETARDOS.INC>
INCLUDE <BIN_BCD.INC>
INCLUDE <LCD_4BIT.INC>
INCLUDE <LCD_MENS.INC>
INCLUDE <EEPROM.INC>
END
Un cordial saludo.
Hola, Meta:
Una pregunta: ¿Por qué dices que sólo puedes contar de 4:15 para abajo?
Espero tu respuesta. Saludos.
¡Ups!... EDITO -------------------
Acabo de leer el por qué sólo 4:15, pero eso no es por la capacidad del timer, sino porque las operaciones deben ser de 16 bits. Es decir, la rutina para convertir de binario a BCD deben manejar números de 16 bits. El decremento que realizas (decfsz TIEMPO,F) deberá ser ahora un decremento de 16 bits.
Dame un poco de tiempo y te muestro unas rutinas para solucionar esto.
Nos vemos luego, si Dios quiere.
Buenas:
Lo leí en el libro www.pic16f84a.org o en las explicaciones de los ejemplos. No se podía por algo de que sólo era de 2556 bytes. No lo encuentro ahora pero me quedé con el problema. Por eso pregunto si con el timer de 16 bits del 16F88 es posible hacerlo.
Te voy a pasar por correo el ejemplo.
Saludo.
Edito:
Acaba de leer tu mensaje editado. No recordaba que era lo que dijiste, pensé que era lo del TIMER. Escoja el tiempo que desees mi muy distinguido amigo.
Por lo que cuentas hay que hacerlos por lo menos de 32 bit para que te haga caso. Modificar la librería esa.
Muchas gracias.
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.
Muchas gracias por la ayuda y si funciona lo que me enviaste.
Una curiosidad que tengo y no sabía.
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.
La parte esa de (.1200) no sabía que se puede cargar más de .256. Lo de los paréntesis, encontré mirando la ayuda del MPLAB v8.56 en Arithmetic Operators and Precedence. No he visto la palabra high(.1200) en ningún sitio. No se como lograste guardar .1200 por la cara cuando aguanta sólo .256 en decimal.
Vi tu ejemplo y me quedo liado todavía. Quiero implementarlo al ejemplo quete envié. Estoy leyendo paso a paso para entenderlo e implementarlo, que sea capaz de meter el tiempo que me de la gana desde el PIC con los botones, a parte de ello, poner 20 minutos que lograste o más tiempo si es posible. La librería del BCD_BIN te viene incluida.
Meta:
En realidad no cargo 1200, no se puede porque en un byte el máximo es 255.
Sucede lo siguiente:
Supongamos que tenemos un número, por ejemplo, 325 (decimal). Este número en hexadecimal se representa como: 0x0145.
El operador high retorna el byte alto de ese valor. Entonces, poner:
movlw high(.325)
Es lo mismo que poner:
movlw 0x01
El operador low retorna el byte bajo de ese valor. Entonces, poner:
movlw low(.325)
Es lo mismo qe poner:
movlw 0x45
La ventaja está en que la conversión de decimal a hexadecimal la hace el propio ensamblador; tú no tienes que hacerla.
Cualquier duda me avisas.
Saludos
Gracias por la explicación.
No me sale mucho implementar tu código al que original que te envié. ¿Puedes lograrlo? Prefiero que si lo haces eso de mostrar 99 minutos como máximo, por poner un ejemplo, puedes argumentarlo.
Se te da mucho el ensamblador, si que tienes experiencias.
Desde que todo me funcione bien, compraré los componentes del PCB, LCD, tubos actínicos, etc. La base lo meteré dentro de un escaner viejo grande que me regalaron. Ya pasaré fotos cuando lo acabe.
Meta:
Te envié al correo el programa modificado.
Eso es todo. Saludos y buen día.
Hello:
Muy bueno a estudiarlo paso a paso a ver que hiciste exactamente. No se como el autor no lo pudo hacer.
Haciendo pruebas me sorprende que funcione en muy bien en poco tiempo.
(http://www.subeimagenes.com/img/lcd-bien-1875.jpg)
Probado hasta donde puede llegar el temporizador. ¿Hasta dónde llega? ¿99:99? Ocurre cosas raras como esto.
Se me puso así: 045:37:015 por poner un ejemplo. Hice pruebas otra vez y ya no pasa nada.
Voy a mirar las librerías a ver exactamente que has tocado, no creo que sea tan engorroso como el ejemplo de arriba.
Muchísimas gracias por la ayuda, ahora si voy a montar la insoladora.
Hola:
Me dió por hacer el ejemplo del 16F84A adaptarlo al PIC16F88. No me funciona el LCD con el proteus 7.7 SP2. Dejo en descargar los ejemplos compeltos en asm del MPLAB y el proteus.
Descargar (https://sites.google.com/site/metaconta/winpic800/Temporizador_Insoladora_16F88.zip?attredirects=0&d=1)
Un cordial saludo.
Hola:
He estado comprobando en pareja con el 16F88 y 16F84A. Son por temas de interrupciones y hay que corregirlo, parece fácil y llevo tiempo.
Capturas:
* Ver paso 1 (http://www.subeimagenes.com/img/paso-1-9983.png) - Enciende los PIC.
* Ver paso 2 (http://www.subeimagenes.com/img/paso-2-9985.png) - Pulsa el botón RB7. Por ahora las intrrupciones son iguales.
* Ver paso 3 (http://www.subeimagenes.com/img/paso-3-9986.png) - Pulsa el botón RB6. Sigue con los mismos bits.
* Ver paso 4 (http://www.subeimagenes.com/img/paso-4-9987.png) - Pulsa RB7. El bits RBIE del 16F88 está en 0 y del 16F84A en 1.
* Ver paso 5 (http://www.subeimagenes.com/img/paso-5-9988.png) - Con RB7 para el 16F84A cuenta atrás bien, el 16F88 no puede contar.
Eso es todo lo que he descubierto. Voy a investigar si es posible arreglar estas cosas. Cualquier auyda es bien recibida.
Saludo.
Hola a todos,
yo también me estoy peleando con el temporizador de ese libro.
Tokes o Meta, me podéis pasar el código original modificado para que pueda contar más tiempo? Yo solo no consigo adaptarlo.
Gracias de antemano.
Cuando pueda te lo paso.
Oki, espero tu mensaje.
Gracias :rolleyes:
Hola amigos estoy intentando hacer el temporizador pero soy principiante en asm. Agradeceria me manden el asm y el hex de este temporizador.
Muchas gracias por su tiempo y Sal2....
hola me pueden paras el codigo hex del temporisador yo tengo uno con atmega
solo qe no tengo el grabador si desean subo el proyecto completo gracias ;-)
hola alguien me puede ayudar y principiante en pic quiero hacer un temporizador programable a 24 horas que pongas el tiempo que quieras prenda un led y al terminar ese tiempo lo apague, vi los ejemplos de un temporizador pero solo llega a 4 min 15 seg espero puedan ayudarme dejo el ejemplo
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
CBLOCK 0x0C
TiempoDeseado
Tiempo
FlagsModo
ENDC
ORG 0x2100
DE 0x00
#DEFINE F_Temporizador_ON FlagsModo,2
#DEFINE F_Temporizador_Ajuste FlagsModo,1
#DEFINE F_Temporizador_OFF FlagsModo,0
#DEFINE SalidaTemporizador PORTB,1
#DEFINE Zumbador PORTB,2
#DEFINE AjustePulsador PORTB,7
#DEFINE IncrementarPulsador PORTB,6
; ZONA DE CÓDIGOS ********************************************************************
ORG 0
goto Inicio
ORG 4
goto ServicioInterrupcion
Mensajes
addwf PCL,F
Mensaje_ON
DT "EN FUNCION",0x00
Mensaje_Ajuste
DT "TIEMPO DECEADO",0x00
Mensaje_OFF
DT " RECARGAR",0x00
;interrupcion de inicio
Inicio
call LCD_Inicializa
movlw Mensaje_Inicio
call LCD_MensajeMovimiento
call Retardo_500ms
call Retardo_500ms
call Retardo_500ms
movlw Mensaje_nollave
call LCD_MensajeMovimiento
call Retardo_500ms
call Retardo_500ms
call Retardo_500ms
call Retardo_500ms
call Retardo_500ms
bsf STATUS,RP0
movlw b'00000111'
movwf OPTION_REG
bsf AjustePulsador
bsf IncrementarPulsador
bcf SalidaTemporizador
bcf Zumbador
bcf STATUS,RP0
clrw
call EEPROM_LeeDato
movwf TiempoDeseado
call ModoTemporizador_OFF
movlw b'10001000'
movwf INTCON
Principal
goto Principal
;subrrutinasdeservicioInterrupcion------------------------------------------
ServicioInterrupcion
btfsc INTCON,T0IF
call Temporizador
btfss INTCON,RBIF
goto FinInterrupcion
btfss AjustePulsador
call CambiarModo
btfsc IncrementarPulsador
goto FinInterrupcion
call Retardo_20ms
btfsc IncrementarPulsador
goto FinInterrupcion
btfsc F_Temporizador_OFF
call ModoTemporizador_ON
btfsc F_Temporizador_Ajuste
call IncrementarTiempoDeseado
FinInterrupcion
bcf INTCON,RBIF
bcf INTCON,T0IF
retfie
;subrrutinasCambiarModo------------------------------------------------------------
CambiarModo
call PitidoCorto
btfsc AjustePulsador
goto EsperaDejePulsar
btfsc F_Temporizador_OFF
goto ModoTemporizador_Ajuste
btfss F_Temporizador_Ajuste
goto ModoTemporizador_OFF
clrw
movwf EEADR
movf TiempoDeseado,W
call EEPROM_EscribeDato
ModoTemporizador_OFF
bcf SalidaTemporizador
call Pitido
movlw b'00000001'
movwf FlagsModo
bcf INTCON,T0IE
movf TiempoDeseado,W
movwf Tiempo
call LCD_Borra
movlw Mensaje_OFF
goto FinCambiarModo
ModoTemporizador_Ajuste
bcf SalidaTemporizador
movlw b'00000010'
movwf FlagsModo
clrf Tiempo
clrf TiempoDeseado
bcf INTCON,T0IE
call LCD_Borra
movlw Mensaje_Ajuste
goto FinCambiarModo
ModoTemporizador_ON
movf TiempoDeseado,W
btfsc STATUS,Z
goto ModoTemporizador_OFF
movwf Tiempo
call PitidoCorto
movlw b'00000100'
movwf FlagsModo
movlw TMR0_Carga50ms
movwf TMR0
movlw Carga_1s
movwf Registro50ms
bsf INTCON,T0IE
call LCD_Borra
bsf SalidaTemporizador
movlw Mensaje_ON
FinCambiarModo
call LCD_Mensaje
call VisualizaTiempo
EsperaDejePulsar
btfss AjustePulsador
goto EsperaDejePulsar
return
;SubrutinaTEMPORIZADOR
CBLOCK
Registro50ms
ENDC
TMR0_Carga50ms EQU -d'195'
Carga_1s EQU d'20'
Temporizador
call Retardo_50micros
call Retardo_20micros
nop
movlw TMR0_Carga50ms
movwf TMR0
decfsz Registro50ms,F
goto FinTemporizador
movlw Carga_1s
movwf Registro50ms
btfss F_Temporizador_ON
goto FinTemporizador
decfsz Tiempo,F
goto VisualizaContador
bcf SalidaTemporizador
call VisualizaTiempo
call Pitido
call Retardo_500ms
call Pitido
call Retardo_500ms
call PitidoLargo
call Retardo_500ms
call ModoTemporizador_OFF
goto FinTemporizador
VisualizaContador
call VisualizaTiempo
FinTemporizador
return
;SubrutinaVisualizaTiempo--------------------------------------------------
VisualizaTiempo
movlw .5
call LCD_PosicionLinea2
movf Tiempo,W
call MinutosSegundos
movf TemporizadorMinutos,W
call BIN_a_BCD
call LCD_Byte
movlw ':'
call LCD_Caracter
movf TemporizadorSegundos,W
call BIN_a_BCD
goto LCD_ByteCompleto
return
;subrutinaminutossegundos----------------------------------------------------
CBLOCK
TemporizadorMinutos
TemporizadorSegundos
ENDC
MinutosSegundos
movwf TemporizadorSegundos
clrf TemporizadorMinutos
Resta60 movlw .60
subwf TemporizadorSegundos,W
btfss STATUS,C
goto FinMinutosSegundos
movwf TemporizadorSegundos
incf TemporizadorMinutos,F
goto Resta60
FinMinutosSegundos
return
;subrutina incrementatiempodeseado
Saltoincremento EQU .5
IncrementarTiempoDeseado
call PitidoCorto
movlw Saltoincremento
addwf Tiempo,F
btfsc STATUS,C
clrf Tiempo
call VisualizaTiempo
call Retardo_100ms
btfss IncrementarPulsador
goto IncrementarTiempoDeseado
movf Tiempo,W
movwf TiempoDeseado
return
;subrrutinapitidolargopitidocorto
PitidoLargo
bsf Zumbador
call Retardo_500ms
Pitido
bsf Zumbador
call Retardo_200ms
PitidoCorto
bsf Zumbador
call Retardo_20ms
bcf Zumbador
return
INCLUDE <RETARDOS.INC>
INCLUDE <BIN_BCD.INC>
INCLUDE <LCD_4BIT.INC>
INCLUDE <LCD_MENS.INC>
INCLUDE <EEPROM.INC>
END :-(
Hola:
No se hacerlo. Mejor funciona con Arduino UNO, es más fácil de programarlo.
El que me ayudó a ponerlo a 99:99 en unos post más atrás pero no a las 24 horas.
[youtube=640,360]https://www.youtube.com/watch?v=qNXp5NFDuHw[/youtube]
http://electronicavm.net/2011/06/22/temporizador-arduino-lcd/
Saludos.
hola, primero quiero agradecer tu ayuda, dos puedes pasarme el codigo para hacer el temporizador de 99:99 programable porfavor, quisiera darle una estudiada haber si puedo hacer el de 24 hrs te lo agradecere mucho saludos
hola de nuevo, mira tengo este codigo de un reloj de 24 horas, quise modificarlo pero lo que logre es q solo decremente los minutos y horas con los segundos acendentes ocea que si llega el segundero a 60 (no a cero) decrementa, tambien tengo el problema de que cuando decrmenta las horas en los minutos en lugar de iniciarce en 59 ejemplo 2:59:59 se inicia en 55 (2:55:60) espero me puedas ayudar
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
LIST P=16F84A
INCLUDE <P16F84A.INC>
CBLOCK 0x0C
Hora ; Guarda las horas.
Minuto ; Guarda los minutos.
Segundo ; Guarda los segundos.
MedioSegundo ; Incrementa cada medio segundo.
Registro50ms ; Incrementa cada 50 ms
Intermitencia ; Para lograr la intermitencia.
FlagsAjuste ; Guarda los flags para establecer los
ENDC ; ajustes de hora y minuto.
#DEFINE REELEVADOR PORTB,1
#DEFINE ModoPulsador PORTB,7 ; Los pulsadores se conectan a estos
#DEFINE IncrementarPulsador PORTB,6 ; pines del Puerto B.
#DEFINE F_AjusteHora FlagsAjuste,1 ; Flags utilizados en la puesta en hora.
#DEFINE F_AjusteMinuto FlagsAjuste,0
#DEFINE F_Intermitencia Intermitencia,0 ; Si es 0, apaga en intermitencia.
TMR0_Carga50ms EQU -d'195' ; Para conseguir la interrupción del
; ZONA DE CÓDIGOS ********************************************************************
ORG 0
goto Inicio
ORG 4
goto ServicioInterrupcion
Mensajes
addwf PCL,F
MensajePublicitario
DT "REC: H M S", 0x00
Inicio call LCD_Inicializa
movlw MensajePublicitario
call LCD_Mensaje
bsf STATUS,RP0 ; Acceso al Banco 1.
movlw b'00000111' ; Prescaler de 256 para el TMR0 y habilita
movwf OPTION_REG ; resistencias de Pull-Up del Puerto B.
bsf ModoPulsador ; Configurados como entrada.
bsf IncrementarPulsador
bcf REELEVADOR
bcf STATUS,RP0 ; Acceso al Banco 0.
clrf FlagsAjuste ; Inicializa todos los flags de la puesta en hora.
clrf Hora ; Inicializa todos los datos del reloj.
clrf Minuto
clrf Segundo
clrf MedioSegundo
clrf Registro50ms
movlw TMR0_Carga50ms ; Carga el TMR0.
movwf TMR0
movlw b'10101000' ; Activa interrupción del TMR0 (TOIE), por cambio
movwf INTCON ; líneas del Puerto B (RBIE) y la general (GIE).
call PuestaEnHoraReset ; Puesta en hora por primera vez.
; La sección "Principal" es mantenimiento. Sólo espera las interrupciones.
; No se puede poner en modo de bajo consumo porque la instrucción "sleep" detiene el Timer 0.
Principal
goto Principal
; Subrutina "ServicioInterrupcion" ------------------------------------------------------
;
; Detecta qué ha producido la interrupción y ejecuta la subrutina de atención correspondiente.
ServicioInterrupcion
btfsc INTCON,T0IF ; Si es una interrupción procedente del
call Reloj ; desbordamiento del Timer 0, actualiza el reloj.
btfss INTCON,RBIF ; Si es una interrupción RBI, lee los pulsadores.
goto FinInterrupcion
btfss ModoPulsador ; ¿Está presionado el pulsador de "MODO"?
call PuestaEnHora ; Sí, pasa a poner en hora.
btfss IncrementarPulsador ; ¿Pulsado "INCREMENTAR"?.
call Incrementar ; Sí, pasa a incrementar el registro de tiempo
FinInterrupcion ; correspondiente.
bcf INTCON,RBIF
bcf INTCON,T0IF
retfie
; Subrutina "Reloj" ---------------------------------------------------------------------
;
; Esta subrutina actualiza los contadores Horas, Minutos, Segundos y Registro50ms.
; Se ejecuta debido a la petición de interrupción del Timer 0 cada 50 ms.
;
; Como el PIC trabaja a una frecuencia de 4 MHz, el TMR0 evoluciona cada µs y se desborda cada
; 195 x 256 = 49920 µs. Sumádole el retardo de 71 µs y el pequeño tiempo de los saltos
; iniciales y de carga del contador, resulta un total de 50000 µs exactos. Es decir, el
; TMR0 producirá una interrupción cada 50 ms exactos, comprobado experimentalmente con la
; ventana Stopwatch del simulador del MPLAB.
Reloj call Retardo_50micros ; Retardo de 71 microsegundos para
call Retardo_20micros ; ajustar a 50 milisegundos exactos.
nop
movlw TMR0_Carga50ms ; Carga el Timer 0.
movwf TMR0
call IncrementaRegistro50ms
btfss STATUS,C ; ¿Ha contado 10 veces 50 ms = 1/2 segundo?
goto FinReloj ; No. Pues sale sin visualizar el reloj.
; Si está en "ModoAjusteHora", o "ModoAjusteMinuto" conmuta el flag de intermitencia y
; salta a visualizar el reloj.
;
movf FlagsAjuste,F
btfsc STATUS,Z
goto IncrementaReloj
movlw b'00000001' ; Conmuta el flag F_Intermitencia cada 500 ms.
xorwf Intermitencia,F
goto ActualizaReloj ; Visualiza el reloj y sale.
IncrementaReloj
bsf REELEVADOR
bsf F_Intermitencia ; Se mantendrá siempre encendido durante
call IncrementaMedioSegundo ; el funcionamiento normal.
btfss STATUS,C ; ¿Ha pasado 1 segundo?
goto ActualizaReloj ; No. Pues sale visualizando el reloj.
call IncrementaSegundos ; Sí. Incrementa el segundero.
btfss STATUS,Z ; ¿Han pasado 60 segundos?
goto ActualizaReloj ; No. Pues sale visualizando el reloj.
call Decrementamin ; Sí. Incrementa el minutero.
btfss STATUS,Z ; ¿Han pasado 60 minutos?
goto ActualizaReloj ; No. Pues sale visualizando el reloj.
call Decrementahr ; Sí. Incrementa las horas.
ActualizaReloj
call VisualizaReloj ; Visualiza el reloj.
FinReloj
return
; Subrutina "VisualizaReloj" ------------------------------------------------------------
;
; Visualiza el reloj en la segunda línea en formato: " 8:47:39".
; Cuando se ajusta una variable, ésta debe aparecer en intermitencia. Para ello, utiliza
; el flag F_Intermitencia que conmuta cada 500 ms en la subrutina Reloj.
;
VisualizaReloj
movlw .4 ; Para centrar visualización
call LCD_PosicionLinea2 ; en la segunda línea.
btfss F_AjusteHora ; ¿Está en la puesta en hora?
goto EnciendeHoras ; No. Visualización normal.
btfss F_Intermitencia ; Sí. Intermitencia si procede.
goto ApagaHoras ; Apaga las horas en la intermitencia.
EnciendeHoras
movf Hora,W ; Va a visualizar las horas.
call BIN_a_BCD ; Lo pasa a BCD.
call LCD_Byte ; Visualiza rechazando cero de las decenas.
goto VisualizaMinutos
ApagaHoras
call LCD_DosEspaciosBlancos ; Visualiza dos espacios en blanco.
;
VisualizaMinutos
movlw ':' ; Envía ":" para separar datos.
call LCD_Caracter
btfss F_AjusteMinuto ; ¿Está en la puesta en hora?.
goto EnciendeMinutos
btfss F_Intermitencia
goto ApagaMinutos
EnciendeMinutos
movf Minuto,W ; Visualiza minutos.
call BIN_a_BCD ; Lo pasa a BCD.
call LCD_ByteCompleto
goto VisualizaSegundos
ApagaMinutos
call LCD_DosEspaciosBlancos ; Visualiza dos espacios en blanco.
;
VisualizaSegundos
movlw ':' ; Envía ":" para separar datos.
call LCD_Caracter
movf Segundo,W ; Visualiza segundos.
call BIN_a_BCD ; Lo pasa a BCD.
call LCD_ByteCompleto
return
;
; Subrutina "Incrementar" ---------------------------------------------------------------
;
; Subrutina de atención a la interrupción por cambio de la línea RB6 al cual se ha conectado
; el pulsador "INCREMENTAR". Incrementa según corresponda una sola de las variables.
Incrementar
call Retardo_20ms ; Espera se estabilicen niveles de tensión.
btfsc IncrementarPulsador ; Si es un rebote sale fuera.
goto FinIncrementar
bsf F_Intermitencia ; Visualiza siempre mientras incrementa.
btfsc F_AjusteHora
call IncrementaHoras
btfsc F_AjusteMinuto
call IncrementaMinutos
call VisualizaReloj ; Visualiza mientras espera que deje
call Retardo_200ms ; de pulsar.
btfss IncrementarPulsador ; Mientras permanezca pulsado,
goto Incrementar ; incrementa el dígito.
FinIncrementar
return
; Subrutina "IncrementaRegistro50ms" ----------------------------------------------------
;
; Incrementa el valor de la variable Registro50ms. Cuando llega a 10, lo cual supone
; medio segundo (50 ms x 10 = 500 ms), lo resetea y sale con el Carry a "1".
;
IncrementaRegistro50ms
incf Registro50ms,F
movlw .10
subwf Registro50ms,W ; (W)=(Registro50ms)-10.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Registro50ms)<10?
clrf Registro50ms ; Lo inicializa si ha superado su valor máximo.
return
; Subrutina "IncrementaMedioSegundo" --------------------------------------------------------
;
; Incrementa el valor de la variable MedioSegundo. Su bit de menor peso se pondrá a "1" una
; vez por segundo.
IncrementaMedioSegundo
incf MedioSegundo,F ; Incrementa.
bsf STATUS,C ; Supone que ha llegado al segundo.
btfss MedioSegundo,0 ; El bit 0 se pondrá a uno cada segundo.
bcf STATUS,C
return
; Subrutina "IncrementaSegundos" -----------------------------------------------------------
;
; Incrementa el valor de la variable Segundo. Si es igual al valor máximo de 60 lo resetea
; y sale con el Carry a "1".
IncrementaSegundos
incf Segundo,F ; Incrementa los minutos.
movlw .60
subwf Segundo,W ; ¿Ha superado su valor máximo?. (W)=(Minuto)-60.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Minuto)<60?
clrf Segundo ; Lo inicializa si ha superado su valor máximo.
return
; Subrutina "IncrementaMinutos" -----------------------------------------------------------
;
; Incrementa el valor de la variable Minuto. Si es igual al valor máximo de 60 lo resetea
; y sale con el Carry a "1".
;
IncrementaMinutos
incf Minuto,F ; Incrementa los minutos.
movlw .60
subwf Minuto,W ; ¿Ha superado su valor máximo?. (W)=(Minuto)-60.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Minuto)<60?
clrf Minuto ; Lo inicializa si ha superado su valor máximo.
return
; Subrutina "IncrementaHoras" -----------------------------------------------------------
;
; Incrementa el valor de la variable Hora. Si es igual al valor máximo de 24 lo resetea
; y sale con el Carry a "1".
;
IncrementaHoras
incf Hora,F ; Incrementa las horas.
movlw .24
subwf Hora,W ; ¿Ha superado su valor máximo?. (W)=(Hora)-24.
btfsc STATUS,C ; ¿C=0?, ¿(W) negativo?, ¿(Hora)<24?
clrf Hora ; Lo inicializa si ha superado su valor máximo.
return
Decrementamin
decf Minuto,1
return
Decrementahr
decf Hora,1
return
PuestaEnHora
call Retardo_20ms ; Espera a que se estabilicen niveles.
btfsc ModoPulsador ; Si es un rebote sale fuera.
goto FinPuestaEnHora
PuestaEnHoraReset ; Al pulsar "MODO" se apaga la variable de
bcf REELEVADOR
bcf F_Intermitencia ; tiempo que se va a ajustar.
movf FlagsAjuste,F ; Si antes estaba en funcionamiento normal, ahora
btfss STATUS,Z ; pasa a ajustar la hora.
goto AjustaSiguiente ; Si no pasa a ajustar la variable de tiempo siguiente.
bsf F_AjusteHora ; Pasa a ajustar la hora.
clrf Segundo ; Inicializa contador de segundos y el resto.
clrf MedioSegundo
clrf Registro50ms
goto FinPuestaEnHora
AjustaSiguiente ; Desplaza un "1" a la derecha del registro
bcf STATUS,C ; FlagsAjuste para ajustar secuencialmente
rrf FlagsAjuste,F ; cada uno de los registros de tiempo:
FinPuestaEnHora ; hora y minuto.
call VisualizaReloj
btfss ModoPulsador ; Ahora espera deje de pulsar.
goto FinPuestaEnHora
return
INCLUDE <RETARDOS.INC>
INCLUDE <LCD_4BIT.INC>
INCLUDE <LCD_MENS.INC>
INCLUDE <BIN_BCD.INC>
END