Reloj Digital con PIC16F84A

Hola, no se si sea el único que ha experimentado lo que yo experimenté unos días atrás. No podía dormir y empecé a plantear como podría hacer un reloj digital, al día siguiente investigue que integrado sería el más conveniente, e inmediatamente me arrojó que el PIC16F84A. Después encontré un video que mostraba un reloj tipo 'vintage' que usaba un controlador MM5314, busqué la manera de conseguir un chip descontinuado pero mi búsqueda no dio muchos frutos, y proseguí con el '16f84, estuve haciendo pruebas en 'Proteus' y creo que me emocioné un poco y comencé a agregar un buzzer, para una alarma, no llegué mucho diseñando el diagrama, así que enfoqué mi prioridad al programa, y como me estoy adentrando al mundo de los microcontroladores de forma autodidacta, porque en la 'preparatoria técnica' en la que estoy no tocamos el tema, y apenas estoy comenzando a programar pequeñas cosas, espero, a través de éste foro, recibir una segunda opinión, o comentarios que pueda ser de asistencia tanto para mi como para otros entusiastas o estudiantes.

Aún soy muy nuevo en éste foro, y por lo tanto no puedo agregar muchos enlaces que proporcionen algo como lo que busco.


Que tengan un buen día :D
 
hubieras enpezado con un pic mas galletudo ese es un pic MUY caro y de MUY bajas prestaciones por que es obsoleto

hubieras enpezado con uno mejor que soporte el lenguaje C.

el reloj en tiempo real puedes usar el DS1302 o el DS1307
la diferencia es que uno es I2C y otro es SPI

no es dificil de usar

es lo malo que la mayoria de la informacion de internet es la mayoria muy vieja y con circuitos que ya no fabrican
 
Si, si vi algunos videos o diagramas que usaban el DS1302 o el DS1307, he leido los datasheet.

Ok, ahora descartamos el '16f84, ¿cuál podría usar? obvio más nuevo y más efectivo y usando el reloj de tiempo real.

Podría ser un PIC24??

Saludos :)
 
jaja no tampoco corras

bueno si tal vez mas que nada hay que ver cosas al trabajar con un microcontrolador

1.-costo
2.-aplicacion

aveces un micro de bajas prestaciones nos queda como anillo al dedo cuando se va a trabajar
sobre todo si nos cubre lo que queremos hacer y el precio es bajo

el pic16f84 no es nada barato

ahora si el reloj en tiempo real es bueno lo he usado hasta tiene ram extra para usarlo como una EEPROM.

para empezar pues te recomiendo aunque se me venga el foro ensima el pic18f4550
no por que sea faci, ni el mejor.
mas bien es por que tiene puerto USB y al tener este puerto puedes grabarle un bootlader

¿que hace el bootloader?

pues es un programa que alguien escribio para ya no usar el grabador de pics a cada rato, conectas el pic a la PC y le das a la PC grabar y se graba solito el pic

eso si debes grabarlo con un grabador el pic y despues ya no es necesario usarlo

esto hace mas facil elaborar un proyecto.

¿lenguajes?
C definitivamente
¿porque?
que tal si no te gustan los microchip PIC alomejor dices me gustan mas los AVR o los Texas o el Arduino que es el mismo AVR.

puedes migrar sin miedo

hay mucha documentacion de lenguaje C para microcontroladores PIC y muchos ejemplos para el calendario en tiempo real
 
para empezar pues te recomiendo aunque se me venga el foro ensima el pic18f4550

Jaja que problema puede haber? :LOL:D

En fin jaja, bueno, al menos en la tienda donde lo puedo conseguir, está casi al mismo precio que el '16f84, no importa, bueno, ya tenemos algo: el pic18f4550 y el reloj en tiempo real, ahora, para comenzar a diseñar el esquemático, para hacer el reloj, como empezarías?

Saludos :)
 
a pues comienza leyendo unos ejercicios de CCS hay muchos en internet , el C te funciona tanto en PC como en cualquier microcontrolador de cualquier fabricante, si te atoras buscan en paginas como conclase C y el rincon del C.

en el foro de todopic.ar hay temas del calendario en tiempo real y el pic

en CCS pic16fXXX y pic18fXXX la mayoria del codigo es muy similar
es decir si no encuentras temas del pic18f4550 busca del mas usado el pic16f877 , el pic16f628
pues son los pic mas comerciales, al usar CCS hace muy compatible el codigo y el codigo te sirbe perfectamente.

tampoco quieras correr sin saber caminar
 
Estoy tratando de hacer un reloj pero no me muestra nada en el lcd. ¿Qué puede ser?
Código:
#include <16f873a.h>
#device adc=10
#fuses NOWDT,BROWNOUT,XT,NOLVP,PUT
#use delay (clock=4m) 
#define use_portb_lcd true
#include <lcd.c>
#use standard_io(c) 
   
  
  int32 tiempo=0;//Tiempo 
   int32 tiempoS;// conteo de segundos
   int32 tiempoH;// conteo de minutos
   int32 tiempoM;// conteo de horas
 #INT_TIMER2
 void  timer2_isr(void)
{ 
   
 set_timer2(25536);
 
 if (tiempo < 17999999)tiempo ++; else tiempo=0;// aumenta cada 20ms, para llevar 
}
  void main(){
  while (true){
 setup_timer_2(t2_div_by_4,124,1);
 enable_interrupts(int_timer2);
 enable_interrupts(global);
 
 
 bucle:
   lcd_gotoxy(1,1);
   tiempoS=((tiempo*20)/1000);//pasar de numero de instrucciones a segundos
   tiempoH=tiempoS /3600;//saco horas
   tiempoS=tiempoS-(tiempoH*3600);//resto horas de los segundos
   tiempoM=tiempoS/60;//saco minutos
   tiempoS=tiempoS - (tiempoM*60);//resto minutos de los segundos
   printf(lcd_putc,"%02lu:%02lu:%02lu",tiempoH,tiempoM,tiempoS);
    goto bucle;
   
}
 }
 
callecuatro1976 dijo:
Estoy tratando de hacer un reloj pero no me muestra nada en el lcd. ¿Qué puede ser?
Código:
#include <16f873a.h>
#device adc=10
#fuses NOWDT,BROWNOUT,XT,NOLVP,PUT
#use delay (clock=4m) 
#define use_portb_lcd true
#include <lcd.c>
#use standard_io(c) 
   
  
  int32 tiempo=0;//Tiempo 
   int32 tiempoS;// conteo de segundos
   int32 tiempoH;// conteo de minutos
   int32 tiempoM;// conteo de horas
 #INT_TIMER2
 void  timer2_isr(void)
{ 
   
 set_timer2(25536);
 
 if (tiempo < 17999999)tiempo ++; else tiempo=0;// aumenta cada 20ms, para llevar 
}
  void main(){
  while (true){
 setup_timer_2(t2_div_by_4,124,1);
 enable_interrupts(int_timer2);
 enable_interrupts(global);
 
 
 bucle:
   lcd_gotoxy(1,1);
   tiempoS=((tiempo*20)/1000);//pasar de numero de instrucciones a segundos
   tiempoH=tiempoS /3600;//saco horas
   tiempoS=tiempoS-(tiempoH*3600);//resto horas de los segundos
   tiempoM=tiempoS/60;//saco minutos
   tiempoS=tiempoS - (tiempoM*60);//resto minutos de los segundos
   printf(lcd_putc,"%02lu:%02lu:%02lu",tiempoH,tiempoM,tiempoS);
    goto bucle;
   
}
 }

Hola, no revisé a detalle tu código pero veo que no estas inicializando el lcd, podrías empezar a ver eso en primera instancia.
 
Si es así, me faltó iniciar el lcd.
Ahora una consulta. ¿Cómo hago para que encienda con un pulso y pare con otro pulso?



Código:
#device adc=10
#fuses NOWDT,BROWNOUT,XT,NOLVP,PUT
#use delay (clock=4m) 
#define use_portb_lcd true
#include <lcd.c>
#use standard_io(c) 
   
  
  int32 tiempo=0;//Tiempo 
   int32 tiempoS;// conteo de segundos
   int32 tiempoH;// conteo de minutos
   int32 tiempoM;// conteo de horas
 
   
 #int_ext 
void interupcion_externa (void) 
{   
 if(input(PIN_A1)==0)
{
 if(input(PIN_A1)==1)
tiempo++;
if(tiempo>3)
{
tiempo=0; 
} 
}  
}
 #INT_TIMER2
 void  timer2_isr(void)
{ 
   
 set_timer2(25536);
 
 if (tiempo < 17999999)tiempo ++; else tiempo=0;// aumenta cada 20ms, para llevar 
}
  void main(){
 
    setup_adc_ports(an0_an1_an3);
setup_adc(adc_clock_div_32  );  
 
  lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("tiempo de secion");
  while (true){
  
 setup_timer_2(t2_div_by_4,124,1);
 enable_interrupts(int_timer2);
 enable_interrupts(INT_EXT);
  ext_int_edge(L_TO_H);
 enable_interrupts(global);
 
 
 bucle:
   lcd_gotoxy(4,2);
   tiempoS=((tiempo*20)/1000);//pasar de numero de instrucciones a segundos
   tiempoH=tiempoS /3600;//saco horas
   tiempoS=tiempoS-(tiempoH*3600);//resto horas de los segundos
   tiempoM=tiempoS/60;//saco minutos
   tiempoS=tiempoS - (tiempoM*60);//resto minutos de los segundos
   printf(lcd_putc,"%02lu:%02lu:%02lu",tiempoH,tiempoM,tiempoS);
    goto bucle;
   
}
 
Ahora una consulta. ¿Cómo hago para que encienda con un pulso y pare con otro pulso?
Modificando tu código, quitando las partes redundantes y no usadas, sería de esta forma usando la librería "Button.c"
Código:
#include <16f873a.h>
#fuses NOBROWNOUT
#use delay (crystal = 4MHz) 
#include <lcd.c>

#include "Button.c"
   
  
int32 tiempo=0;//Tiempo 
int32 tiempoS;// conteo de segundos
int32 tiempoH;// conteo de minutos
int32 tiempoM;// conteo de horas

 #INT_TIMER2
 void  timer2_isr(void)
{ 
   set_timer2(25536);
   if (tiempo < 17999999)tiempo ++; else tiempo=0;// aumenta cada 20ms, para llevar 
}

void main()
{
int1 flag = 0;
int8 B0 = 0;

   setup_timer_2(t2_div_by_4,124,1);
   enable_interrupts(global);
   
   lcd_init();
   lcd_putc("\fTiempo de sesion");
   
   port_b_pullups(true);
   
   while (true)
   {
      if (button(pin_b3,0,255,10,B0,1))
      {
         if(flag == 0)
         {
            flag = 1;
            enable_interrupts(int_timer2);
         }
         else if(flag == 1)
         {
            flag = 0;
            disable_interrupts(int_timer2);
         }
      }
         tiempoS=((tiempo*20)/1000);//pasar de numero de instrucciones a segundos
         tiempoH=tiempoS /3600;//saco horas
         tiempoS=tiempoS-(tiempoH*3600);//resto horas de los segundos
         tiempoM=tiempoS/60;//saco minutos
         tiempoS=tiempoS - (tiempoM*60);//resto minutos de los segundos
         
         lcd_gotoxy(4,2);
         printf(lcd_putc,"%02lu:%02lu:%02lu",tiempoH,tiempoM,tiempoS);
   }
}
Así cómo estás usando la interrupción externa en éste PIC, no tiene efecto ni sentido.
Si lo que quieres es modificar el tiempo, lo debes hacer de otra forma.

Suerte.
 
ahora solo logro hacer detener el contador pero no puedo ponerlo en cero
Pues limpia la variable "tiempo"
Ésto lo puedes hacer justamente a continuación de la instrucción "disable_interrupts(int_timer2);"
No creo que sea necesario limpiar el Timer2, pero por si las dudas, también ponlo en 0.

Nota:
La librería "Button.c" también puede estar dentro de la carpeta del proyecto.
Por eso la declaré así: #include "Button.c" y no así: #include <Button.c>
 
ok quiero hacerlo por el puerto c port_c_pullups(true); asi estaría bien y coloco tiempo=0;debajo "disable_interrupts(int_timer2);" y tendría que arrancar , mi idea es que arranque en cero con un pulsador que empiece a correr hasta que se apreté el mismo botón y pare y tenerlo un rato apretado para colocarlo en cero otra vez
 
Última edición:
ok quiero hacerlo por el puerto c port_c_pullups(true); así estaría bien y coloco tiempo=0;debajo "disable_interrupts(int_timer2);" y tendría que arrancar , mi idea es que arranque en cero con un pulsador que empiece a correr hasta que se apreté el mismo botón y pare y tenerlo un rato apretado para colocarlo en cero otra vez
El puerto C no tiene resistencias pull-up internas, tendrás que poner una externa para el pulsador.
Y si es como pienso que sería, entonces el código quedaría así:
PHP:
#include <16f873a.h>
#fuses NOBROWNOUT
#use delay (crystal = 4MHz) 
#include <lcd.c>

#include "Button.c"
   
  
int32 tiempo=0;   // Tiempo 
int32 tiempoS;    // conteo de segundos
int32 tiempoH;    // conteo de minutos
int32 tiempoM;    // conteo de horas

 #INT_TIMER2
 void  timer2_isr(void)
{ 
   set_timer2(25536);
   if (tiempo < 17999999)tiempo ++; else tiempo=0; // aumenta cada 20ms, para llevar 
}

void main()
{
int1 flag = 0;
int8 B0 = 0;
int16 contador = 0;

   setup_timer_2(t2_div_by_4,124,1);
   enable_interrupts(global);
   
   lcd_init();
   lcd_putc("\fTiempo de sesion");
   
   port_b_pullups(true);
   
   while (true)
   {
      if (button(pin_b3,0,255,10,B0,1))   // Si se presiona el pulsador...
      {
         while(!input(pin_b3))            // Mientras esté pulsado...
         {
            ++contador;                   // Incrementar "contador"
            delay_ms(1);                  // Retardo de 1ms.
            
            if(contador == 3000)          // Si "contador" llegó a 3000 (3 segundos)...
            {            
               disable_interrupts(int_timer2);  // Deshabilitar Timer2
               tiempo = 0;                // Limpiar "tiempo"
               flag = 1;                  // Mantener "flag" en 1 (Para que el soltar el pulsador no avance el conteo)
               lcd_gotoxy(5,2);
               lcd_putc("00:00:00");      // Poner en ceros la pantalla.
            }
         }
         
         contador = 0;                    // Limpiar "contador"
         
         if(!flag)
         {
            flag = 1;
            enable_interrupts(int_timer2);
         }
         else if(flag)
         {
            flag = 0;
            disable_interrupts(int_timer2);
         }
      }
         
         tiempoS=((tiempo*20)/1000);      // pasar de número de instrucciones a segundos
         tiempoH=tiempoS /3600;           // saco horas
         tiempoS=tiempoS-(tiempoH*3600);  // resto horas de los segundos
         tiempoM=tiempoS/60;              // saco minutos
         tiempoS=tiempoS - (tiempoM*60);  // resto minutos de los segundos
         
         lcd_gotoxy(5,2);
         printf(lcd_putc,"%02lu:%02lu:%02lu",tiempoH,tiempoM,tiempoS);
   }
}
De esta forma, al presionar el pulsador se iniciará el conteo, una segunda pulsación lo detendrá, y dejando el pulsador presionado por 3 segundos, se pondrá el tiempo en 0.
¿Esa es la idea?
 
Última edición:
me queda asi pase el botón en el puerto c anda pero me falta un poquito es mas difícil de lo que pensé pero con tu ayuda voy aprendiemdo
 

Adjuntos

  • voltimetro con reloj.rar
    12.3 KB · Visitas: 38
Nop, quedamos en usar una resistencia pull-up, no una resistencia pull-down.
Si usas una resistencia pull-down, también se tendrá que modificar el programa.

Adjunto el proyecto para que veas cómo sería.
 

Adjuntos

  • 16F873A Cronómetro con LCD 16x2.rar
    25.6 KB · Visitas: 29
por que me atraza tanto el contador quiero tener un a fuente que me marque la tensión la corrfiente y el tiempo de trabajo, pero el reloj atraza mucho
 

Adjuntos

  • voltimetro con reloj.rar
    12.4 KB · Visitas: 22
  • reloj.rar
    1.3 KB · Visitas: 45
¿Por qué me atrasa tanto el contador? Quiero tener una fuente que me marque la tensión, la corriente y el tiempo de trabajo, pero el reloj atrasa mucho.
El problema donde obtuviste el código, era eso precisamente: Cronometro con pic siempre atrasa

Debe ser porque está mal calculado el Timer2, porque en ese código se usa el Timer3 con un PIC18F2550 y se usa a 16 bits.
Con los 8 bits del Timer 2 en el PIC16F873A, no se pueden alcanzar los 20 milisegundos que se requieren para el conteo correcto, lo máximo son 4.096ms. Con el prescaler 1:16
Sobre ese tema explican los posibles problemas.

Mejor mira este ejemplo de un cronómetro de mi autoría y adáptalo a tu proyecto.
Éste si cuenta bien las horas, los minutos, los segundos y los milisegundos.

También puede tener algún ligero atraso, pero te puede resultar útil para lo que deseas.
 

Adjuntos

  • 16F873A Cronómetro con Timer1.rar
    24.8 KB · Visitas: 29
Última edición:
me atrasa por la cantidad de veces que hago leer el adc para tomar un promedio, baje las mediciones y empezó a andar mejor ahora tengo que ver el tema del voltímetro, como hacer para poder tomar mediciones , promediar y que no ponga tan lento el pic.
 
Atrás
Arriba