Buenas:
Dejo el código del chisme PIC16F88 que ya funciona para las 99:99.
Pues no, no funciona para los 16F88, si para el 16F84A. El 16F88 me da problemas con el tema de las interrupciones, cosa que estoy averiguando como corregirlo. Dejaré por si algún visitante en el futuro le haga falta tener la posibilidad de untemporizador a 99:99 con el 16F84A.
Código: ; 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_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 " En MARCHA", 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
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_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,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_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,T0IE ; 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,T0IE ; 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,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.
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
Gracias por la infi y Feliz Navidad 2010. |