Problema con temporizador de 18F4450

hola, estoy teniendo algunos problemas con el temporizador, así que me he dispuesto a crear un programa sencillo que lo unico que hace es incrementar una variable cada segundo y mostrarla por pantalla, para comprobar si contaba bien, pero resulta me cuenta muuucho mas rapido, casi no da tiempo a ver cada valor..
aqui dejo el codigo:
Simplemente cargo el timer con el valor 6 y un preescaler de 16, lo que me genera una interrupción cada 4 ms, creo la variable contador y la cargo a 250, cada vez que la variable contador vale 0, muestro el valor seg por pantalla.. Tengo algún error pero no se si es porque estoy bloqueado o lo desconozco pero no lo encuentro..


Código:
#include "18F4450.h" 

#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP 

#use delay (clock=4000000) //Fosc=4Mhz
#define LCD_DB4   PIN_D0 
#define LCD_DB5   PIN_D1 
#define LCD_DB6   PIN_D2 
#define LCD_DB7   PIN_D3 

#define LCD_E     PIN_A1 
#define LCD_RS    PIN_A3 
#define LCD_RW    PIN_A2 

#include <flex_lcd.c> // libreria del LCD.



int contador=250;
int seg=0;
#int_TIMER0
void periodo(void)
{

set_timer0(6);
contador--;

          
 
}


void main (void)
{
set_tris_a(0x01);
set_tris_b(0x0);
set_tris_d(0x0);
lcd_init(); //inicializa lcd
lcd_gotoxy(1,1);
lcd_putc("inicializando");
lcd_putc("\f");
delay_ms(1000);


SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_16);
SETUP_TIMER_0(RTCC_8_BIT);
SET_TIMER0(6);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
  while (TRUE)   { 

 if (contador==0)
   {
    
   
   contador=250;
   
   seg++;
   lcd_gotoxy(1,1);
   lcd_putc("seg");
   lcd_gotoxy(2,2);
   printf(lcd_putc," %i",seg);   
		 
         
		 
      }
		
	}
   
		}
 
Última edición:
Quetal danivr sabes he tenido el mismo problema y lo que pasa es q en C los calulos no son exaxtos ya que el compilador agrega lineas lo cual aunmenta el tiempo. Lee este libro http://www.taringa.net/posts/ebooks...imulador-PROTEUS-para-microcontroladores.html Ahi explican algo sobre los timer en C. Yo todavia no consigo la forma exacta de calcular la carga de los temporizadores. Ahorita ando un poco corto de tiempo pero espero que nos podamos ayudar en nuestro problema comun.
Saludos
 
Algo había leido de c, sin embargo yo nunca he tenido esos problemas con el 16F877 por ejemplo.. No se, será que aun no les tengo tomada la medida a los 18F o que tienen algo que funciona diferente y no me he enterado
 
Hola danivr

Sospecho que tu valor del preescaler y tu contador no estan bien determinados:

1. Con un reloj a 4Mhz tenemos que la frecuencia util es de 1Mhz (clk/4)
2. Con preescaler de 16 (RTCC_DIV16) nos queda una frecuencia de 1000000/16 = 62500
3. Para que el contador TMR0 desborde le estas cargando un valor de 250, seran 6 incrementos para que rote a '0' y entonces se genere una interrupcion, es decir 62500 / 6 = 10416.66666
4. Es decir, la rutina de servicio se ejecuta 10416 (aprox.) veces por segundo.

Posible solucion

1. Usar el preescaler con RTCC_DIV64, 1000000 / 64 = 15625 y cargar TMR0 con 125
2. Serian 15625 / 125 = 125, serian las veces que la rutina de servicio se ejecutaria por segundo, es decir 1 seg / 125 veces = 0.008 ms, si usas un contador adicional que cuente las veces que se ejecuta la rutina llegas a la cuenta de 125 veces y decrementas tu segundero

3. Una alternativa seria usar TMR0 en modo 16 bits ya que estas usando un 18F4550
4. Usar el preescaler con RTCC_DIV64 nos da la cuenta de 15625, si cargas en el contador TMR0 el valor 65536 - 15625 = 49911 (0xC2F7) tendras una interrupcion cada segundo.

Como ves? Que opinan?

Saludos
 
Muchas gracias! Es de mucha ayuda..

Me podrías explicar ésto? si por ejemplo quiero 20ms? no veo claro como calculas el tiempo ahi.. es que con el timer de 16 me va bien, mientras que el de 8 me da problemas..
3. Una alternativa seria usar TMR0 en modo 16 bits ya que estas usando un 18F4550
4. Usar el preescaler con RTCC_DIV64 nos da la cuenta de 15625, si cargas en el contador TMR0 el valor 65536 - 15625 = 49911 (0xC2F7) tendras una interrupcion cada segundo.
 
Última edición:
Para 20 ms...

frecuencia = 1 / periodo = 1 / 0.02 = 50

usa la formula

tmr0 = 65536 - clk / (frec * 4 * Preescaler)
= 65536 - 4000000 / ( 50 * 4 * 4)
= 60536

OJO, debes usar el parametro RTCC_DIV4 para el preescaler, esta claro que con las combinaciones de cristales, preescaler y tmr0 puedes lograr frecuencias que resultan exactas, esto no es siempre.

Saludos
 
Atrás
Arriba