TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: DarkVect en 11 de Febrero de 2008, 10:18:08

Título: Problema de precisión con set_timer0()
Publicado por: DarkVect en 11 de Febrero de 2008, 10:18:08
Hola amigos, quiero conseguir que el Timer0 me salte cada 0,1ms. Para ellos utilizo un cristal de 4MHzy precargo el timer0 a 156 de forma que el tiempo de interrupción me queda:

T=(256-156)*(4/4·10^6)=0,0001

Dentro del Timer tengo el siguiente código:

Código: [Seleccionar]
#INT_TIMER0
void Interrupcion_Timer0()                         
{
   set_timer0(156);
   nClocks++;

   if(nClocks==40000)
   {
      nClocks=0;
      output_toggle(LED);
   }
}

De forma que el led debería cambiar cada 4 segundos. Pues bien, ni por asomo se acerca a ese valor. De hecho el tiempo que obtengo es de 5,36 a 5,44 dependiendo de mi capacidad de reacción al parar el crono. La variable nClocks es un int16.

El Timer está configurado así:

Código: [Seleccionar]
setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);     
setup_TIMER_1(T1_DISABLED);
setup_TIMER_2(T2_DISABLED,0,1);

He probado a quitar el set_timer0(156) y entonces la temporización es exacta a 10,24 segundos, como debe ser.

Qué estoy pasando por alto?

Se os ocurre otra forma de conseguir los 0,1ms.

Olvidé decir que programa en CCS, que el PIC es un 16F818 y que en el main no hay nada, es un simple bluce do-while vacío.
Título: Re: Problema de precisión con set_timer0()
Publicado por: DarkVect en 11 de Febrero de 2008, 13:43:53
He hecho alguna prueba más y me pasa algo muy raro; cuando escalo el timer por un valor grande, 128 por ejemplo, me temporiza bien con el set_timer0(). Sin embargo si lo escalo a 1 o 2 o 4 no funciona bien.

Creo que tiene que ver que la variable que cuenta el número de interrupciones sea int16, puede ser? Es mejor que cuente con dos int8 anidados?

Gracias!!
Título: Re: Problema de precisión con set_timer0()
Publicado por: DarkVect en 11 de Febrero de 2008, 13:52:07
Me respondo a mi mismo, anidando pasa lo mismo. HE probado con un ejemplo de lo más simple y no soy capaz de ver dónde está el error:

Código: [Seleccionar]
#include <16LF84A.h>                               //pic a utilizar

#fuses XT
#fuses NOWDT
#fuses PROTECT
#fuses PUT

#use delay (clock=4000000)                         
#use fast_io(a)
#use fast_io(b)

#define LED PIN_A1                                 //LED de funcionamiento


int16 nClocks=0;


#INT_TIMER0
void Interrupcion_Timer0()
{
   set_timer0(56);
   nClocks++;                                     

   if(nClocks==25000)                                 
   {
      nClocks=0;
      output_toggle(LED);
   }
}


void main(void)
{
   disable_interrupts(GLOBAL);                     //deshabilitar interrupciones
   disable_interrupts(INT_EEPROM);                 //deshabilitar interrupcion EEPROM
   disable_interrupts(INT_RB);                     //deshabilitar interrupcion portb
   disable_interrupts(INT_EXT);                    //deshabilitar interrupcion externa
   
   ext_int_edge(H_TO_L);                           //interrupcion en flanco de bajada
   port_b_pullups(TRUE);                           //pullups portb activadas
   setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);     

   set_tris_a(0b00000000);                         //porta todo como salida
   set_tris_b(0b00000000);                         //portb todo como salida
   
   enable_interrupts(INT_TIMER0);                  //interrupcion del contador
   enable_interrupts(GLOBAL);                      //interrupciones activadas

   do
   {
     
   }while(TRUE);
}
Título: Re: Problema de precisión con set_timer0()
Publicado por: pocher en 11 de Febrero de 2008, 17:27:19
Mira a ver si esto te sirve: http://www.todopic.com.ar/foros/index.php?topic=19025.0 (http://www.todopic.com.ar/foros/index.php?topic=19025.0)

Un saludo
Título: Re: Problema de precisión con set_timer0()
Publicado por: DarkVect en 19 de Febrero de 2008, 07:38:20
Muchas gracias. Es justo lo que me pasa, entro demasiadas veces en la interrupción y se hace patente el error.