# Ciclos de reloj y tiempo para delays 16f84



## RBX374 (Jul 15, 2009)

Pues estoy trabajando con delays en un pic16f84a, un cristal de 4MHz, y quiero calcular el tiempo que hago de retardo con una delay. 4 MHz son 4.000.000Hz que quiere decir que una instruccion tarda 4us que son 0,004ms, no? Me parece que no iba así. Cuanto tarda en ejecutar una instrucción?

Porque cuanto tardaría en ejecutar esto?


DELAY

	movlw	0xFF
DLOOP
	movwf	DCOUNT
	nop
	decfsz	DCOUNT,W
	goto	DLOOP

	movlw	0xFF
DLOOP2
	movwf	DCOUNT
	nop
	decfsz	DCOUNT,W
	goto	DLOOP2


Gracias


----------



## RBX374 (Jul 15, 2009)

A ver, os ahorro la tarea de contar las instrucciones de este programa que he escrito:

unas 2040 instrucciones? y esto cuanto tiempo demora al pic¿


seria esto, verdad? Esque en Micros me estoy iniciando y ops:


----------



## george.manson.69 (Jul 15, 2009)

hola...el reloj del pic se divide entre 4....4Mhz/4=1Mhz

en pocas palabras las instrucciones duran 1uS.

entonces :

```
delay       movlw 0xFF
                movwf variable_1

delay_1  movlw 0xFF
               movwf variable_2
delay_2   decfsz variable_2,F
               goto delay_2
               decfsz variable_1,F
               goto delay_1
               return
```

este instrucciones va tardar....si vemos la variable 1 se carga con 255 y variable dos tambien
entonces se va a decrementar variable_2 uno en uno, osea va tardar 255 ciclos, cuando termine de 
decrementar va a decrementar a uno la variable 2, y asi sucesivamente, hasta decrementar la variable 1 hasat cero y regresa..

255x255=65025 ciclos y eso se multiplica por el tiempo 
65025x1uS=65.025 mS de retardo.


----------



## RBX374 (Jul 15, 2009)

Ah claro ya lo entiendo! Luego para crear un delay de más de medio segundo necesito tres variables, y hacerlas encadenadas en vez de consecutivas. Con tres variables consigo un delay máximo de 255*255*255 que son aprox 16000000 uS= 16 segundos.

Por lo que veo, la instrucion de goto no gasta tiempo? Porque hay un poquito más de instrucciones de las que has dicho

Lo que tampoco entiendo es porque pones decfsz variable_2, F , no tendría que ser decfsz variable_2,variable_2?


porque la idea de incluir de incluir instrucciones de no-operacion para que cada ciclo tenga más instrucciones?


----------



## george.manson.69 (Jul 15, 2009)

goto consume 2 ciclos y si afecta...mucho si usas este metdo de temporizacion...yo he usado el timer0...
pero por ahora te consego que vas asi bien por ahora...

ahora usa decfsz variable_1,F esta instruccion decrementa la variable y la guarada el resultado en el misma variable,

variable_2=variable_2-1

y asi...

si usas decfsz variable_2,w

solo haces..

w=variable_2-1

y no te va funcionar porque el regitro w es donde se guarda temporalmente un valor, y ese valor lo desecha cuando se sobre escribe en w.

por ejemplo:

movlw 0x01      ;carga w con 1
movlw 0x02      ;borra el uno de w y guarda a w el 2
movwf variable ; y lo que se va a guardar en la variable es lo que tuvo lo ultimo guardado en w.

espeor que no te alla confundido


----------



## mabauti (Jul 15, 2009)

el MPLab trae un contador de ciclos.


----------



## Vick (Jul 15, 2009)

Si, puedes hacer bucles anidados para lograr retardos muy largos, las instrucciones duran un ciclo de máquina, para un oscilador de 4MHz es 1µs, exepto las de salto que duran dos ciclos, por ejemplo goto o call, y en las condicionales como decfsz que duran un ciclo mientras la condición no se cumple y dos ciclos cuando la condición se cumple y salta...

Si necesitas calcular retardos de forma rápida y fácil usa alguno de estos programas:

http://www.golovchenko.org/cgi-bin/delay

http://www.todopic.com.ar/utiles/calcular_retardos.zip

La F en decfsz variable_2, F indica que el resultado será guardado en el mismo registro variable_2... las instrucciones nop se usa para aumentar el tiempo del bucle o ajustar, cada nop gasta un ciclo de máquina.


----------



## entropio (Oct 13, 2010)

jejeje creo que me ayudarian si  tengo un reloj int del pic 16f628a a 37KHz cuanto tiempo tarda cada instruccion.

por que si entiendo en el caso de tener un reloj a 4Mhz , un ciclo mauina tarda 4 ciclos reloj
entonces 1Mciclos maquina =4Mciclos Reloj, pero de donde sacan eso de que cada instrucion maquina tarda 1us jejeje 

necesito algo de matematicas si alguien me lo puede explicar y para el reloj de 37Khz interno del pic 16F628A


----------



## Atreides (Oct 14, 2010)

Paso a paso
Para 4Mhz, un ciclo reloj es 1/4000000=0.25us. Un ciclo máquina son cuatro ciclos reloj 4*0.25us=1us.
Para 37Khz, un ciclo reloj es 1/37000=27.027us. Un ciclo máquina 4x27.027us=108.108us.
Cada instrucción dura un ciclo máquina, excepto las de salto como goto, call, y las decfs dependen de si se cumple el salto o no.


----------



## Meta (Oct 15, 2010)

Si quieres saber de retardos puedes hacerlo por aquí.

http://www.golovchenko.org/cgi-bin/delay

Saludo.


----------



## Protoboard (Oct 15, 2010)

En esta página puedes encontrar una explicación detallada de como realizar retardos por software en microcontroladores pic

http://micropic.wordpress.com/2007/02/09/retardos-por-software/


----------



## Meta (Oct 15, 2010)

En este libro también.

www.pic16f84a.org

Saludo.


----------



## Protoboard (Oct 15, 2010)

Ese libro es muy bueno, pero la página que puse tiene la ventaja de que es gratis, está disponible las 24 horas y explica paso a paso como calcular los retardos. Resumiendo: es genial! y no lo digo porque yo sea el autor


----------



## Meta (Oct 15, 2010)

Parece que la idea es sacado del libro. Pues si, está bien explicado. Hace tiempo que ya no actualizas tu blog. 

PD:_ Juraría que tenías otro nick._


----------



## Protoboard (Oct 15, 2010)

Conozco el libro pero la verdad es que nunca lo he usado. Al final no importa si se aprende con el libro o con la página, lo cierto es que la idea es la misma. Lo importante es darse cuenta que siguiendo una lógica muy sencilla se pueden programar retardos de cualquier duración.

También hay que tener en cuenta que los retardos son útiles pero tienen su lado oscuro y es que esclavizan al micro a realizar la misma tarea (el retardo en si mismo) durante todo el tiempo que dura éste por lo que se desperdician muchos ciclos de proceso. Una solución para esto puede ser usar alguno de los timers. Por ejemplo el temporizador timer 0.

PD: @Meta no te equivocas, pero el otro nick quedó arrumbado hace tiempo así que esto es borrón y cuenta nueva


----------



## anthony123 (Abr 20, 2013)

Hablando de ciclos de reloj, ¿Cual es la manera más efectiva para introducir un delay de 10,20 o 30 min en un microcontrolador? (para evitar que éste se "pierda")


----------



## Meta (Abr 20, 2013)

Hola:

Mira aquí.
http://electronica-pic.blogspot.com.es/2012/02/retardos-para-pic12f-16f-y-18f.html

Saludo.


----------



## anthony123 (Abr 20, 2013)

Muchas gracias, pero tendrás alguna recomendación en C?

Saludos!


----------



## D@rkbytes (Abr 21, 2013)

anthony123 dijo:


> Hablando de ciclos de reloj, ¿Cual es la manera más efectiva para introducir un delay de 10,20 o 30 min en un microcontrolador? (para evitar que éste se "pierda")


Este ejemplo que adjunto en PICC, sirve para hacer un retardo de 1 segundo.
Puede ser usado para hacer un RTC (Reloj en Tiempo Real)
Se basa en usar un cristal de 32768 Hz con el oscilador externo T1OSI, T1OSO de algunos PIC.
Este ejemplo puede ser usado como base para lograr retardos de tiempo largos (Horas)
Incluso para hacer un reloj con displays en modo multiplex, ya que la temporización no afecta el programa.

Notas:
Programa para un 16F628A (Aplicable a otros PIC con los cambios básicos al programa)

Saludos.


----------



## ellautis (Jul 7, 2014)

Hola amigos . uds saben como se puede hacer prender una secuencia determinada 24 veces por segundo?? seria con un pic 16f628. la idea es hacer que entren 24 escenas en un segundo para 8 leds. 

Saludos


----------



## Daniel Meza (Jul 7, 2014)

ellautis dijo:


> Hola amigos . uds saben como se puede hacer prender una secuencia determinada 24 veces por segundo?? seria con un pic 16f628. la idea es hacer que entren 24 escenas en un segundo para 8 leds.
> 
> Saludos



Divides 1Seg/24 y el valor que obtengas de tiempo lo generas con ayuda de un Timer. Ya sea por interrupción o testeo cada que transcurra un desborde del TMR actualizas los datos de los leds para generar el efecto de las escenas


----------



## ellautis (Jul 8, 2014)

Muchas gracias por la explicacion Daniel , Me podrias dar un ejemplo sencillo de como configurar el tiempo en el Timer? solo para orientarme un poco.

Saludos y muchas gracias por la ayuda.


----------



## Daniel Meza (Jul 8, 2014)

La ecuación para el tiempo, considerando que usas el TMR1 (es de 16 bits y dará mayor flexibilidad que el TMR0):

TMR1=2^16-(Fosc*T)/(4*Pree)

Fosc=Frecuencia del cristal que uses
T=1/24
Pree: Divisor usado en el preescaler, ya sea 2,4,8 o 16

el resultado que te de ese cálculo será el que le tendrás que cargar al TMR1. El algoritmo sería así:

-Configurar T1CON para fuente de reloj interna, preescaler deseado 
-Poner a 0 bandera de interrupción del TMR1 (TMR1IF) presente en el registro PIR1
-Cargar resultado del cálculo en los registros TMR1H y TMR1L
-Activar reloj del TMR1 por medio del bit TMR1ON presente en el registro T1CON
-Esperar a que se ponga en uno la bandera de interrupción del TMR1 

La ejecución de el procedimiento anterior tomará 1/24 seg, lo que necesitas temporizar entre cada escena


----------



## Lucas Reggiani (Dic 10, 2015)

D@rkbytes dijo:


> Este ejemplo que adjunto en PICC, sirve para hacer un retardo de 1 segundo.
> Puede ser usado para hacer un RTC (Reloj en Tiempo Real)
> Se basa en usar un cristal de 32768 Hz con el oscilador externo T1OSI, T1OSO de algunos PIC.
> Este ejemplo puede ser usado como base para lograr retardos de tiempo largos (Horas)
> ...



Hola D@rkbytes:

            He descargado tu programa y en la simulacion me andubo perfectamente, pero me surgio un problema, y es que durante la interrupcion quize agregar una suma(de una variable seg)y la cuestion es que pruebo el programa y no va para atras ni para adelante, y eso que trate de usar condicioness sencillas para seguir mi avance, aca dejo el codigo fallido 


```
/*******************************************************************************
* Compilador: CCS PCM C Compiler, Versión 4.140
* Programa: Timer_1Seg.C
* Versión: 1.0
* Autor: D@rkbytes
* Compañia: Digitek
* Notas: 
* Timer de un segundo con TMR1 (16 Bits)
* Se usará el oscilador interno a 4 MHz.
* El externo en RB6 y RB7, con un cristal de 32768 Hz.
*******************************************************************************/
#include <16f887.h>

int seg=0;

#use     delay(internal=4mhz)
/* Estableciendo lo anterior en este PIC...
La palabra de configuración (Fuses) qué dará el compilador, está bien así.
INTRC/IO,PWRTE=ON,MCLRE=ON,BOREN=ON */
#byte    PORTA = getenv("SFR:PORTA")   // Referencia del registro PORTA
#bit     RA1 = PORTA.1                 // Definir RA1
#bit     RA2 = PORTA.2                 // Definir RA2

// Controlador de la interrupción por desborde del TMR1  
#int_timer1 
void tmr1_int(void){
   clear_interrupt(int_timer1);     // Limpiar flag por desborde del TMR1
   set_timer1(0x8000);             // Recargar el TMR1 con 32768
// RA2 = ~RA2;                    // Toggle en RA2 (Otra forma de hacer toggle)
   seg++;                    // Esto se hará cada 1 segundo.
                                    
} 
//--------------------------MUESTREO-------------------------------------------


//----------------------------------o------------------------------------
void main(void){ 
   set_tris_a(0b11111001);          // RA1 y RA2 como salidas
   setup_timer_1(t1_external_sync|t1_div_by_1|t1_clk_out);
   enable_interrupts(int_timer1);   // Habilitar interrupción del Timer 1 
   enable_interrupts(global);       // Habilitar interrupciones globales 
   set_timer1(0x8000);              // Cargar el TMR1 con 32768
   
   while(true){                     // Hacer un bucle infinito del programa.
   
      
         if(seg<10){
               output_high(PIN_A0);
               output_high(PIN_A1);
               output_high(PIN_A2);
         }
         if(seg>10){
               output_high(PIN_A3);
               output_high(PIN_A4);
               output_high(PIN_A5);
         }
   
   }
}
```


----------



## D@rkbytes (Dic 10, 2015)

Es que debiste hacer unos cambios.
TRISA está configurado para que RA1 y RA2 sean salidas, pero tú quieres usar desde RA0 hasta RA5 como salidas.

Entonces el programa quedaría así:

```
#include <16f887.h>
#use     delay(internal=4mhz)

int8 seg=0;

// Controlador de la interrupción por desborde del TMR1  
#int_timer1 
void tmr1_int(void){
   clear_interrupt(int_timer1);     // Limpiar flag por desborde del TMR1
   set_timer1(0x8000);              // Recargar el TMR1 con 32768
                                    // Esto se hará cada 1 segundo.
   seg ++;
} 

void main(void)
{
   setup_timer_1(t1_external_sync|t1_div_by_1);
   enable_interrupts(int_timer1);   // Habilitar interrupción del Timer 1 
   enable_interrupts(global);       // Habilitar interrupciones globales 
   set_timer1(0x8000);              // Cargar el TMR1 con 32768
   
   while(true)
   {
      if(seg<10)
      {
         output_high(PIN_A0);
         output_high(PIN_A1);
         output_high(PIN_A2);
      }
      
      if(seg>10)
      {
         output_high(PIN_A3);
         output_high(PIN_A4);
         output_high(PIN_A5);
      }
   }
}
```
Ten en cuenta que la variable "seg" siempre seguirá en incremento hasta que se desborde.
*int *en PIC C Compiler es de 255 bits. (1 Byte)

Con un "*else*" en vez de:* if(seg>10)* se logra el mismo resultado.


----------



## FJMAN (May 14, 2016)

Hola D@rkbytes, con tu permiso yo también he modificado tu programa, gracias por compartirlo, muy levemente para intentar algo simple pero tengo alguna pega.
Necesito realizar temporizaciones distintas dependiendo del estado de RA0 y deben ser lo más precisas posible, sobre todo las más largas, para no ganar o perder mucho tiempo al menos durante las 24H que se usará el circuito.
Las temporizaciones necesarias son las siguientes:
27 segundos led apagado y 3 segundos led activo y vuelta a empezar.
60 segundos led apagado y activo el led 1,1 segundos y vuelta a empezar.
El caso es que los tiempos no me cuadran mucho, sobre todo el de 60/1,1 y me he dado cuenta que el reinicio de la variable seg despues de hacer el delay no sirve para lo que yo busco, el timer1 sigue contando independientemente de los delay que ponga por lo que tendría que añadirle ese 0,1 segundos de más en este segundo caso. Creo que la manera de hacer esto puede ser más sencilla de lo que yo pienso, parar y reiniciar el timer1??, pero me he quedado en blanco y pienso que la voy a liar...
El estado de RA0 solo sería necesario comprobarlo una vez, en el arranque del programa, y dependiendo de ello funcionar 24H y ya. Veo innecesario comprobarlo cada segundo, como lo hago? el tener la interupción por medio hace que me pierda en el programa... jejeje:


```
/*******************************************************************************
* Compilador: CCS PCM C Compiler, Versión 4.140
* Programa: Timer_1Seg.C
* Versión: 1.0
* Autor: D@rkbytes
* Compañia: Digitek
* Notas: 
* Timer de un segundo con TMR1 (16 Bits)
* Se usará el oscilador interno a 4 MHz.
* El externo en RB6 y RB7, con un cristal de 32768 Hz.
*******************************************************************************/
#include <16f628a.h>
int seg=0;
#use     delay(internal=4mhz)
#byte    PORTA = getenv("SFR:PORTA")   // Referencia del registro PORTA
#byte    PORTB = getenv("SFR:PORTB")   // Referencia del registro PORTB
#bit     RB0 = PORTB.0                 // Definir RB0
#bit     RB1 = PORTB.1                 // Definir RB1
#bit     RA0 = PORTA.0                 // Definir RA0
// Controlador de la interrupción por desborde del TMR1  
#int_timer1 
void tmr1_int(void)
{
   clear_interrupt(int_timer1);     // Limpiar flag por desborde del TMR1
   set_timer1(0x8000);             // Recargar el TMR1 con 32768
   RB1 = ~RB1;                      // Toggle en RB1 (Otra forma de hacer toggle)
   seg++;                               // Esto se hará cada 1 segundo.
} 
 
void main(void)
{
   set_tris_a(0x1F);     // Puerto A como entradas.
   set_tris_b(0x00);     // Puerto B como salidas.
   setup_timer_1(t1_external_sync|t1_div_by_1|t1_clk_out);
   enable_interrupts(int_timer1);   // Habilitar interrupción del Timer 1 
   enable_interrupts(global);       // Habilitar interrupciones globales 
   set_timer1(0x8000);              // Cargar el TMR1 con 32768
   
   while(true)
   {                     // Hacer un bucle infinito del programa.
     If (input (pin_A0)==0)
       {
        if(seg<27)
                RB0 = 0;
         else
            {
              RB0 = 1;
              delay_ms (3000);
              RB0 = 0;
              seg=0;
            } 
       } 
     else
        {
        if(seg<60)
             RB0 = 0;  
         else
            {
              RB0 = 1;
              delay_ms (1100);
              RB0 = 0;
              seg=0;
            } 
         
       }
   }
}
```


----------



## D@rkbytes (May 14, 2016)

FJMAN dijo:


> El estado de RA0 solo sería necesario comprobarlo una vez en el arranque del programa y dependiendo de ello, funcionar 24H y ya.
> Veo innecesario comprobarlo cada segundo. ¿Cómo lo hago?


Saludos.
Puedes usar una bandera que le indique al programa si RA0 se encontraba en 1 o en 0 al inicio.

Algo así:

```
void main (void)
{
   int1 flag_init = input(PIN_A0);
   
   
   while (true)
   {
      if(flag_init)
      {
         // Código
      }
      else
      {
         // Código
      }
   }
}
```


----------



## FJMAN (May 14, 2016)

Gracias por la respuesta, el problema que más me trae de cabeza es la temporización de 1,1 segundos y luego hacer los 60 segundos con la mayor precisión posible. Creo que la opción más sencilla sin usar delay sería poner un timer que desborde cada 100ms, contar 600 interrupciones, encender, contar 11, apagar y a correr.
Salu2


----------



## FJMAN (May 21, 2016)

Hola otra vez, he seguido con los cambios y la simulación en Proteus funciona al pelo, lo compilo ok pero lo grabo y no funciona. He usado tu programa pero con un cristal de 4 Mhz para hacer una temporización de 100mSeg. El circuito esta bien echo ya que con otro programa anterior funciona bien, la única diferencia es la conexión del cristal.
En mi anterior programa el circuito tenía un cristal de 4 mhz conectado en las patillas 15 y 16, OSC1 y OSC2 para usar un cristal externo, pero en este usamos el oscilador interno y un cristal de 4Mhz, en mi caso, conectado en las patillas 12 y 13, T1CKI y T1OSI.
A la hora de grabar el PIC, uso ICprog 1.05C, entiendo que solo debo seleccionar en oscilador XT y el bit de configuración PWRT.
Adjunto programa para ver si alguien puede decirme que hago mal
	
	



```
/*******************************************************************************
* Compilador: CCS PCM C Compiler, Versión 4.140
* Programa: Timer_100mSeg.C
* Versión: 1.0	
* Autor: FJM@N
* Timer para 60/1,1_27/3 segundos con TMR1 (16 Bits)
* Oscilador interno a 4 MHz.
* Oscilador externo en RB6 y RB7, con un cristal de 4 MHz.
*******************************************************************************/
#include <16F628A.h>
#FUSES NOWDT
#FUSES PUT                      //Power Up Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#use delay(clock=4000000)
#byte    PORTA = getenv("SFR:PORTA")   // Referencia del registro PORTA
#byte    PORTB = getenv("SFR:PORTB")   // Referencia del registro PORTB
#bit     RA0 = PORTA.0                 // Definir RA0
#bit     RB0 = PORTB.0                 // Definir RB0
int16 COUNT;

#int_TIMER1
void  tmr1_int(void) 
{
   clear_interrupt(int_timer1);     // Limpiar flag por desborde del TMR1
   set_timer1(0x3CC2);              // Recargar el TMR1 con 15554
   COUNT++;                         // Aumentamos la cuenta de las interrupciones
}

void main(void)
{
   set_tris_a(0b11111111);          // RA0 entrada
   set_tris_b(0b11111110);          // RB0 salida
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_8|T1_CLK_OUT|T1_EXTERNAL_SYNC);      //131 ms overflow
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   set_timer1(0x3CC2);              // Recargar el TMR1 con 15554
   While (COUNT>=1)
   If (RA0==0)
         {
            if (COUNT<12) //Cada interrupcion dura 0,1 segundos//Contamos 1,1 Segundos
                 RB0 = 1;
	       else
		  RB0 = 0;
            if (COUNT==612) //Contamos 60 + 1,1 Segundos
            {
            RB0 = 1;
            COUNT=1;
            }
         }
         Else
            {
            if (COUNT<31) //Cada interrupcion dura 0,1 segundos//Contamos 3 Segundos
                RB0 = 1;
	       else
	        RB0 = 0;		  
            if (COUNT==301) //Contamos 27 + 3 Segundos
            {
            RB0 = 1;
            COUNT=1;
            }  
            }

 }
```
:


----------



## D@rkbytes (May 21, 2016)

FJMAN dijo:


> En mi anterior programa el circuito tenía un cristal de 4 mhz conectado en las patillas 15 y 16, OSC1 y OSC2 para usar un cristal externo, pero en este usamos el oscilador interno y un cristal de 4Mhz, en mi caso, conectado en las patillas 12 y 13, T1CKI y T1OSI.


No creo que usando un cristal de 4 MHz para la sincronización externa del Timer 1, llegue a funcionar.
El oscilador del Timer 1 está específicamente diseñado para trabajar con un cristal de 32,768 KHz.



FJMAN dijo:


> He usado tu programa pero con un cristal de 4 Mhz  para hacer una temporización de 100mSeg.
> El circuito está bien hecho ya  que con otro programa anterior funciona bien, la única diferencia es la  conexión del cristal.


En dado caso que el cristal de 4 MHz llegara a oscilar para el Timer 1, el valor para que desborde cada 100 ms, no es correcto.
Debería ser de: 53036 (0xCF2C) y en este caso con el prescaler a 1:8​


FJMAN dijo:


> Entiendo que sólo debo seleccionar en oscilador XT y el bit de configuración PWRT.


Seleccionar el fuse XT (XT_OSC) es para que el oscilador principal funcione con un cristal. (Obviamente externo y hasta 4 MHz.)
El fuse PUT (PWRTE) es opcional, pero es recomendable usarlo porque temporizará cerca de 72 ms después de conectada la alimentación del PIC, manteniéndolo en estado de reset.
Luego de este tiempo el PIC empezará a ejecutar el programa.
Es útil para esperar a que la tensión de alimentación se estabilice.

Puedes usar un cristal de 4 MHz, y configurar el Timer 1 para que use el interno a 4 MHz.
Y si usas un cristal de 32,768 KHz para el Timer1, el valor para que desborde cada 100 ms. es de: 65434 (0xFF9A) y ésto si se usa el prescaler 1:8


----------



## FJMAN (May 21, 2016)

Nuevamente gracias por responder. Como ya imaginaba el problema es el cristal y la configuración de este que me he liado pero bien. Acabo de leer que ese oscilador es igual al oscilador interno en modo LP, o sea, solo hasta 200.000Khz.

Los calculos estan mal por que di por hecho que eran los mismos que con el timer1 en modo temporizador y me salía preescaler de 2 y precarga de 15536 para el overflow. Al simularlo ya ví que iba demasiado rápido, cambié el preescaler a 8 y ya contaba bién, se pasaba en unos 36 useg, por eso luego le puse 15554. Con ese valor salía exacto o +/- 4useg después de unas tres horas.
El fuse PUT lo puse por que hasta que se inicializaba todo notaba que era un poco aleatoria la primera interrupción y el resto mucho más exacta. Me aseguré de ello contando realmente el resto de interrupciones después de esta primera interrupción y es bastante preciso ahora.
Prefiero usar el cristal de 4 Mhz como comentas ya que anteriormente lo usaba y el circuito ya está incluso montado de hace años, cambiar algo sería engorroso y el problema era... es... la inexactitud del propio código a base de delays.... voy a ello...
Gracias por todo.

Salu2


----------

