TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Trev en 11 de Octubre de 2009, 23:48:40

Título: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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)
         {
         
         }
       }
       
       
       
       
       
       


Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: fidodido18 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?
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ 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
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ en 12 de Octubre de 2009, 22:29:43
Hola.

Me refería al diagrama esquemático de conexión.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky 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!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ 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
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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
 
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ 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
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky 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!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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  :(
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno 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

Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev 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.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 13 de Octubre de 2009, 02:26:43
Ademas la diferencia no esta en el orden de los µs sino en los milisegundos adelanta 6 min en 12 hs = se agradece la respuesta
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno en 13 de Octubre de 2009, 02:34:56
Yo sigo pensando que ese programa debe retrasar. A ver si hay algún problema con las divisiones y los decimales que tienes en la función que reparte los segundos entre horas y minutos.

¿Puedes hacer una prueba?: no hagas ninguna operación con la variable "momento_actual". Déjala incrementarse indefinidamente y cuando pase una hora justa comprueba si su valor es 3600 justos. Apuesto a que la cifra va a ser menor a 3600.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 13 de Octubre de 2009, 13:19:37
Analizando un poco como trabaja el sistema todo indica que debería de atrasar tal como comenta Nocturno!

Paso a paso seria, el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us. Entonces cuando se produce la interrupción por overflow se tiene 30us para actualizar el timer y así no perder un ciclo en la cuenta, y esto con un cristal de 4MHz vamos a estar un poco ajustados (Por experiencia el guardado de contexto ronda alrededor de los 50 ciclos) así que lo recomendable sería un cristal de 20 MHz. Luego para el timer0 cuando se realiza una escritura este se inhibe durante 2 ciclos, pero en el datasheet no encontré nada de esto referido al Timer1, pero igual me queda la duda  :?

Sería bueno que realices la prueba que comenta Nocturno, porque por mas vueltas que se le de no se ve porque adelante, y es raro que el cristal este fuera de frecuencia  :undecided:

Saludos!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ en 13 de Octubre de 2009, 16:41:33
Hola.

Pues los cristales de 32k768Hz si que son sensibles al calor, hay que soldarlos rápido no mas para evitar estar cambiándolos jejeje. Coincido con Suky, sería mejor aumentar el valor del cristal del oscilador general, para no aumentar el error en tiempo en la gestión de la interrupción.

Saludos
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 14 de Octubre de 2009, 12:38:56
Bien muchachos estoy enfermo hoy aguantenme un dia y si puse cristal de 20 MHz y lo que dice nocturno son 3 intrucciones de carga del timer que son

MOVLW  80
MOVWF  0F 
CLRF   0E
a 20 megas son 600 ns ahh y otra cosa y hablando a la ligera mire el asm y parece que solo al final de las interrupciones limpia las banderas y recupera los registros imp según creo pero no parece salvarlos,lo vi a la ligera no loestudie pero me parecio eso,mos vemos mañana.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 14 de Octubre de 2009, 12:50:23
 :shock: No solo eso, esta el guardado de contexto. Buscar información sobre interrupciones, manejo de interrupciones, etc.  ;-)
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno en 14 de Octubre de 2009, 12:54:41
Efectivamente, lo que más consume es el guardado del contexto.

Que te recuperes
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 14 de Octubre de 2009, 13:35:00
Gracias viejo era una migraña nomas y Suky ya se a lo que te refieres al salvado de los registros importantes como STATUS Y W solo que no le dimos ese nombre en mi escuela y son estas:
Código: [Seleccionar]
0000:  MOVLW  00
0001:  MOVWF  0A
0002:  GOTO   5A2
0003:  NOP
0004:  MOVWF  7F
0005:  SWAPF  03,W
0006:  CLRF   03
0007:  MOVWF  21
0008:  MOVF   0A,W
0009:  MOVWF  20
000A:  CLRF   0A
000B:  MOVF   04,W
000C:  MOVWF  22
000D:  MOVF   77,W
000E:  MOVWF  23
000F:  MOVF   78,W
0010:  MOVWF  24
0011:  MOVF   79,W
0012:  MOVWF  25
0013:  MOVF   7A,W
0014:  MOVWF  26
0015:  MOVF   7B,W
0016:  MOVWF  27
0017:  BCF    03.7
0018:  BCF    03.5
0019:  BTFSS  0B.3
001A:  GOTO   01D
001B:  BTFSC  0B.0
001C:  GOTO   036
001D:  MOVLW  8C
001E:  MOVWF  04
001F:  BTFSS  00.0
0020:  GOTO   023
0021:  BTFSC  0C.0
0022:  GOTO   039
0023:  MOVF   22,W
0024:  MOVWF  04
0025:  MOVF   23,W
0026:  MOVWF  77
0027:  MOVF   24,W
0028:  MOVWF  78
0029:  MOVF   25,W
002A:  MOVWF  79
002B:  MOVF   26,W
002C:  MOVWF  7A
002D:  MOVF   27,W
002E:  MOVWF  7B
002F:  MOVF   20,W
0030:  MOVWF  0A
0031:  SWAPF  21,W
0032:  MOVWF  03
0033:  SWAPF  7F,F
0034:  SWAPF  7F,W
0035:  RETFIE
asique son 53 + las 3 de carga del timer son 56/5 µs de retraso  11.2 µs de retraso por segundo y no se veria en el proteus porque tiene presición de 4 decimales pero con eso deben pasar casi 100.000 segundos para q retrase un segundo o sea un segundo de retraso cada un poquito mas de un dia y es aceptable tampoco podemos pretender perfeccion absoluta
ademas que si o si se tienen que ejecutar.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 14 de Octubre de 2009, 15:34:59
mmm... mira el análisis que hice unos mensajes anteriores y te darás cuenta que si usas 20MHz, alcanzas a actualizar el timer antes de que llegue el siguiente pulso  :|
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 14 de Octubre de 2009, 18:55:52
Hola  :) Nocturno:

Citar
Yo no creo que sea el cristal, jamás me he encontrado con un cristal que falle.

El hecho es que falla y esta adelantando como 300 Hz y es este,el de 20 MHz no tiene nada q ver o poco.
No hay otra forma de explicar que adelante!!.
Pero creo que estamos de acuerdo en algunos puntos:

Citar
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.

Citar
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.

Asique como esto es inevitable (a menos que se pueda cambiar el orden de ejecución,o sea que primero se salve W y se cargue el timer y solo serian 1000 ns,pero el compilador realiza automaticamente esto asique es inmutable) con este método y si o si hay q cargar el timer porque no hay preescaler 1:2 en el mejor de los casos se logra que retrase 6 minutos por año y con este valor porque tampoco se puede compensar porque
Citar
el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us.
porque son 11 µs a 20 mHz y no podria poner por ejemplo set_timer1(32769) porque me paso y ya adelantaria salvo q use un cristal de 8 MHz entonces la perdida de tiempo ya estaria cerca de los 30,5 se perderia una cuenta y la compensaria sumandole a la carga del timer.
Ya emprolije todo y sigue = voy a hacer lo que planteas Nocturno y despues cuento
Citar
no hagas ninguna operación con la variable "momento_actual". Déjala incrementarse indefinidamente y cuando pase una hora justa comprueba si su valor es 3600 justos. Apuesto a que la cifra va a ser menor a 3600.

y sino de lutima pasare a lo que planteas Suky:
Citar
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.-
Paro lo cual vendria bien que esboces un ejemplo
Todo esto biene despues que logre que atrase y no q adelante,Nos vemos  ;-)
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 14 de Octubre de 2009, 19:01:24
Todavía no logras entender como trabaja o no logre explicarme aquí:

Analizando un poco como trabaja el sistema todo indica que debería de atrasar tal como comenta Nocturno!

Paso a paso seria, el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us. Entonces cuando se produce la interrupción por overflow se tiene 30us para actualizar el timer y así no perder un ciclo en la cuenta, y esto con un cristal de 4MHz vamos a estar un poco ajustados (Por experiencia el guardado de contexto ronda alrededor de los 50 ciclos) así que lo recomendable sería un cristal de 20 MHz. Luego para el timer0 cuando se realiza una escritura este se inhibe durante 2 ciclos, pero en el datasheet no encontré nada de esto referido al Timer1, pero igual me queda la duda  :?

Sería bueno que realices la prueba que comenta Nocturno, porque por mas vueltas que se le de no se ve porque adelante, y es raro que el cristal este fuera de frecuencia  :undecided:

Saludos!

Los 30.5 us es el periodo de la señal que ingresa al timer1 y que cuenta, por eso con lo que detalle saco la conclusión de que es mejor un cristal de 20MHz.

Llegaste a hacer la prueba que indico Nocturno?

Después la opción del combinar CCP con el timer si el problema es la frecuencia del oscilador estamos en las mismas  :?

Saludos!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno en 14 de Octubre de 2009, 19:09:26
Y ahora que lo pienso, ¿porqué no usas el Timer2?
Si le pones un prescaler de 1:16 y un postcaler de 1:8 tendrás 32768 / 16 / 8 = 256 ticks por segundo.
El Timer2 es de 8 bits y desbordaría cada segundo sin tener que precargar nada.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: reiniertl en 15 de Octubre de 2009, 10:14:20
Yo estoy convencido que con el TIMER1 se puede hacer perfectamente.

Configurando correctamente el preescaler se pueden obtener tiempos de interrupción, para ese cristal de 32768 de:

Preescaler  Tint
  1:1              500ms
  1:2            1000ms
  1:4            2000ms
  1:8            4000ms

No hay que estar escribiendo en el registro del TIMER, cosa nada recomendable, ya que se presentan los siguientes problemas

Al escribir el registro, no se puede escribir en TMR1L porque esta acción implica la pérdida de dos ciclos de máquina completos en resincronizar el reloj del temporizador.
Se elimina el tiempo contado por el temporizador desde que se desbordó hasta que se escribió, porque el contador cuenta aún después de desbordarse y pedir INT, la latencia de la interrupción puede ser variable, así que este tiempo no podemos conocerlo a ciencia cierta.
Sería conveniente sólo escribir en TMR1H, tiempo antes que TMR1L se desborde, de modo que no haya problemas con la temporización. Recordemos que TMR1H se incrementa con cada desbordamiento de TMR1L.

Así que lo mejor es no tocar el timer, sino configurarlo correctamente.

Aquí un enlace a un trabajo que no he terminado, pero que puede aclarar algunas cosas:
TIMER1 en los microcontroladores PIC. Ajuste por software del periodo de desbordamiento (http://www.wikitronica.net/index.php/TIMER1_en_los_microcontroladores_PIC._Ajuste_por_software_del_per%C3%AD%C2%ADodo_de_desbordamiento)

saludos
Reinier

Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 15 de Octubre de 2009, 10:45:26
Configurando correctamente el preescaler se pueden obtener tiempos de interrupción, para ese cristal de 32768 de:

Preescaler  Tint
  1:1              500ms
  1:2            1000ms
  1:4            2000ms
  1:8            4000ms

Estas cometiendo el mismo error mio, sin cargar el timer sería:
Preescaler  Tint
  1:1            2000ms
  1:2            4000ms
  1:4            8000ms
  1:8            16000ms

Ahora con respecto a escribir el timer se pierden 2 ciclos maquinas, si ese fuese el caso no habría problemas, pero se pierden en este caso que usa una fuente externa? (2 ciclos de la fuente externa) Igual si fuera el caso creo que no responde al adelanto que presenta el reloj  :?


Saludos!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: reiniertl en 15 de Octubre de 2009, 11:00:04
Si el TIMER1 es de 16 bits y el período de reloj para el cristal externo del que se habla es de 32768Hz, en un segundo se producen desbordamientos según la siguiente expresión (2^16)/32768 que da exactamente 2, lo que significa que el timer se desbordará dos veces en 1 segundo, por lo que su período es de 0.5s que es lo mismo que 500ms y así sucesivamente.

Saludos
Reinier

PD: He arreglado este post para que se entienda mejor
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 15 de Octubre de 2009, 11:15:28
 :shock: El cristal es de 32768 Hz, osea que el timer contará 32768 pulsos por segundo, y como es de 16bits, el desbordamiento ocurre a 216=65536, osea que deben pasar 2 segundos  :mrgreen:

Saludos!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: reiniertl en 15 de Octubre de 2009, 11:31:47
Si Suki, tienes razón, es evidente que hoy ando confundi'o
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 15 de Octubre de 2009, 13:56:24
Ya esta amigos no se peleen mas por el timer1 que no da para mas el asunto no pude eliminar el adelantamiento es mejor pasar al timer2 y asi no depender de un cristal que evidentemente no son de confianza,hoy si puedo subo el ejemplo terminado,nos vemos  :)
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Suky en 15 de Octubre de 2009, 14:32:07
Nunca nos peleamos! Todo es para ir aprendiendo un poquito cada día. Es lo bueno del foro que todos aportan sin ningún interés tratando de resolver el problema  ;-)

Saludos!
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 15 de Octubre de 2009, 14:39:34
Me confundí parece que Nocturno habla como si el timer 2 fuera un contador con cristal externo ¿pero como se configura? la ayuda no dice nada o estamos los dos confundidos?  :?
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: reiniertl en 15 de Octubre de 2009, 14:45:10
Yo hice un reloj con TIMER1 que funcionó durante dos meses sin interrupción y no se adelantó ni atrasó (al menos sisiblemente). Claro, utilicé TIMER1+CCP. Si quieres me das un correo y mañana cuando pase por la casa te mando el proyecto completo. Está en hecho C de CCS y hay simulación para Proteus.

saludos
Reinier
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: fidodido18 en 17 de Octubre de 2009, 02:12:02
Yo hice un reloj con TIMER1 que funcionó durante dos meses sin interrupción y no se adelantó ni atrasó (al menos sisiblemente). Claro, utilicé TIMER1+CCP. Si quieres me das un correo y mañana cuando pase por la casa te mando el proyecto completo. Está en hecho C de CCS y hay simulación para Proteus.

saludos
Reinier

Hola amigo mejor subelo al foro, para que cuando alguien presente este mismo problema sepa como solucionarlo! y asi no te tenga que mandar un MP para que tambien le reenvies el documento....

Respecto al tema siempre me he dado cuenta que proteus es una cosa muy distinta simulando en C, a veces coincide pero cuando el tiempo es muy importante casi nunca es exacta, y lo he comprobado! los erros son en msegundos, con osciloscopio de laboratorios especializados de la U y computador core 2 duo 2 gigas de ram y un pwm.

Conclusion si tienes un osciloscopio a la mano trata de ver ese pulso y sales de duda.

Otra es volver a ASM  :? (ya hasta se me olvido pasar de banco :mrgreen:) y controlar esas instrucciones al maximo.

pero estoy casi completamente seguro que el error esta en codigo..
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 12 de Noviembre de 2009, 20:02:56
Hola,despues de un tiempo se pudo solucionar el problema no habia ningún error en el programa ni en el proteus,era el maldito cristal y la protoboard,cambié todo de lugar y pasado 1 dia de prueba no adelanta ni atrasa ni un minuto,tambien modifique el programa para eliminar la precarga del timer1 con el módulo CCP en modo captura,en fin solucionado  :-/
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: MLO__ en 12 de Noviembre de 2009, 22:38:56
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-

Me lo imaginaba ... es que las protoboard a veces dan malas pasadas.

Que bueno que ya este bien.

Saludos
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 13 de Noviembre de 2009, 00:16:45
Citar
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


Si MLO yo confiaba en el proteus y no me falló eso es lo mejor de esto es bueno poder confiar en el sino todo se vuelve muy entropico,hay q dudar primero del harware antes del proteus,nos vemos y ahora me gustaría agregarle una función de alarma cuando tenga tiempo,nos vemos  :-/ aca dejo el código definitivo

Código: [Seleccionar]


#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_CCP1
CCP1_rsi()
{
Conta_Segundos+=1;
Mi_Hora();
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
}


#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;
    portb=0x00;
    lcd_gotoxy(6,1);
    printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
    delay_ms(10);
    set_timer1(0);
}


// 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;
      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);
      setup_timer_1(T1_EXTERNAL |T1_DIV_BY_1 |T1_CLK_OUT);
      enable_interrupts(INT_CCP1);
      setup_ccp1(CCP_COMPARE_RESET_TIMER);
      CCP_1=32768;
         while(1)
         {
         
         }
       }
       
       
       
       
       
       
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno en 13 de Noviembre de 2009, 02:33:57
Me alegro que lo hayas resuelto.
Pero no confíes en Proteus 100% aunque en esta ocasión te haya dado la razón, falla mucho.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 13 de Noviembre de 2009, 15:43:59
Ok Nocturno seria bueno q abras un hilo sobre eso asi nos prevenimos,gracias por tu aporte ahh y los otros dias q nos quedamos sin este foro andube chusmeando por tu pagina esta buena, Salu2   ;-)
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Nocturno en 13 de Noviembre de 2009, 18:29:36
Juraría que había un hilo abierto en el que se publicaron los principales errores detectados, pero lo he estado buscando y no lo encuentro.
Gracias por lo de la página.
Título: Re: Reloj maldito:adelanta,adelanta y vuelve a adelantar :(
Publicado por: Trev en 23 de Noviembre de 2009, 19:42:14
Y que tal es el HT1380?me lo acabo de comprar tenia intenciones de usar un DS3232 pero fue imposible conseguirlo  :5] alguien ha usado este chip estaria piola q me contaran sus experiencias mientras estoy aprendiendo i2c q no se nada pero si alguno lo ha usado me gustaria saber q onda,bye