PIC16 10hz timer con timer1 y 1Mhz clock

0

Necesito incrementar un cronómetro a 10 hz usando el timer1 en un PIC16F628. El reloj externo es 1Mhz, suministrado por un oscilador empaquetado (EPSON sg8002db). Sin preescalador, el valor para configurar el temporizador en (creo) debería ser:

tics de reloj en 1 segundo: 1000000

el temporizador marca en 1 segundo: 250000 (reloj / 4)

tics del temporizador en 1/10 de segundo: 25000 (tics del temporizador / 10)

Entonces: 65536 - 25000 = 40536

pero debo tener en cuenta la latencia desde el desbordamiento del temporizador hasta cuando se restablece el valor del reloj: este es el número de ciclos que toma desde el desbordamiento que se produce hasta que configuro el valor del temporizador.

El código IRQ es:

    irq             movwf   w_temp          ; save state
                    swapf   STATUS, w
                    clrf    STATUS
                    movwf   status_temp
                    movf    PCLATH, w
                    movwf   pclath_temp
                    clrf    PCLATH

                    btfss   PIR1,TMR1IF     ; timer1 IRQ?
                    goto    notimer1
                    bcf     PIR1,TMR1IF     ; yes, clear it

                    movLw   T1SPEED >> 8    ; reset timer1
                    movwf   TMR1H
                    movLw   T1SPEED & 0xff
                    movwf   TMR1L           ; timer1 is off and running again

                    call    timer           ; increment clock

    notimer1        btfss   INTCON, T0IF    ; timer0 IRQ?
                    goto    notimer0
                    bcf     INTCON, T0IF    ; yes, clear it

                    call    led_set         ; update display

                    btfss   PORTA,6         ; button pressed?
                    goto    nobut
                    clrf    digit0          ; yes, reset clock
                    clrf    digit1
                    clrf    digit2
                    clrf    digit3
    nobut
    notimer0        movf    pclath_temp, w  ; restore state
                    movwf   PCLATH
                    swapf   status_temp, w
                    movwf   STATUS
                    swapf   w_temp, f
                    swapf   w_temp, w
                    retfie

Lo que me parece un lugar en la región de unos 14 ciclos, por lo que LATENCY = 14

65536 - (25000 - LATENCIA) = 40550

pero esto da un reloj que es demasiado lento, perdiendo varios segundos por minuto. Si cambio el valor de LATENCIA a ~ 200 (por ejemplo, configurar el temporizador 1 a 40736), está cerca, dentro de 1 segundo por minuto, pero aún no es exacto. De hecho, con LATENCY = 199, es demasiado rápido y con LATENCY = 200, es lento.

No puedo ver dónde se están gastando estos ciclos adicionales: establece el valor del reloj a primera hora en la rutina IRQ. No puedo encontrar nada en la hoja de datos acerca de que el temporizador 1 se haya detenido durante una rutina de interrupción, ¿no es así? Si es así, eso sería un fastidio, porque la rutina toma una cantidad variable de ciclos dependiendo de los dígitos que se desborden.

¿Es necesario elegir 2 valores de recarga diferentes y alternar entre ellos para alcanzar exactamente 10 hz?

    
pregunta Charlie Skilbeck

2 respuestas

6

En lugar de usar el temporizador 1 de 16 bits, que requiere que vuelva a cargar el valor en el código, use el temporizador 2 de 8 bits, que tiene un registro predefinido PR2. Cargue PR2 con 250, con un valor de prescaler de 1: 1. Luego se interrumpirá cada 1 ms y se volverá a cargar automáticamente, por lo que no habrá problemas de latencia.

Dentro de su interrupción, solo incremente un contador de un solo byte. En su rutina básica, use un bucle while y pruebe cada vez que el contador sea igual a 100 (es decir, que haya transcurrido 1/10 de segundo). Luego reinicie el contador y actualice y reinicie su reloj / led en el nivel básico, no en su rutina de interrupción.

    
respondido por el tcrosley
0

en lugar de restablecer el temporizador 1, simplemente actualice la alarma para que sea 0.1s más en el futuro

    
respondido por el Jasen

Lea otras preguntas en las etiquetas