Desfase de tiempo con Timer0 PIC 16F877A (temporizador)

Hola, estoy intentando hacer un programa con el ensamblador del PIC 16F877A, que me permita medir el tiempo en segundos indefinidamente, sin embargo tengo un desfazamiento entre el tiempo real y el tiempo que marca el PIC, al parecer el PIC se atrasa conforme el intervalo de tiempo se hace mas largo... este es mi codigo:

INCLUDE<P16F877A.INC>
LIST p=16F877A

;Bits de configuracion
__CONFIG _XT_OSC & _PWRTE_ON & _BODEN_OFF & _CP_OFF & _WDT_OFF

ORG 0
GOTO Inicio

;Rutina de configuracion

CONF_PIC
BSF STATUS,RP0 ;Conmuta al banco 1
CLRF TRISB ;Puerto B = Salida
MOVLW b'11000100'
MOVWF OPTION_REG ;Configuracion de Timer0
BCF STATUS,RP0 ;Conmuta al banco 0
BCF INTCON,TMR0IF ;Limpiar el bit de la interrupcion
MOVLW 0
MOVWF PORTB ;Puerto B = 0000 0000
BSF INTCON,TMR0IE ;Activa Int de desbordamiento de TMR0
RETURN

;Programa principal

Inicio
CALL CONF_PIC ;Inicializar
cont1 EQU d'32' ;Declaracion de contador en memoria
IniciaContador
MOVLW d'125'
MOVWF cont1
MOVLW d'8'
MOVWF TMR0
Ciclo1
BTFSS INTCON,TMR0IF
GOTO Ciclo1
BCF INTCON,TMR0IF
DECFSZ cont1
GOTO Ciclo1
MOVLW d'1'
XORWF PORTB,1
GOTO IniciaContador
END

-------------------------------------

En el programa anterior estoy usando:

Preescaler = 32
Contador = 125
TMR0 = 8 (6 + 2, Considerando los 2 ciclos por escribir en TMR0)

Ojo: Estoy usando un cristal X-TAL de 4Mhz como oscilador y el registro OPTION_REG, tambien lo configure para usar ese oscilador y no el WDT.

En si el programa tiene que encender durante 1seg un LED y manterlo apagado durante 1seg, prenderlo de nuevo y asi indefinidamente, lo estoy simulando en ISIS PROTEUS y con el cronometro de la simulacion es como me doy cuenta de que esta desfasado al poco tiempo de ejecucion, tengo la sospecha de que sea tmb por el tiempo que toman las instrucciones para encender el LED sin embargo creo que eso seria minimo :S y no lo deberia de notar si no hasta despues de mucho tiempo...

CUALQUIER AYUDA, BIENVENIDA!!!!!!!!!!!!! GRACIAS!!!
 
Bueno miren modifique el Programa, tenia un error de logica al reescribir TMR0 :p, de tal modo que ahora

TRM0 = 0
Prescaler = 64
Oscilador = XTAL 4Mhz

Segun la formula para calcular el tamaño del Contador, con esos parametros encontre que el valor del contador debe ser: 61.03515625, sin embargo se me complica manejar fracciones y lo deje en 61 de tal modo que:

Contador = 61

Ahora tengo un desfasamiento menor pero sin embargo existe y al parecer el PIC se adelanta 1.6 minutos cada 2.7 dias (algo asi), quisiera si alguien me pueda dar una sugerencia de como compensar esto (como poder considerar esa fraccion) o si lo mejor seria cambiar la frecuencia de mi oscilador, e leeido que los relojes comerciales manejan osciladores que manejan fracciones :S (no se donde conseguir eso), bueno este es mi codigo ahora:

INCLUDE<P16F877A.INC>
LIST p=16F877A

__CONFIG _XT_OSC & _PWRTE_ON & _BODEN_OFF & _CP_OFF & _WDT_OFF ;Bits de configuracion

ORG 0
GOTO Inicio

;Rutina de configuracion
CONF_PIC
BSF STATUS,RP0 ;Conmuta al banco 1
CLRF TRISB ;Puerto B = Salida
MOVLW b'11000101'
MOVWF OPTION_REG ;Configuracion de Timer0
BCF STATUS,RP0 ;Conmuta al banco 0
CLRF PORTB ;Limpiar PORTB
RETURN

;Programa principal
Inicio
CALL CONF_PIC ;Inicializar
cont1 EQU d'32'
BCF INTCON,TMR0IF
IniciaContador
MOVLW d'61'
MOVWF cont1
Ciclo1
BTFSS INTCON,TMR0IF
GOTO Ciclo1
BCF INTCON,TMR0IF
DECFSZ cont1
GOTO Ciclo1
MOVLW d'1'
XORWF PORTB,1
GOTO IniciaContador

END

-------------------------------------------

Ojo: esta vez no escribo en el registro TMR0 asi que no considero los 2 ciclos de escritura, dejo que el TMR0 pase de 0-255

Bueno cualquier ayuda por favor no se limiten :p
 
Una sugerencia... Si es que tu proyecto utiliza una fuente a transformador puedes utilizar la salida de la onda senoidal del embobinado secundario para general una señal de reloj cuadrada de 60Hz y esta utilizarla como señal de reloj del TMR0. Este último se cargaría inicialmente con 196 para que cuando pase 1 seg (60 pulsos) el TMR0 se desborde indicando que ya transcurrió 1 seg. El programa sería:

Esp_1s_p0 ;Subrutina de tiempo de espera de 1 seg


bsf STATUS,RP0 ;Acceso a banco 1 de RAM
movlw 0x68 ;Configura el reloj externo del TMR0 y desactiva el preescaler
movwf OPTION_REG^0x80
movlw d'196'
movwf TMR0 ;Carga constante de tiempo en el TMR0
bcf INTCON,T0IF ;Borra bandera de desborde del TMRO

Esp_1sp0_bucle

btfss INTCON,T0IF ;Espera a que trancurra el tiempo fijado
goto Esp_1sp0_bucle
bcf INTCON,T0IF ;Borra bandera de interrupción del TMR0

cada que se ejecute este código puedes ir incrementado un contador que marque la cantidad de segundos transcurridos. Ahora habría que ingeniarcelas para contar más de 255 segundos concatenando varios contadores.
Saludos
 
Oh gracias, pero mi fuente de poder es un integrado regulador de voltaje de 5V (L7805CV), de cualquier forma no se como hacer eso de la bobina secundaria segun yo la fuente eliminadora de voltaje que tengo es un transformador que tiene una sola bobina :S, lo que pasa es que no tengo muchos conocimientos de electronica solo me gusta mucho :p yo soy programador.

Bueno genere una tabla en un programa que hice para calcular la frecuencia del oscilador que necesito, y el prescaler requerido, para obtener un valor para el contador que sea entero y no asignar valores a TMR0, de tal manera que lo deje incrementar de 0-255.

Esta es la TABLA, los valores del oscilador estan en MHZ:

COUNT: 25.000000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.0512
COUNT: 50.00000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.1024
COUNT: 25.000000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.1024
COUNT: 75.000000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.1536
COUNT: 100.0000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.2048
COUNT: 50.00000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.2048
COUNT: 25.000000 TMR0: 0 PREESCALER: 8 OSCILADOR: 0.2048
COUNT: 125.000000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.2560
COUNT: 150.00000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.3072
COUNT: 75.000000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.3072
COUNT: 175.000000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.3584
COUNT: 200.0000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.4096
COUNT: 100.0000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.4096
COUNT: 50.00000 TMR0: 0 PREESCALER: 8 OSCILADOR: 0.4096
COUNT: 25.000000 TMR0: 0 PREESCALER: 16 OSCILADOR: 0.4096
COUNT: 225.000000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.4608
COUNT: 250.00000 TMR0: 0 PREESCALER: 2 OSCILADOR: 0.5120
COUNT: 125.000000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.5120
COUNT: 150.00000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.6144
COUNT: 75.000000 TMR0: 0 PREESCALER: 8 OSCILADOR: 0.6144
COUNT: 175.000000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.7168
COUNT: 200.0000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.8192
COUNT: 100.0000 TMR0: 0 PREESCALER: 8 OSCILADOR: 0.8192
COUNT: 50.00000 TMR0: 0 PREESCALER: 16 OSCILADOR: 0.8192
COUNT: 25.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 0.8192
COUNT: 225.000000 TMR0: 0 PREESCALER: 4 OSCILADOR: 0.9216
COUNT: 250.00000 TMR0: 0 PREESCALER: 4 OSCILADOR: 1.0240
COUNT: 125.000000 TMR0: 0 PREESCALER: 8 OSCILADOR: 1.0240
COUNT: 150.00000 TMR0: 0 PREESCALER: 8 OSCILADOR: 1.2288
COUNT: 75.000000 TMR0: 0 PREESCALER: 16 OSCILADOR: 1.2288
COUNT: 175.000000 TMR0: 0 PREESCALER: 8 OSCILADOR: 1.4336
COUNT: 200.0000 TMR0: 0 PREESCALER: 8 OSCILADOR: 1.6384
COUNT: 100.0000 TMR0: 0 PREESCALER: 16 OSCILADOR: 1.6384
COUNT: 50.00000 TMR0: 0 PREESCALER: 32 OSCILADOR: 1.6384
COUNT: 25.000000 TMR0: 0 PREESCALER: 64 OSCILADOR: 1.6384
COUNT: 225.000000 TMR0: 0 PREESCALER: 8 OSCILADOR: 1.8432
COUNT: 250.00000 TMR0: 0 PREESCALER: 8 OSCILADOR: 2.0480
COUNT: 125.000000 TMR0: 0 PREESCALER: 16 OSCILADOR: 2.0480
COUNT: 150.00000 TMR0: 0 PREESCALER: 16 OSCILADOR: 2.4576
COUNT: 75.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 2.4576
COUNT: 175.000000 TMR0: 0 PREESCALER: 16 OSCILADOR: 2.8672
COUNT: 200.0000 TMR0: 0 PREESCALER: 16 OSCILADOR: 3.2768
COUNT: 100.0000 TMR0: 0 PREESCALER: 32 OSCILADOR: 3.2768
COUNT: 50.00000 TMR0: 0 PREESCALER: 64 OSCILADOR: 3.2768
COUNT: 25.000000 TMR0: 0 PREESCALER: 128 OSCILADOR: 3.2768
COUNT: 225.000000 TMR0: 0 PREESCALER: 16 OSCILADOR: 3.6864
COUNT: 250.00000 TMR0: 0 PREESCALER: 16 OSCILADOR: 4.0960
COUNT: 125.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 4.0960
COUNT: 150.00000 TMR0: 0 PREESCALER: 32 OSCILADOR: 4.9152
COUNT: 75.000000 TMR0: 0 PREESCALER: 64 OSCILADOR: 4.9152
COUNT: 175.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 5.7344
COUNT: 200.0000 TMR0: 0 PREESCALER: 32 OSCILADOR: 6.5536
COUNT: 100.0000 TMR0: 0 PREESCALER: 64 OSCILADOR: 6.5536
COUNT: 50.00000 TMR0: 0 PREESCALER: 128 OSCILADOR: 6.5536
COUNT: 25.000000 TMR0: 0 PREESCALER: 256 OSCILADOR: 6.5536
COUNT: 225.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 7.3728
COUNT: 250.00000 TMR0: 0 PREESCALER: 32 OSCILADOR: 8.1920
COUNT: 125.000000 TMR0: 0 PREESCALER: 64 OSCILADOR: 8.1920
COUNT: 150.00000 TMR0: 0 PREESCALER: 64 OSCILADOR: 9.8304
COUNT: 75.000000 TMR0: 0 PREESCALER: 128 OSCILADOR: 9.8304
COUNT: 175.000000 TMR0: 0 PREESCALER: 64 OSCILADOR: 11.4688
COUNT: 200.0000 TMR0: 0 PREESCALER: 64 OSCILADOR: 13.1072
COUNT: 100.0000 TMR0: 0 PREESCALER: 128 OSCILADOR: 13.1072
COUNT: 50.00000 TMR0: 0 PREESCALER: 256 OSCILADOR: 13.1072
COUNT: 225.000000 TMR0: 0 PREESCALER: 64 OSCILADOR: 14.7456
COUNT: 250.00000 TMR0: 0 PREESCALER: 64 OSCILADOR: 16.3840
COUNT: 125.000000 TMR0: 0 PREESCALER: 128 OSCILADOR: 16.3840
COUNT: 150.00000 TMR0: 0 PREESCALER: 128 OSCILADOR: 19.6608
COUNT: 75.000000 TMR0: 0 PREESCALER: 256 OSCILADOR: 19.6608

Ya probe estos valores en el ISIS PROTEUS y funcio a la perfeccion, ahora no se si sea posible encontrar un cristal con alguna de esas frecuencias o generar uno con esa frecuencia, bueno con eso generaria un conteo de segundos muy exacto...
 
COUNT: 150.00000 TMR0: 0 PREESCALER: 16 OSCILADOR: 2.4576
COUNT: 75.000000 TMR0: 0 PREESCALER: 32 OSCILADOR: 2.4576

Muy bien, siguiendo entonces tu diseño, he revisado y comprobado que existe exactamente el cristal de 2.4576 (He de suponer que se trata de 2.4576 MHz; Veo que vives en México, la página que he consultado es de una tienda que está precisamente en el centro. Saludos
 
Oh muchas gracias, si al parecer encontre un cristal que queda perfecto "Cristal De Cuarzo Lp 32.768khz Para Rtc", lo vi en mercado libre :p, no sabia que habia cristales especificamente diseñados para aplicaciones de tiempo real, eso me facilita las cosas.

Intente utilizar una rutina delay para conpensar el deafase pero como son varios ciclos el delay que produce ejecutar las instrucciones me causa de nuevo el desfase y se me complica mucho, entonces opte mejor por usar el cristal, bueno aqui pongo los valores que me sirvieron por si a alguien les sirven, con esto optengo mucha mayor presicion en el temporizador.

Contador: 16
Prescaler: 2
TMR0: 0
Oscilador: 0.032768 Mhz

Gracias por la ayuda
 
Atrás
Arriba