Optimizar temporizacion un segundo exacto con microchip 16f690

Hola para un proyecto de un reloj estaba tratando de temporizar 1s, utilizando el timer0, ya realize una rutina que se supone que realiza esto. Calcule que esta rutina por dia atrasaria mi reloj 3.25 minutos, a la semana 22.75 minutos, lo cual me parece bastante. Como oscilador se esta usando el oscilador interno del pic. En fin queria ver si habia una forma de optimizar el programa para que la temporizacion sea mas exacta.

Se que hay circuitos integrados que dan una referencia de frecuencia mas exacta, pero no pienso utilizarlos en este proyecto, unicamente voy a utilizar el microcontrolador, por lo que estos CI no son una opcion

Gracias de antemano por las respuestas :)

Voy a colocar el programa el cual funciona asi:

1. Inicializacion: Configura Puerto c como salida, configura Timer con registro "option" y configura interrupciones con registro "intcon".
2. Rutina Principal: Carga los valores para el "timer" y "segundero" (variable para temporizar), saca al puerto c una variable q se llama "display" (que inicialmente esta en cero), cada vez que pase un segundo esa variable se incrementa.
3. Desborde: Cuando se desborda el timer incrementa "segundero" , cuando segundero se desborda se termina la temporizacion y hace un call a una rutina (temp.acabo) la cual incrementa la variable "display" para luego mostrarla en cuatro leds colocados en el puerto c.

Código:
    list      p=16F690            ; list directive to define processor
    #include <p16F690.inc>        ; processor specific variable definitions
    errorlevel  -302              ; suppress message 302 from list file
    __CONFIG   _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF 

	CBLOCK	0X20
SEGUNDERO			;VARIABLE PARA CONTAR UN SEGUNDO
DISPLAY
	ENDC

	CBLOCK	0X70		;REGISTROS TEMPORALES
STATUS_TEMP
WORK_TEMP
	ENDC

	REPETICIONES EQU	D'131'
	
;--------------------------DIRECCION 0000H, AQUI APUNTA CUANDO SE HACE UN RESET---------------------------
	ORG 0
	GOTO 	INICIALIZACION	;SALTA A INICIO YA QUE A CONTINUACION VIENE EL VECTOR DE INTERRUPCION
;--------------------------------------VECTOR DE INTERRUPCION---------------------------------------------
	ORG 4
	GOTO	DESBORDE		;RUTINA DE SERIVICO DE INTERRUPCION
;--------------------------------------PROGRAMA PRINCIPAL-------------------------------------------------	
	ORG 5
INICIALIZACION:
	CLRF	PORTC		;LIMPIA EL PUERTO C
	BSF	STATUS, RP0	;BANCO1
	CLRF	TRISC		;PUERTO C COMO SALIDA
	MOVLW	B'00000101'	;CONFIGURA TIMER0 CON: FUENTE DE OSCILADOR INTERNO, INCREMENTO EN 
				;FLANCO DE SUBIDA,
	MOVWF	OPTION_REG	;PRESCALER ENTRE 64, Y LO ESCRIBE EN OPTION
	MOVLW	B'10100000'	;SE VA A GRABAR EN INTCON LA HABILITACION DE GIE Y T0IE
	MOVWF	INTCON		;SE ESCRIBE PARA CONFIGURAR LAS INTERRUPCIONES POR DESBORDE DEL TIMER
	BCF	STATUS, RP0	;BANCO0
	CLRF	DISPLAY		;SE ASEGURA QUE DISPLAY SEA CERO

UNSEGUNDO: ;AQUI CARGA POR PRIMERA VEZ LO NECESARIO EN EL TIMER 
	       ;Y EN LA VARIABLE PARA REALIZAR LA TEMPORIZACION
	MOVLW	REPETICIONES	;ESCRIBO 125 EN W PARA CONFIGURAR EL TIMER0 Y LA VARIABLE SEGUNDERO
	MOVWF	SEGUNDERO	;CONFIGURO SEGUNDERO
	MOVWF	TMR0		;CONFIGURO TIMER
RUTINAPRINCIPAL:
	BTFSC	DISPLAY,4	;CHEQUEA SI LLEGO A 16
	CALL	LIMPIAR		;VA A RESETEAR EL CONTADOR
	MOVF	DISPLAY,W	;PASA DISPLAY A W
	MOVWF	PORTC		;LO DESPLIEGA EN EL PUERTO C
	GOTO	RUTINAPRINCIPAL
LIMPIAR:
	CLRF	DISPLAY
	RETURN

;---------------------------------------------RUTINA-DE-SERVICIO-DE-INTERRUPCION---------------------------
DESBORDE:
	MOVWF 	WORK_TEMP	;GRABA EL REGISTRO DE TRABAJO EN SU REGISTRO TEMPORAL
	SWAPF 	STATUS,0 		;INTERCAMBIA LOS BITS MAS ALTOS Y MAS BAJOS DE STATUS Y LOS GRABA EN W
	CLRF 	STATUS 		;LIMPIA STATUS Y SE DEVUELVE A BANCO0, INDEPENDIENTE DE DONDE ESTABA
	MOVWF 	STATUS_TEMP 	;GRABA STATUS EN STATUS_TEMP PARA Q NO SE PIERDA
;---------------------------------AQUI-SE-PONE-LA-RUTINA-PARA-ATENDER-LA-INTERRUPCION-----------------------
	INCFSZ	SEGUNDERO,F	;INCREMENTA LA VARIABLE DE TEMPORIZACION
	GOTO	SIGUE
	CALL	TEMP.ACABO	;AQUI SE PONE LO QUE QUIERE Q SE REALIZE CUANDO TERMINE LA 
				;TEMPORIZACION DE 1 SEGUNDO
SIGUE:
	MOVLW	REPETICIONES	;ESCRIBO 125 EN W PARA CONFIGURAR TMR0
	MOVWF	TMR0		;CONFIGURO TIMER
;---------------------------------AQUI-TERMINA-LA-RUTINA-PARA-ATENDER-LA-INTERRUPCION-----------------------
	SWAPF 	STATUS_TEMP,0 	;LE DA VUELTA A STATUS DEJANDOLO IGUAL QUE ANTES Y LO GRABA EN W
	MOVWF 	STATUS		;DEJA STATUS COMO ESTABA ANTES
	SWAPF 	WORK_TEMP,1	;LE DA VUELTA Y LO GRABA EN EL MISMO
	SWAPF 	WORK_TEMP,0	;LE DA VUELTA DEJANDOLO IGUAL Y LO DEVUELVE A W
	BCF	INTCON, T0IF	;LIMPIA EL FLAG DE LA INTERRUPCION DEL TIMER0
	RETFIE					;TERMINO DE ATENDER LA INTERRUPCION
;-----------------------------------TERMINA-LA-RUTINA-DE-SERVICIO-DE-INTERRUPCION---------------------------

TEMP.ACABO:
	INCF	DISPLAY		;INCREMENTA
	MOVLW	REPETICIONES	;ESCRIBO 125 EN W PARA CONFIGURAR TMR0
	MOVWF	SEGUNDERO	;CONFIGURO SEGUNDERO
	RETURN

	END
[/code]
 
Prodria ser velocidad del nucleo=1Mhz, preescalador=16, timer0 valor max 250 * 250 el registro de conteo sale 1000000uS eso lo hice con un atmel.
 
Atrás
Arriba