Autor Tema: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(  (Leído 7186 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« en: 11 de Octubre de 2009, 23:48:40 »
A ver si me pueden dar una mano con este problema uso el timer1 con crystal externo de 32768 Hz la simulación en proteus creo que esta perfecta porque hago dos breakpoint cuando ingreso a la interrupción del timer y cuando se actualiza la hora y me da un segundo exacto en ambos casos,no se que pasa cambie los cristales el de 4 MHz puse otro y lo mismo,lo puse mas cerca y lo mismo,puse uno de 20 MHz y lo mismo  :(,cambie los de 32768 HZ y lo mismo ya no se que hacer es la primera vez que uso el timer1 con oscilador externo y hace 4 dias que estoy lidiando con este problema

Código: [Seleccionar]
#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS,PUT,NOPROTECT,NOWDT,NOLVP
#byte portb=6
#byte portc=7
#byte portd=8
#include <flex_lcd.c>
#use standard_io(b,c)
//#use fast_io(b)

#define SEGUNDOS_EN_UNA_HORA 3600
#define SEGUNDOS_EN_UN_MINUTO 60


int32 Conta_Segundos=0,MomentoActual=0;
int32 Horas=0,Minutos=0,Segundos=0;
int set,flag_timer1;
byte last_b;

void Mi_Hora(void);
void Cambiar_Hora(int32 *Horas,int32 *Minutos);
void reset(void)
{
Conta_Segundos=0;
Momentoactual=0;
}

#INT_TIMER1
timer1_rsi()
{
set_timer1(32768);
++Conta_Segundos;
Mi_Hora();
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
}

// Interrupcion RB4 - RB7 /////////////////////////////////////////////////////
#INT_RB
rb_isr()
{
    byte changes;
    changes=last_b^portb;       //XOR.
    last_b=portb;
    if (bit_test(changes,5) && !bit_test(last_b,5))
    {                                                     
         lcd_gotoxy(6,2);
         lcd_putc("..              ");    //Indica que se va a incrementar las horas.
         delay_ms(200);
         lcd_gotoxy(6,2);
         lcd_putc("                ");
         delay_ms(200);
         lcd_gotoxy(6,2);
         lcd_putc("..              ");
         if(set==1)
         {
         lcd_gotoxy(1,2);
         lcd_putc("        ..      ");   // Indica que se van a incrementar los minutos
         delay_ms(250);
         lcd_gotoxy(1,2);
         lcd_putc("                ");
         delay_ms(250);
         lcd_gotoxy(1,2);
         lcd_putc("        ..      ");
         }
         set+=1;
         if (set==2)
         set=0;   
    }
    if (bit_test(changes,6) && !bit_test (last_b,6))   //INCREMENTAR.
    {
    Cambiar_hora(&Horas,&Minutos);
    }
    if (bit_test(changes,7) && !bit_test (last_b,7))   //DECREMENTAR.
    {
    Cambiar_hora(&Horas,&Minutos);       
    }
    Conta_Segundos=(Minutos*60)+(Horas*3600)+Segundos;
    bit_clear(portb,0);          //Solo modifico el nibble bajo sin tocar el alto
    bit_clear(portb,1);          //y consigo escribir el port
    bit_clear(portb,2);
    bit_clear(portb,3);
    lcd_gotoxy(6,1);
    printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
    delay_ms(10);
    set_timer1(32768);   
}


// Programa Principal /////////////////////////////////////////////////////////
   
void  Mi_Hora()
      {
      MomentoActual=Conta_Segundos;
      Horas=MomentoActual/SEGUNDOS_EN_UNA_HORA;
      MomentoActual%=SEGUNDOS_EN_UNA_HORA;               //Guarda el resto de la división entera.
      Minutos=MomentoActual/SEGUNDOS_EN_UN_MINUTO; 
      MomentoActual%=SEGUNDOS_EN_UN_MINUTO;   
      Segundos=MomentoActual;
      if(Horas==24 && Minutos==0 && Segundos==0)
      {
      Horas=0;
      Minutos=0;
      Segundos=0;
      reset();
      }
      }
     
void Cambiar_hora(int32 *Horas,int32 *Minutos)
{
if(set==0)
   {
      if(portb==0b10110000)
      {
      ++*Minutos;
      if(*Minutos==60){*Minutos=0;}
      }
   }
if(set==1)
   {
      if(portb==0b10110000)
      {
      ++*Horas;
      if(*Horas==24){*Horas=0;}
      }
   }
if(set==0)
   {
      if(portb==0b01110000)
      {
      if(*Minutos==0){*Minutos=60;}
      --*Minutos;
      }
   }   
if(set==1)
   {
      if(portb==0b01110000)
      {
      if(*Horas==0){*Horas=24;}
      --*Horas;
      }
   }   
}     
       
void  main(void)
      {
      lcd_init();
      set_tris_b(0xf0);
      port_b_pullups(TRUE);
      portb=0xf0;
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);//el preescaler q va es 2.
      enable_interrupts(INT_TIMER1);
      enable_interrupts(INT_RB);
      enable_interrupts(GLOBAL);
      set_tris_c(0b00000011);
      set_tris_d(0x00);
      lcd_gotoxy(1,1);
      lcd_putc("Reloj Digital");
      delay_ms(1500);
      lcd_putc("\fHora 00:00:00 ");
      lcd_gotoxy(1,2);
      lcd_putc("        ..      ");
      delay_ms(250);
      lcd_gotoxy(1,2);
      lcd_putc("                ");
      delay_ms(250);
      lcd_gotoxy(1,2);
      lcd_putc("        ..      ");
      delay_ms(250);
      set_timer1(32768);
         while(1)
         {
         
         }
       }
       
       
       
       
       
       



Desconectado fidodido18

  • PIC18
  • ****
  • Mensajes: 312
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #1 en: 12 de Octubre de 2009, 15:26:32 »
A ver si me pueden dar una mano con este problema uso el timer1 con crystal externo de 32768 Hz la simulación en proteus creo que esta perfecta porque hago dos breakpoint cuando ingreso a la interrupción del timer y cuando se actualiza la hora y me da un segundo exacto en ambos casos,no se que pasa cambie los cristales el de 4 MHz puse otro y lo mismo,lo puse mas cerca y lo mismo,puse uno de 20 MHz y lo mismo  :(,cambie los de 32768 HZ y lo mismo ya no se que hacer es la primera vez que uso el timer1 con oscilador externo y hace 4 dias que estoy lidiando con este problema

estas seguro que cuando cargar el timer con ese valor te da 1 segundo exacto? tengo otra pregunta si te parece tan importante la hora porque no dejas que de ello se encargue otro modulo especializado en eso?

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #2 en: 12 de Octubre de 2009, 16:53:11 »
Estoy segurisimo según creo o estoy loco?  :oops: y sino fijate en la imagen del debug que hice en proteus entre impresiones consecutivas en display pasa un segundo exacto exacto ;fijate en el breakpoint que hice otros me recomendaron q sacara el printf de ahi y lo hiciera con flag pero haciendo eso no era exacto y con respecto a tu otra pregunta

1. Según creo esta el DS1307 pero viendo la hoja de datos su precición depende de la del cristal asique estoy en la misma

2.Aun siendo mejor no lo voy a conseguir estoy en la 2da ciudad de mi pais y tuve suerte de conseguir el cristal digo DS1307 y no saben que es me quieren dar un transistor me paso lo mismo que cuando traté de conseguir un motor DC.
Asique es lo que hay y tendrá que salir con esto a menos que alguien me quiera enviar uno y se agradeceria
Si quieres te paso el archivo del proteus asi lo debugeas tu mismo,Saludos y gracias.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #3 en: 12 de Octubre de 2009, 21:34:45 »
Podrías subir un esquemático? La precarga del Timer esta bien, podrías usar lo que te aconsejo Suky también en la configuración del Timer1.

Saludos
El papel lo aguanta todo

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #4 en: 12 de Octubre de 2009, 22:14:02 »
Bien MLO voy a subir el archivo de proteus y el código para que lo debugees esta bueno lo que decia Suky de las banderas para casos en general pero probando ese código ya ni siquiera en el simulador era exacto asique sigo con el mio original,que a mi entender el simulador me indica que no hay errores.Gracias y nos vemos

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #5 en: 12 de Octubre de 2009, 22:29:43 »
Hola.

Me refería al diagrama esquemático de conexión.
El papel lo aguanta todo

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #6 en: 12 de Octubre de 2009, 23:06:54 »
Lo que pasa que mi método podrá adelantarse o atrasarse en 1 ciclo un par de 1us (Que el ojo humano nunca detectaría), pero los errores entre ciclos se cancelan, y en 10 min, 1h, 30hs no debería de visualizarse ningún error perceptible, esto porque no recargamos el timer. Es lo que intenté explicar en el otro hilo, pero...  :?


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #7 en: 12 de Octubre de 2009, 23:23:49 »
Hola.

No quiero una foto de tu montaje Trev.

En la simulación marca la interrupción de 1 segundo correctamente, así que podría ser una falla en el hardware, por lo que seria recomendable que subas el diagrama esquemático del hardware, para revisar las conexiones y esas cosas, si puedes subir la foto también, pssss bien, eso ayudaría mucho para detectar mas fallos.

Saludos
El papel lo aguanta todo

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #8 en: 13 de Octubre de 2009, 00:14:46 »
Hola amigos,Suky creo que te refieres a T1_DIV_BY_2 pero poniendo esto interrupe cada 4 s en la ayuda dice:
Parameters:
mode values may be:

T1_DISABLED,     T1_INTERNAL, T1_EXTERNAL, T1_EXTERNAL_SYNC

T1_CLK_OUT

T1_DIV_BY_1, T1_DIV_BY_2, T1_DIV_BY_4, T1_DIV_BY_8

constants from different groups may be or'ed together with |.
asique no es T1_DIV_BY_1/2. No es la fórmula asi? 1segundo=(65536/32768)*PREESCALER si P=1/2 da 1 y lo pongo como T1_DIV_BY_2
Bien no cargo el timer pero interrumpe cada 4s.
MLO adjunto la foto es un buen cablerio je
 

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #9 en: 13 de Octubre de 2009, 00:30:25 »
 :shock: :shock: :shock:

jeje no pude ver el cristal!!

La idea es que el cristal de 32k768Hz este lo mas cerca posible a los pines correspondientes a T1OSO y T1OSI y que de ellos salgan los condensadores de 33pF a GND. Otra recomendación es el anillo de GND al rededor de los pines del oscilador. Hay veces que las proto nos juegan malas pasadas con los cristales -a mi también me ha pasado-

Saludos
El papel lo aguanta todo

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #10 en: 13 de Octubre de 2009, 00:51:26 »
Bueno mañana lo voy a emprolijar un poco porque ya es tarde al montaje porque puede haber capacidades parasitas pero ya hice eso y nada (lo acerque no lo emprolije) y ya les dije q los cap son de 27pF saludos
Mañana subo otra vez la foto la saco con mi celu

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #11 en: 13 de Octubre de 2009, 00:55:35 »
 :oops: :oops: Estaba haciendo la cuenta mentalmente al revés  :oops: Pido disculpas por ser tan necio y no haber estudiado bien el tema.  :mrgreen:

Edit: Se podría combinar el timer con el módulo CCP en modo captura y evento especial (Todo en conjunto funcionaria de la manera que trabaja el timer2 con PR2) para generar la interrupción automática sin recarga del timer logrando mayor precisión.-


Saludos!
« Última modificación: 13 de Octubre de 2009, 01:12:58 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #12 en: 13 de Octubre de 2009, 01:25:50 »
Voy a hacer una cosa; mañana emprolijo y cuando tenga plata me compro otro cristal en otro lugar si lo consigo y sino de última probamos con tu otra forma Suky que ni idea porque nunca use el timer2,es el cristal ¿y que? cuando quiera usar el DS1307 lo voy a tener que conectar = asique es frustrantre  :(

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #13 en: 13 de Octubre de 2009, 02:05:14 »
Yo no creo que sea el cristal, jamás me he encontrado con un cristal que falle.
Yo apuesto a que el error está en el código. Y lo digo por lo siguiente: desde que el micro salta a la interrupción hasta que ejecuta la precarga para la siguiente interrupción hay varios ciclos de reloj, especialmente lo referido al guardado de contexto y alguna operación más. Si quieres examina el código ASM que genera tu programa para comprobar el montón de instrucciones que hay antes del set_timer().

Una vez llegado a la precarga, tú le estableces un salto de 32768 ciclos y por lo tanto la duración será de 32768+el tiempo perdido anteriormente.

Si no estoy equivocado, con ese programa, el reloj atrasará en lugar de adelantar.

Y respecto a que en Proteus no se vea ese efecto puede ser por dos razones:
- sólo tienes precisión de 4 decimales. Si hubiera un error de 99 microsegundos no lo verías
- no es la primera vez que Proteus falla


Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
« Respuesta #14 en: 13 de Octubre de 2009, 02:16:26 »
El hecho es que adelanta por lo tanto no es cierto lo que dices y fijate en los breakpoint que trazo en proteus.


 

anything