TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: neocommandos en 26 de Octubre de 2004, 18:04:00

Título: Sentencia printf
Publicado por: neocommandos en 26 de Octubre de 2004, 18:04:00
       Hola foro
tengo una duda...estoy realizando un reloj usando para ello el timer0, y a la hora de visualizar el tiempo, necesito que en el lcd aparezca un ancho de campo de 2. De forma que aun cuando la variable que almacena los segundos, sean 7, en el lcd aparezca 07, y no 7. Estoy usando para ello la sentencia printf de esta forma

printf(lcd_puts,"%2d",segundos);

 pero no funciona, ya que en caso de ser 7, lo que hace es añadirme un espacio en blanco.

Hay alguna forma directa de hacerlo, mediante algun modificador de printf?
sino supongo que habria construir algun codigo para diferencia cuando es menor mayor de 9, no?

Gracias de antemano.
Título: RE: Sentencia printf
Publicado por: wqtrp en 26 de Octubre de 2004, 18:12:00
agregale un 0 despues del % y antes del 2 y todo lindo

suerte
Título: RE: Sentencia printf
Publicado por: neocommandos en 26 de Octubre de 2004, 19:12:00
Que rapidez!

Probe eso antes, y me daba un fallo, por eso pense que lo hacia mal, pero ya he trasteado y si el modificador es como tu dices.

Pero cuando realizo el codigo que te indico abajo, me aparece por ejemplo

00:000:00:25

donde 25 son los segundos, los 00 situados a su izquierda los minutos, y todo lo anterior 00:000 no se porque sale.

Ademas, el reloj atrasa una barbaridad, en 2 minutos, ya se retrasa del orden de segundos y tampoco veo el porque.

Aqui adjunto el codigo....


/*//////////////////////////////////////////////////////////////////////////////
     Este programa es un reloj con formato 24 horas que se muestra en
     el LCD. Para el reloj se ha utilizado el temporizador TMR0.
//////////////////////////////////////////////////////////////////////////////*/


#include    <16F877A.H>                 /* tipo de PIC */
#include    <lcd.c>

#use        delay( clock = 4000000 ) /* reloj de 4 MHz */
#fuses      XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NODEBUG,NOLVP,NOCPD
#use        fast_io(B)

//#include    <Rutinas.h>


char cuenta_interrupciones=0;
char segundo=0;
char minuto=0;
char hora=0;


#int_rtcc
void interrupt(void)
{
   cuenta_interrupciones++; // Incrementa la variable que cuenta las
                            // interrupciones

   if(cuenta_interrupciones==250)    // Si la cuenta ha llegado a 250 ha
                                      // pasado 1 segundo
   {
      cuenta_interrupciones=0;
      segundo++;

   }

   if(segundo>59)
   {
      segundo=0;
      minuto++;
   }

   if (minuto>59)
   {
      minuto=0;
      hora++;
   }

   if (hora>23)
      hora=0;

   set_rtcc(0x06);          // interrupciones y recarga el timer

}



void main( void )
{
   lcd_init();

   setup_counters (RTCC_INTERNAL, RTCC_DIV_16); // Programacion TMR0
   set_timer0(0x06);                            // Carga el valor del timer0

   enable_interrupts(INT_RTCC);                 // Habilita interrupcion TMR0
   enable_interrupts(GLOBAL);                   // Habilita las interrupciones


   while(1)
   {

      lcd_gotoxy(5,1);         // Posiciona el cursor del LCD en dicha posicion
      printf(lcd_puts,"%02d",hora);
      lcd_putc(":");
      printf(lcd_puts,"%02d",minuto);
      lcd_putc(":");
      printf(lcd_puts,"%02d",segundo);
   }

}



Título: RE: Sentencia printf
Publicado por: oshow en 27 de Octubre de 2004, 03:54:00
Hola neocommandos, he probado tu código y salvo algunos fallos a la hora de compilar funciona perfectamente, la forma de mostrar el reloj es tal y como tú preguntas, que ponga un cero delante del dígito si éste es menor de 10.

Te pasteo el código modificado. Lo único que no he comprobado es la precisión de la interrupción, pero lo que preguntas (la visualizacion del reloj) es como quieres que sea.

Codigo:

#include <16F877A.H> /* tipo de PIC */
#use delay( clock = 4000000 ) /* reloj de 4 MHz */
#include <lcd.c>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NODEBUG,NOLVP,NOCPD
#use fast_io(B)

//#include <Rutinas.h>


char cuenta_interrupciones=0;
char segundo=0;
char minuto=0;
char hora=0;


#int_rtcc
void interrupt(void)
{
   cuenta_interrupciones++; // Incrementa la variable que cuenta las
   // interrupciones

   if(cuenta_interrupciones==250) // Si la cuenta ha llegado a 250 ha
   // pasado 1 segundo
      {
         cuenta_interrupciones=0;
         segundo++;

      }

   if(segundo>59)
      {
         segundo=0;
         minuto++;
      }

   if (minuto>59)
     {
         minuto=0;
         hora++;
     }

   if (hora>23)
      hora=0;

   set_rtcc(0x06); // interrupciones y recarga el timer

}



void main( void )
{
   lcd_init();

   setup_counters (RTCC_INTERNAL, RTCC_DIV_16); // Programacion TMR0
   set_timer0(0x06); // Carga el valor del timer0

   enable_interrupts(INT_RTCC); // Habilita interrupcion TMR0
   enable_interrupts(GLOBAL); // Habilita las interrupciones


   while(1)
   {

      lcd_gotoxy(5,1); // Posiciona el cursor del LCD en dicha posicion
      printf(lcd_putc,"%02u",hora);
      lcd_putc(":");
      printf(lcd_putc,"%02u",minuto);
      lcd_putc(":");
      printf(lcd_putc,"%02u",segundo);
   }

}



Saludos.
Título: RE: Sentencia printf
Publicado por: pocher en 27 de Octubre de 2004, 05:19:00
Como Oshow ha comprobado el código que pegaste tenía errores ¿no entiendo como pudiste comprobar el funcionamiento con estos errores?

Cuidado con los retrasos: la recarga del TMR0 hazla al entrar en la interrupción, no al salir.
Título: RE: Sentencia printf
Publicado por: wqtrp en 27 de Octubre de 2004, 07:05:00
hola, si como dice pocher, debe mover la instruccion de recarga del timer a inicio de la int., ( y deberia ser lo primero)
asi y todo no podras solucionar el problema de la precicion y sera bastante, calculo q del orden del 1%
el primer problema es q estas usando un divisor de prescaler, con lo cual nunca podras ajustarla lo suficiente, la mejor condicion q llegaras sera de 16/4000 q es un 4 por mil


dependiendo del pic, deberias usar algo tipo el modulo de PWM para q el mismo micro haga la recarga del timer y entonces si, seras completamente feliz ..... ja

suerte....

Título: RE: Sentencia printf
Publicado por: pocher en 27 de Octubre de 2004, 08:00:00
Completamente de acuerdo, se me había pasado.

Otras causas de retrasos:

Al entrar en la interrupción se gastan microsegundos (malo)

Al utilizar la función de recarga del timer se gastan microsegundos (malo)
Título: RE: Sentencia printf
Publicado por: neocommandos en 27 de Octubre de 2004, 16:40:00
   Hola a todos,
ciertamente habia fallos, despiste mio alguno, aunque realmente funcionaba.
He vuelto a probar el codigo que me mandastes oshow, gracias. Ciertamente como habeis dicho pocher y wqtrp  aun poniendo la recarga del timer al principio, el retraso aun es bastante grande,asi que probare otra cosa. Y aun me sigue apareciendo en la pantalla ceros de mas, por ejemplo si han transcurrido 25 segundos, me apareceria esto en el lcd:


00:000:00:25



Lo del PWM para que haga la recarga del timer en que consistiria la idea, wqtrp? no acabo de entenderlo...

Gracias a todos por vuestra ayuda.
Título: RE: Sentencia printf
Publicado por: cucaracha en 27 de Octubre de 2004, 16:58:00
Noooooooooooo!!! mi@ otra vez me pilló!!!desquiciado
Bueno... repito.

Te es más fácil usar un cristal adecuado para esos menesteres... Cuales. Pues aquellos que dividiendo entre 256 resulte un número entero.
Recuerdas esos cristales usados en los RTC... 32,768KHz. Pues mira 32768/256=128, osea, numerito entero... Que casualidad!!Muchas risas
Pues eso... busca cristales que sigan esa regla...
3.276.800Hz (3,2768Mhz) por ejemplo. Esta no es una frecuencia que me haya sacado de la manga ni nada de eso... hay muchas, que precisamente son para este uso, para que generen bases de tiempo en segundo mediante timers. Hay muchos.
Mira por ejemplo en www.micropik.com en cristales y verás...
Por cierto... este tema de los cristales ya ha sido tratado varias veces en el foro por si te interesa...

Saludos!!

PD: a ver... copiar texto..... ahora no me pillas mi@!!!
Título: RE: Sentencia printf
Publicado por: wqtrp en 27 de Octubre de 2004, 18:04:00
como ha derivado esto , de un printf a optimizar un reloj.....ja

bueno, vamos por partes, segun el ejemplo usas el f877, fijate en el data sheet en el timer 2 como se puede utilizar y veras q pones un valor en un registro y automaticamente cuando el timer llega a ese valor, genera una int. y ademas repone el valor nuevamente, tofo esto sin utilizar ciclos de pic.

pero sin duda la solucion de cucaracha es la mejor para un reloj, utilizas el timer 1 con un cristal externo, eso chiquitos q parecen un tubito y q estan por todos lados, (en lo relojes sobre todo) q son de muy baja frecuencia, generalmente 32768Hz y al pic lo haces oscilar con un RC nomas, para q mas, si la presicion te la da el otro cristal...

excelente lo de cuca.... y nosotros enterrados con los ciclos.....

suerte
Título: RE: Sentencia printf
Publicado por: oshow en 27 de Octubre de 2004, 22:17:00
Volviendo al tema de la visualización... ahora mismo no se porque te salen todos esos ceros, yo he usado ese especificador de formato con varios relojes y me ha funcionado a la perfección, no sé, prueba a borrar el lcd antes de que imprima nuevos datos cada segundo, a ver si consigues solucionar algo así.

De todas formas he simulado el código en proteus y funciona perfectamente, se visualiza bien.... no se me ocurre nada por lo que te puedan salir todos esos ceros... podría ser tu versión del compilador??? no sé que decir....a mí, el código que te he puesto en cuanto a visualización funciona perfectamente...

Saludos.
Título: RE: Sentencia printf
Publicado por: neocommandos en 28 de Octubre de 2004, 19:30:00
Hola oshow, pues si estoy pensando que sea el compilador. Lo he simulado con el Proteus, y aparecen todos esos ceros de mas a excepcion de uno.

Lo de borrar la pantalla, tambien probe, pero no funciona, de hecho no se ve nada en la pantalla, aun poniendole retardos.

Voy a ver si consigo otra version de compilador.
Título: RE: Sentencia printf
Publicado por: neocommandos en 03 de Noviembre de 2004, 18:51:00
           Hola a todos de nuevo,
ya probe el codigo con el compilador nuevo de duracion 30 dias de CCS, la version 3.212d y sigue haciendo lo mismo. Tambien probe a borrar el lcd, pero igualmente pasa lo mismo.

Tambien, lo he simulado de nuevo en Proteus, y siguen saliendo esos ceros de mas, solo que uno menos.

Oshow dices que has probado el mismo codigo en proteus, y no te aparecen los ceros, no?

La verdad es que ya no se que probar,...a alguien se le ocurre algo???


Título: RE: Sentencia printf
Publicado por: kruskal en 03 de Noviembre de 2004, 20:37:00
IdeaIdeaIdeaIdeaIdea

Te recomiendo que uses un reloj de tiempo real (RTC), puede ser un I2C DS1307 o uno con serial con clock DS1302. No se atrasan y ademas de darte la hora al segundo puedes tener la fecha dia:mes:año:dia de la semana.

hace tiempo intente hacer un reloj fue un completo fracaso por mas que intente, se atrasa o incluso se adelanta de muy mala calidad el resultado.
El PCW tiene librerias muy transparentes que hacen muy facil usar un RTC, sin dudas se te acabaran los problemas cuando uses uno.

Salud2 y Suerte.

Título: RE: Sentencia printf
Publicado por: pocher en 04 de Noviembre de 2004, 03:09:00
Si quieres hacer un reloj con un PIC la mejor solución es la que apuntó Cuca, usando un cristal de 3,2768 MHz por ejemplo. Con un preescaler de 128 conseguirás que se desborde cada 1s (sin recargar el TMR0, que se pierden valiosos us).

Y para arañar más us, no lo hagas por interrupción, hazlo detectando en el while la activación del bit T0IF.

Por supuesto otra solución es con un RTC.

Un saludo
Título: RE: Sentencia printf
Publicado por: oshow en 04 de Noviembre de 2004, 03:50:00
La visualización me funciona perfectamente... tanto en proteus como en un montaje real... no se me ocurre nada por lo que te pueda pasar lo que comentas...

Un saludo

PD: En el montaje real no tengo puesto el código que aquí aparece, tengo implementado un rtc mediante i2c, pero el especificador de formato %02u si que está funcionando perfectamente.