Autor Tema: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?  (Leído 2676 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Hola mi reloj funciona pero me parece muy engorroso el código  :? aceptaria sugerencias de como simplificarlo lo más posible ademas el valor del segundo no es preciso en la realidad aunque en el proteus me anda perfecto,lo que si no tengo conectados los condensadores de 22 pF¿será eso?Nos vemos  :)

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #1 en: 21 de Agosto de 2009, 00:10:09 »
Hola.

Pues, la mejor manera de obtener precision es conectarle un cristal de 32k768Hz y aprovechar el Timer1 o el Timer0 para contar los pulsos mediante el T1OSI.

Saludos
El papel lo aguanta todo

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #2 en: 21 de Agosto de 2009, 01:30:42 »
El timer1 con cristal externo de 32768Hz y preescaler 1:2 te genera una interrupción exacta de 1 segundo como bien indica MLO_
Otra forma de hacerlo es usar las interrupciones del timer con oscilador interno y "tratar" de ajustarlo para que sea lo más próximo a 1 seg, pero siempre tendrá algún error.  Como tu lo haces seguro va a tener un error bastante notorio, pues ejecutas una series de instrucciones que llevan cierta cantidad de ciclos de reloj osea un par de ms y luego haces la demora de 1 segundo sin tener en cuenta lo anterior.

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

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #3 en: 21 de Agosto de 2009, 02:04:55 »
Hola amigos..yo me referia a un desfasaje importante que persistia aun despues de poner los capacitores de 27 pF pero como sospechaba que era por el brownout lo saque y andubo bien pero el código es un espanto y haciendolo asi no podre programar la hora con mi teclado  :(.., ya van tres horas andando y me da la misma hora calculada en mi celular asique estoy conforme por ahora pero me gustaria fijarle una hora con el teclado pero la verdad no me sale con lo poco que recuerdo de C que por falta de tiempo deje un poco en el olvido,Salu2

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #4 en: 21 de Agosto de 2009, 12:18:35 »
Hola mi reloj funciona pero me parece muy engorroso el código  :? aceptaria sugerencias de como simplificarlo lo más posible ademas el valor del segundo no es preciso en la realidad aunque en el proteus me anda perfecto,lo que si no tengo conectados los condensadores de 22 pF¿será eso?Nos vemos  :)

el segundo archivo esta CORRUPTO amigo...
preuba a resubirlo.


un saludo

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #5 en: 21 de Agosto de 2009, 14:04:26 »
Hola, mi pequeño aporte, el tema de la precisión ya te comentaron como hacerlo. Por lo que vi el código esta bien escrito pero se simplificaria mucho si cambias la manera de hacer el calculo. Lo prinicipal es tener una base de tiempo la cual vas a contar, en tu caso deberia ser un timer de 1s lo mas exacto posible, en el handler de la interrupción actualizas un contador de 32 bits para que te de la precisión. Ejemplo: ( No uso MicroChip ni CCS espero que entiendas las lineas de C )

Código: C
  1. volatile INT32 TimerTicks;
  2.  
  3. TimerInterruptHandler( void )
  4. {
  5.    TimerTicks ++;
  6. }
  7.  
  8. INT32 GetTimerTicks( void )
  9. {
  10.     volatile INT32 ReadTicks;
  11.  
  12.     ReadTicks = TimerTicks;
  13.  
  14.     while ( ReadTicks != TimerTicks )
  15.     {
  16.        ReadTicks = TimerTicks;
  17.      }
  18.     return( ReadTicks );
  19. }

La primera función cuenta los ticks que se producen por segundo, deberas colocar el codigo correspondiente para tu micro para el manejo de la interrupcion, en la segunda se devuelve ese contador de manera "atomica".
Una vez que tenes ese contador, lo que resta es transformar los segundos, en minutos, horas, dias, meses y años, simplemente haciendo cuentas. Para finalizar usar solamente una funcion para escribir el display como string, tomas los valores anteriores ( segundos, minutos, horas, etc ) convertidos a string y los mostras.
Te dejo un ejemplo de como desde una base de tiempo se convierte a dias, horas, minutos pero la idea es la misma.

Código: C
  1. /*------------------------------------------------------------------------------------------------
  2. ** Function Name : GetElapsedTime
  3. ** Description   : Get elpased time form startup in DD:HH:MM:SS:mmm format
  4. ** Input         : Destinity vars
  5. ** Output        : Nothing
  6. ** Notes         :
  7. --------------------------------------------------------------------------------------------------*/
  8. void GetElapsedTime( byte *Days, byte *Hours, byte *Mins, byte *Secs, word *Miliseconds )
  9. {
  10.   dword CurrentTime = GetMiliSecondsFromStartup();
  11.  
  12.   *Days = CurrentTime / MILISECOND_IN_DAY;
  13.   CurrentTime %= MILISECOND_IN_DAY;
  14.  
  15.   *Hours = CurrentTime / MILISECOND_IN_HOUR;
  16.   CurrentTime %= MILISECOND_IN_HOUR;
  17.  
  18.   *Mins = CurrentTime / MILISECOND_IN_MINUTES;
  19.   CurrentTime %= MILISECOND_IN_MINUTES;
  20.  
  21.   *Secs = CurrentTime / MILISECOND_IN_SECONDS;
  22.   *Miliseconds = CurrentTime % MILISECOND_IN_SECONDS;
  23. }

Saludos !

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #6 en: 21 de Agosto de 2009, 18:06:01 »
Gracias amigo valoro tu respuesta y me parece buena la idea,en un principio se me habia ocurrido algo asi pero sin usar el timer (usando el delay_ms(1000) simplemente,soy vago y no me acordaba del timer :mrgreen:) tomar una variable bien grosa de 32 o 64 bits y despues hacer las cuentas para calcular todo invocando alguna función..,la ultima función no la pesco bien porque hay punteros y no los entiendo aun pero voy a estudiar la estructura,ahora me voy a poner  jugar un rato y haber que sale,subo el archivo de proteus de nuevo

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #7 en: 21 de Agosto de 2009, 18:17:15 »
Hola, te explico un poco, a la función se la invoca de esta manera:

Código: C
  1. ...
  2.  byte Days, Hours, Mins, Secs;
  3.  word Miliseconds;
  4.  
  5.  GetElapsedTime( &Days, &Hours, &Mins, &Secs, &Miliseconds );
  6. ...

Como la función devuelve muchos valores, los mismos son devueltos por referencia, por eso el tema de los punteros, vos declaras variables y a la función les pasas los punteros para que escriba ahi. La cuentas lo que hacen es calcular primero los dias en base a la cantidad de milisegundos que hay en un dia ( mi base de tiempo son 100 ms y no segundos ), después haces el módulo para que te quede el remanente y asi vas siguiendo. En mi caso solo cuento dias, porque no es un real time clock, a vos se te complica un poco porque seguramente tenes que tener en cuenta los dias de los meses y los bisiestos.

Saludos !

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #8 en: 21 de Agosto de 2009, 20:44:35 »
Bueno listo ahi lo hice andar  :-/ gracias a las rutinas q me pasaste RICHI777 lo adapte un poco porque no quiero la fecha..,se simplifico enormemente  :-/ ahora lo que me queda es poder programarle la hora con el teclado porque no dispongo de pulsadores..Salu2.

Código: [Seleccionar]
#include <16f877a.h>
#use delay(clock=4000000)
#fuses XT,PUT,NOPROTECT,NOWDT,NOLVP
#byte portd=8
#include <flex_lcd.c>

const INT16 SEGUNDOS_EN_UNA_HORA=3600;
const int SEGUNDOS_EN_UN_MINUTO=60;
const int SEGUNDOS_EN_SEGUNDOS=1;

int Horas,Minutos,Segundos;
volatile INT32 TimerTicks;

TimerInterruptHandler( void )
      {   
TimerTicks++;
      }

INT32 GetTimerTicks( void )               //No la voy a usar por ahora!!
      {   
      volatile INT32 ReadTicks;     
      ReadTicks = TimerTicks;
         while ( ReadTicks != TimerTicks )   
         {       
         ReadTicks = TimerTicks;     
         }   
      return( ReadTicks );
      }

void MOMENTO_ACTUAL( byte *Horas, byte *Minutos, byte *Segundos)
      {
      INT32 MomentoActual;
      MomentoActual = GetTimerTicks();     //Esta es la función que devuelve los segundos
      //*Dias = MomentoActual / SEGUNDOS_EN_UN_DIA;             //Calcula los dias.
      //MomentoActual %= SEGUNDOS_EN_UN_DIA;                    //
      *Horas = MomentoActual / SEGUNDOS_EN_UNA_HORA; 
      MomentoActual %= SEGUNDOS_EN_UNA_HORA;   
      *Minutos = MomentoActual / SEGUNDOS_EN_UN_MINUTO; 
      MomentoActual %= SEGUNDOS_EN_UN_MINUTO;   
      *Segundos = MomentoActual / SEGUNDOS_EN_SEGUNDOS;
      MomentoActual %= SEGUNDOS_EN_SEGUNDOS;
      }


      main()
      {
      lcd_init();
      set_tris_d(0x00);
         while(1)
         {
         lcd_gotoxy(1,1);
         printf(lcd_putc,"%02d:%02d:%02d",Horas,Minutos,Segundos);
         delay_ms(1000);
         TimerInterruptHandler();
         MOMENTO_ACTUAL(&Horas,&Minutos,&Segundos);       
         }
       }   

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #9 en: 22 de Agosto de 2009, 11:38:58 »
Hola Trev, buenisimo !!! y ahora el código que mucho mas sencillo, un comentario, si las variables Horas, minutos y segundos son gloables no hace falta pasarlas como punteros, actualizalas de una una en la función.

Saludos !

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #10 en: 22 de Agosto de 2009, 15:00:23 »
Bueno si ahora me voy a poner a estudiar un rato el tema de los punteros y no te preocupes por el overflow de la variable q cuenta los segundos porque según calcule va a tardar mas de 100 años en hacerlo  :D

PD:Ayer estube intentando agregarle la función de seteo del reloj para que sea un verdadero reloj(sino hay que prenderlo a las 12 igual registre un atraso de 15-20 s en un dia)con el teclado pero sin exito  :( ya que tienes experiencia en la programación en C no me vendria mal que me tires una idea de como hacerlo :mrgreen: , de una cosa estoy seguro que este código es mucho mas flexible que el otro si se pretende agregarle esta función,Saludos desde Rosario.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Mi reloj funciona pero es muy engorroso el codigo¿como simplificarlo?
« Respuesta #11 en: 22 de Agosto de 2009, 15:47:11 »
Otra vez te comento, para tener precisión en los segundos te conviene utilizar el timer 1 y un oscilador externo, con delay_ms(1000) es seguro que vas a tener ese error.

Después para ingresar hora por teclado podría ser así:

Código: C
  1. printf(lcd_putc,"\fIngreso Hora\n");
  2.      lcd_send_byte(0,0x0F);  // Coloca cursor parpadeando.-
  3.      Tecla=getc_Teclado();   // Tecla devuelve el valor de la tecla y no su codificación ascII
  4.      printf(lcd_putc,"%u",Tecla);
  5.      i=(Tecla<<4);
  6.      Tecla=getc_Teclado();   // Tecla devuelve el valor de la tecla y no su codificación ascII
  7.      printf(lcd_putc,"%u:",Tecla);
  8.      i+=Tecla;
  9.      Hora=(i>>4)*10;       // Convierto a bcd
  10.      Hora=Hora+(i<<4>>4);  //
  11.      /****************************/
  12.      Tecla=getc_Teclado();  
  13.      printf(lcd_putc,"%u",Tecla);
  14.      i=(Tecla<<4);
  15.      Tecla=getc_Teclado();  
  16.      printf(lcd_putc,"%u:",Tecla);
  17.      i+=Tecla;
  18.      Minuto=(i>>4)*10;       // Convierto a bcd
  19.      Minuto=Minuto+(i<<4>>4);  //
  20.      /****************************/
  21.      Tecla=getc_Teclado();  
  22.      printf(lcd_putc,"%u",Tecla);
  23.      i=(Tecla<<4);
  24.      Tecla=getc_Teclado();  
  25.      printf(lcd_putc,"%u",Tecla);
  26.      i+=Tecla;
  27.      Segundo=(i>>4)*10;       // Convierto a bcd
  28.      Segundo=Segundo+(i<<4>>4);  //
  29.      lcd_send_byte(0,0x0C);  // Apaga cursor.-
  30.      delay_ms(300);


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


 

anything