;********************************** INT_Temporizador.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=16F88
INCLUDE <P16F88.INC>
__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
CBLOCK 0x20
TiempoDeseado_H ; El tiempo deseado de temporización.
TiempoDeseado_L
Tiempo_H ; Tiempo que resta de temporización.
Tiempo_L
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 " Contando...", 0x00
Mensaje_Ajuste
DT "Tiempo deseado:", 0x00
Mensaje_OFF
DT " PARADO", 0x00
Mensaje_Arriba_ON
Mensaje_Arriba_OFF
Mensaje_Abajo_ON
Mensaje_Abajo_OFF
; Instrucciones de inicialización. ------------------------------------------------------
;
Inicio
call LCD_Inicializa
bcf STATUS,RP1
bsf STATUS,RP0
clrf ANSEL
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,RP1
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_L ; que se ajustó.
movlw .1
call EEPROM_LeeDato
movwf TiempoDeseado_H
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,TMR0IF
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,TMR0IF
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_L,W ; apague la alimentación.
call EEPROM_EscribeDato
incf EEADR,F
movf TiempoDeseado_H,W
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,TMR0IF ; Prohíbe las interrupciones del TMR0.
movf TiempoDeseado_L,W ; Repone otra vez el tiempo que se desea para la
movwf Tiempo_L ; próxima temporización.
movf TiempoDeseado_H,W
movwf Tiempo_H
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_L ; Resetea el tiempo.
clrf Tiempo_H
clrf TiempoDeseado_L
clrf TiempoDeseado_H
bcf INTCON,TMR0IF ; Prohíbe las interrupciones del TMR0.
call LCD_Borra
movlw Mensaje_Ajuste ; En pantalla el mensaje correspondiente.
goto FinCambiarModo
ModoTemporizador_ON
movf TiempoDeseado_H,F ; Si el tiempo deseado es cero pasa a modo
btfss STATUS,Z ; de trabajo "Temporizador_OFF".
goto ModoTemporizador_ON_Sigue
movf TiempoDeseado_L,F
btfsc STATUS,Z
goto ModoTemporizador_OFF
ModoTemporizador_ON_Sigue
movf TiempoDeseado_L,W
movwf Tiempo_L
movf TiempoDeseado_H,W
movwf Tiempo_H
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,TMR0IF ; 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.
decf Tiempo_L,F
movlw 0xFF
xorwf Tiempo_L,W
btfsc STATUS,Z
decf Tiempo_H,F
movf Tiempo_L,F
btfss STATUS,Z
goto VisualizaContador ; Visualiza el tiempo restante.
movf Tiempo_H,W
btfss STATUS,Z
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_L,W ; Convierte el tiempo deseado (y expresado sólo en
movwf MinutosSegundos_TiempoL ; segundos) a minutos y segundos.
movf Tiempo_H,W
movwf MinutosSegundos_TiempoH
call MinutosSegundos
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
;*************************
; Aquí está la subrutina MinutosSegundos modificada para manejar
; números de 2 bytes. Ésta sí úsala en lugar de la otra.
MinutosSegundos
CBLOCK
TemporizadorSegundos, TemporizadorMinutos
MinutosSegundos_TiempoH
MinutosSegundos_TiempoL
ENDC
clrf TemporizadorMinutos ; 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 TemporizadorMinutos,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
; fué negativo.
addwf MinutosSegundos_TiempoL,W
movwf TemporizadorSegundos
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_L,F ; saltos de SALTO_INCR segundos.
btfsc STATUS,C
incf Tiempo_H,F
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_L,W ; Actualiza el tiempo deseado.
movwf TiempoDeseado_L ; Este es el tiempo deseado.
movf Tiempo_H,W
movwf TiempoDeseado_H
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