Foro de elhacker.net

Informática => Electrónica => Mensaje iniciado por: Meta en 8 Septiembre 2010, 01:20 am



Título: Temporizador para insoladora
Publicado por: Meta en 8 Septiembre 2010, 01:20 am
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.

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                ; 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.


Título: Re: Temporizador para insoladora
Publicado por: Tokes en 8 Septiembre 2010, 01:43 am
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.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 8 Septiembre 2010, 02:41 am
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.


Título: Re: Temporizador para insoladora
Publicado por: Tokes en 8 Septiembre 2010, 04:03 am
Mira, te hice un programa un tanto sencillo para mostrarte como debe modificarse tu programa.

Código
  1. ; Este programa lo único que hace es contar desde 20 minutos hasta 0,
  2. ; es decir, no puede ajustarse, a menos que se edite el programa.
  3.  
  4. LIST P=16F84A
  5. INCLUDE "P16F84A.INC"
  6.  
  7. CBLOCK 0CH
  8. Reg_50ms, Tiempo_H, Tiempo_L
  9. ENDC
  10.  
  11. ; Ojo: En vez de usar una variable llamada TIEMPO debes usar dos:
  12.  ; - Una para almacenar el byte alto de la cantidad de segundos,
  13. ; llamada Tiempo_H.
  14. ; - Una para almacenar el byte bajo de la cantidad de segundos,
  15. ; llamada Tiempo_L.
  16. ;
  17. ; ¿Por qué 2 bytes? Pues porque para temporizar hasta 20 minutos se
  18. ; requieren hasta 20 x 60 = 1200 segundos. La cantidad 1200 se representa
  19. ; con mínimo 2 bytes.
  20.  
  21. #DEFINE Alarma PORTB,0
  22.  
  23. ORG 00H
  24. goto Inicio
  25.  
  26. ORG 04H
  27. goto Interrupcion
  28.  
  29. Inicio
  30. bcf Alarma
  31. bsf STATUS,RP0
  32. movlw b'11000111'
  33. movwf OPTION_REG
  34. bcf Alarma
  35. bcf STATUS,RP0
  36.  
  37. call LCD_Inicializa
  38. movlw high(.1200) ; Carga el byte alto del tiempo en la variable
  39. movwf Tiempo_H ; Tiempo_H.
  40. movlw low(.1200) ; Carga el byte bajo del tiempo en la variable
  41. movwf Tiempo_L ; Tiempo_L.
  42. call Visualiza_Tiempo ; Visualiza el tiempo en la pantalla.
  43.  
  44. movlw .20 ; Se prepara para temporizar.
  45. movwf Reg_50ms
  46. movlw .60
  47. movwf TMR0
  48. bcf INTCON,T0IF
  49. bsf INTCON,T0IE
  50. bsf INTCON,GIE ; Habilita interrupciones.
  51.  
  52. Ciclo
  53. goto Ciclo
  54.  
  55. ; Rutina de servicio a la interrupción.
  56. Interrupcion
  57. movlw .60
  58. movwf TMR0 ; Recarga el TMR0.
  59. decfsz Reg_50ms ; ¿Ya pasó 1 segundo?
  60. goto Fin_Interrupcion
  61.  
  62. movlw .20 ; Sí, entonces recarga el registro.
  63. movwf Reg_50ms
  64.  
  65. ; Ojo: Aquí se va a realizar el decremento del tiempo, pero
  66. ; es un decremento de 16 bits.
  67. decf Tiempo_L,F ; Decrementa en 1 el byte bajo.
  68. movlw 0xFF
  69. subwf Tiempo_L,W
  70. btfsc STATUS,Z ; ¿El resultado es negativo?
  71. decf Tiempo_H,F ; Sí, entonces decrementa en 1 el byte alto.
  72.  
  73. call Visualiza_Tiempo ; Visualiza el tiempo en la pantalla.
  74.  
  75. ; Atención: Anteriormente sólo decrementamos el tiempo, pero NO
  76. ; verificamos si llegó al valor 0. Aquí se realiza esto. Si los
  77. ; dos bytes del tiempo valen 0 significa que el tiempo terminó.
  78. movf Tiempo_H,F
  79. btfss STATUS,Z ; ¿Vale 0 el byte alto?
  80. goto Fin_Interrupcion ; No, pues sale de la interrupción.
  81. movf Tiempo_L,F
  82. btfss STATUS,Z ; ¿Vale 0 el byte bajo?
  83. goto Fin_Interrupcion ; No, pues sale de la interrupción.
  84.  
  85. ; Llegamos aquí porque los dos bytes valen 0, es decir, el tiempo terminó.
  86. bsf Alarma ; Activa la alarma
  87. call Retardo_2s ; durante un corto tiempo.
  88. bcf Alarma
  89.  
  90. bcf INTCON,T0IE ; Prohibe la interrupción del TMR0
  91. ; Para que detener el conteo.
  92.  
  93. Fin_Interrupcion
  94. bcf INTCON,T0IF ; Borra la bandera de interrupción
  95. retfie ; y retorna.
  96.  
  97. ; Subrutina Visualiza_Tiempo.
  98. ;
  99. ; Observa que antes sólo se hacía:
  100. ;
  101. ; movf TIEMPO,W
  102. ; call MinutosSegundos
  103. ;
  104. ; Pues ahora el tiempo es de dos bytes y debe hacerse como sigue.
  105. Visualiza_Tiempo
  106. call LCD_Borra
  107. ; Debes hacerlo así para que funcione. La rutina MinutosSegundos
  108. ; modificada maneja los registros MinutosSegundos_TiempoH y
  109. ; MinutosSegundos_TiempoL.
  110. movf Tiempo_H,W
  111. movwf MinutosSegundos_TiempoH
  112. movf Tiempo_L,W
  113. movwf MinutosSegundos_TiempoL
  114. call MinutosSegundos ; Convierte de segundos a minutos y
  115. ; segundos.
  116. movf Minutos,W
  117. call BIN_BCD
  118. call LCD_ByteCompleto
  119. movlw ':'
  120. call LCD_Caracter
  121. movf Segundos,W
  122. call BIN_BCD
  123. call LCD_ByteCompleto
  124. return
  125.  
  126. ; La rutina BIN_BCD yo la hice, pero puedes usar la que tú tienes.
  127. ; Lo que pasa es que la hice porque no la tengo.
  128. ; Insisto, puedes usar la que tú tienes.
  129. BIN_BCD
  130. CBLOCK
  131. Unidades, Decenas, Centenas
  132. ENDC
  133.  
  134. movwf Unidades
  135. clrf Decenas
  136. clrf Centenas
  137. BIN_BCD_Resta10
  138. movlw .10
  139. subwf Unidades,F
  140. btfss STATUS,C
  141. goto Fin_BIN_BCD
  142.  
  143. incf Decenas,F
  144. movlw .10
  145. subwf Decenas,W
  146. btfss STATUS,C
  147. goto BIN_BCD_Resta10
  148.  
  149. clrf Decenas
  150. incf Centenas,F
  151. goto BIN_BCD_Resta10
  152.  
  153. Fin_BIN_BCD
  154. movlw .10
  155. addwf Unidades,F
  156. movf Unidades,W
  157. swapf Decenas,F
  158. iorwf Decenas,W
  159. swapf Decenas,F
  160. return
  161.  
  162. ; Aquí está la subrutina MinutosSegundos modificada para manejar
  163. ; números de 2 bytes. Ésta sí úsala en lugar de la otra.
  164. MinutosSegundos
  165. CBLOCK
  166. Segundos, Minutos
  167. MinutosSegundos_TiempoH
  168. MinutosSegundos_TiempoL
  169. ENDC
  170.  
  171. clrf Minutos ; Borra los minutos.
  172. ; Le resta 60 al tiempo que está almacenado en las variables
  173. ; MinutosSegundos_TiempoH y MinutosSegundos_TiempoL.
  174. MinutosSegundos_Resta60
  175. movlw .60
  176. subwf MinutosSegundos_TiempoL,F ; Resta 60 del byte bajo.
  177. btfss STATUS,C ; ¿Es negativo?
  178. decf MinutosSegundos_TiempoH,F ; Sí, entonces decrementa en
  179. ; 1 el byte alto.
  180. btfsc MinutosSegundos_TiempoH,7 ; ¿El resultado es negativo?
  181. goto Fin_MinutosSegundos ; Sí, pues ya terminamos de convertir.
  182.  
  183. incf Minutos,F ; Incrementa en 1 la cantidad de minutos.
  184. goto MinutosSegundos_Resta60 ; Sigue revisando si hay más minutos.
  185.  
  186. Fin_MinutosSegundos
  187. movlw .60 ; Le suma 60 a la cantidad de tiempo ya que
  188. ; previamente se le restó 60 y el resultado
  189. ; fue negativo.
  190. addwf MinutosSegundos_TiempoL,W
  191. movwf Segundos
  192. return
  193.  
  194. INCLUDE "LCD_4BIT.INC"
  195. INCLUDE "RETARDOS.INC"
  196.  
  197. END

Bien, en el programa podrás darte cuenta que cargué un valor en las variables Tiempo_H y Tiempo_L:

Código:
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:

Código
  1. ; Incrementar la variable de tiempo.
  2.   movlw   IncrementoTiempo ; Le suma un valor de incremento al
  3.   addwf    Tiempo_L,F           ; byte bajo.
  4.   btfsc      STATUS,C             ; ¿Hubo acarreo?
  5.   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.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 8 Septiembre 2010, 04:53 am
Muchas gracias por la ayuda y si funciona lo que me enviaste.

Una curiosidad que tengo y no sabía.

Código
  1. movlw high(.1200) ; Carga el byte alto del tiempo en la variable
  2. movwf Tiempo_H ; Tiempo_H.
  3. movlw low(.1200) ; Carga el byte bajo del tiempo en la variable
  4. movwf Tiempo_L ; Tiempo_L.
  5.  

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.


Título: Re: Temporizador para insoladora
Publicado por: Tokes en 8 Septiembre 2010, 06:06 am
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


Título: Re: Temporizador para insoladora
Publicado por: Meta en 8 Septiembre 2010, 06:37 am
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.


Título: Re: Temporizador para insoladora
Publicado por: Tokes en 8 Septiembre 2010, 20:00 pm
Meta:

Te envié al correo el programa modificado.

Eso es todo. Saludos y buen día.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 8 Septiembre 2010, 22:28 pm
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.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 6 Diciembre 2010, 17:40 pm
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.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 20 Diciembre 2010, 16:32 pm
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.


Título: Re: Temporizador para insoladora
Publicado por: yarboclo en 31 Enero 2011, 21:29 pm
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.


Título: Re: Temporizador para insoladora
Publicado por: Meta en 10 Febrero 2011, 03:58 am
Cuando pueda te lo paso.


Título: Re: Temporizador para insoladora
Publicado por: yarboclo en 17 Febrero 2011, 21:06 pm
Oki, espero tu mensaje.
Gracias :rolleyes:


Título: Re: Temporizador para insoladora
Publicado por: f2v en 25 Septiembre 2011, 12:19 pm
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....


Título: Re: Temporizador para insoladora
Publicado por: markitosb en 8 Enero 2012, 14:45 pm
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 ;-)


Título: temporizador 24 horas
Publicado por: elcerouno en 24 Septiembre 2015, 19:09 pm
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 :-(


Título: Re: Temporizador para insoladora
Publicado por: Meta en 9 Octubre 2015, 02:38 am
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.

qNXp5NFDuHw

http://electronicavm.net/2011/06/22/temporizador-arduino-lcd/

Saludos.


Título: Re: Temporizador para insoladora
Publicado por: elcerouno en 23 Octubre 2015, 16:11 pm
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


Título: Re: Temporizador para insoladora
Publicado por: elcerouno en 23 Octubre 2015, 16:23 pm
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