Problema con DS1307, no cuenta bien.

Hola a todos, estube buscando mi problema pero realmente no lo encontre. Estoy tratando de hacer un reloj, mostrado en un lcd 16x2 usando el ds1307 y un at89s52 programado en C. Es un proyecto personal y puramente para aprender a usar el ds1307. La libreria del ds la tuve que hacer yo, ya tenia una echa para controlar una memoria i2c por lo que los cambios fueron infimos, el protocolo es el mismo. El reloj anda, no atrasa y no adelanta por lo que pude ver, pero lo que hace es...arranca y cuenta hasta 06 segundos por ejemplo (que por lo que parece lo hace mas rapido, es decir menos de un segundo entre numero y numero) y se queda ahi mas de un segundo o mas tiempo del que habia entre los anteriores segundos, luego continua bien hasta por ejemplo 12 o 13 (a modo ejemplo, nunca lo hace igual) a velocidad mas rapida y despues se para mas tiempo y compenza lo que se apuro. En pocas palabras no atrasa ni adelanta, pero si le prestas atencion segundo a segundo ves que no funciona como deberia. Cabe destacar que no le coloque la pila de 3V al integrado, usa los 5V mismos del micro, no se si esto pueda estar afectando.

Muchas gracias, saludos!
 
Es necesario inicializar el DS1307, otra cosa supongo tomas la frecuencia de referencia desde su pin de salida, este es de colector abierto y necesita de un resistor de pull-up. Puede ser esta la causa, una entrada flotada provoca falsos disparos y por eso hace lo que quiere
 
Hola, no estoy tomando la frencuencia de referencia, ese pin esta a masa. Yo leo el DS mediante el protocolo i2c constemente y actualizo la informacion en pantalla. El ds lo incializo al comienzo configurando el bit 7 del registro 0X00. Gracias!
 
También es preciso configurar el modo 12 o 24 horas, en fin, lo de los tiempos inexactos puede ser un conflicto en el programa del micro... te recomiendo que aproveches la salida SQW/OUT del DS1307 y las interrupciones del micro, así puedes mantener al micro en otras tareas y solo refrescar su info del LCD cuando ocurra una interrupción del DS1307, además de mejorar la precisión del reloj
 
Como digiste, es un problema del programa del micro. Conecte a un led la salida a 1 hz del ds y nunca se traba, prende y apaga constatemente de manera igual, o eso parece a mi ojo. Por lo tanto el problema esta en el refresco del programa, yo lo hice para que lea constantemente. usando la interrupcion seria lo mas adecuado no?



Solucionado, el problema era el soft, usando la salida del ds para sincronizar la lectura logre el correcto funcionamiento, muchas gracias!!!
 
Última edición:
Que bien, es mejor utilizar esa salida que tiene el DS1307, ahorra la necesidad de estarlo leyéndolo constantemente, con ella solo cuando es necesario... suerte
 
La batería en un DS1307 es completamente necesaria para su operación o si no, tienes que conectar el pin VBAT a ground. Directo de la hoja de datos:

"Backup Supply Input for Any Standard 3V Lithium Cell or Other Energy Source. Battery voltage must be held between the minimum and maximum limits for proper operation. Diodes in series between the battery and the VBAT pin may prevent proper operation. If a backup supply is not required, VBAT must be grounded."
 
Buenas tardes estoy programanado el reloj DS1307 para el PIC18F4550 y estoy teniendo problemas con el cambio de hora en verano y en invierno.

Mi código es el siguiente:

Código:
#include <18f4550.h>  
#use delay(clock=1000000) 
#use i2c(MASTER, SDA=PIN_b0, SCL=PIN_b1,slow) 

//Registros DS1307 
#define ds_seconds 0x00 
#define ds_minutes 0x01 
#define ds_hours 0x02 
#define ds_day 0x03 
#define ds_date 0x04 
#define ds_month 0x05 
#define ds_year 0x06 
#define ds_control 0x07 

//DS1307 
//Vbat a tierra 
#fuses XT,NOWDT,NOPBADEN                    //Fusibles de configuracion, OSC XT, y Watchdog Desactivado
#BYTE PORTD=0xF83
#BYTE PORTB=0xF81
#include "lcd.c"  
#include "key.c"
#int_EXT2
void EXT2_isr(void){
teclado();
}
void main(void) 
{ 
set_tris_b(0b11111111);  
set_tris_d(0b00001111);            
enable_interrupts(INT_EXT2); // Habilita la interrupción en RB0
enable_interrupts(GLOBAL); // Habilitación general de interrupción 
ext_int_edge(L_TO_H); // Config. int. por flanco descendente. (L_TO_H) para ascendente
int16 retardo; //Cada cuando actualiza lectura en LCD 

//Dato en registro ds, a mandar o leer 
int seconds,minutes,hours,day,date,month,year,control; 
boolean cambio_hora = true; 

retardo=500; //ms a tardar entre lectura y lectura 

//Justo cuando prende circuito, la fecha que establece es la siguiente 
seconds= 0x40; 
minutes= 0x59; 
hours = 0x01; //modo 24 hrs 
day = 0x01; //1 es domingo 
date = 0x27; 
month = 0x10; 
year = 0x13; 
control= 0x00; //OUT=0 SQWE=0 RS0-1=0 no hay onda cuadrada 


//Establece fecha y hora 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que empiece en registro ds_seconds 
//Aquí establece fecha y hora respecto a la puesta arriba 
i2c_write(seconds); 
i2c_write(minutes); 
i2c_write(hours); 
i2c_write(day); 
i2c_write(date); 
i2c_write(month); 
i2c_write(year); 
i2c_write(control); 
i2c_stop(); //Ya puso la hora y fecha 
//El RTC ya está marcando el tiempo y fecha 

//Rutina LCD 
lcd_init(); //Inicia LCD 
lcd_putc("\f"); //Limpia LCD 
lcd_putc("Real Time Clock\n"); //rtc 
lcd_putc(" DS1307"); 
delay_ms(3000); 

while(1) 
{ 

delay_ms(retardo); //Usuario lee 

//Obtiene datos de DS1307 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que ponga registro en ds_seconds 
i2c_stop(); 

i2c_start(); 
i2c_write(0xd1); //Lee DS1307 
seconds = i2c_read(); 
minutes = i2c_read(); 
hours = i2c_read(); 
day = i2c_read(); 
date = i2c_read(); 
month = i2c_read(); 
year = i2c_read(0); //no ack 
i2c_stop(); 

if (day == 0x01 && month != 0x03 && month != 0x10 ){
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x01 && month == 0x03 && date < 0x25){
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x01 && month == 0x03 && date >= 0x25 && hours != 0x02){
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}

else if (day == 0x01 && month == 0x03 && date >= 0x25 && hours == 0x02){
hours = 0x03;
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}

else if (day == 0x01 && month == 0x10 && date < 0x25){
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x01 && month == 0x10 && date >= 0x25 && hours != 0x02){
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x01 && month == 0x10 && date >= 0x25 && hours == 0x02){
if (cambio_hora){  
hours = 0x01;
}
cambio_hora=!cambio_hora;
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}

else if (day == 0x02){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Lunes;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x03){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Martes;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x04){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Miércoles;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x05){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Jueves;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x06){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Viernes;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
else if (day == 0x07){
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Sábado;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
} 
}
El problema es que cuando hago esto:
Código:
else if (day == 0x01 && month == 0x10 && date >= 0x25 && hours == 0x02){
if (cambio_hora){  
hours = 0x01;
}
cambio_hora=!cambio_hora;
//Representa datos en la LCD 
printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year 
printf(lcd_putc,"Domingo;  %2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
}
Me cambia la hora bien al principio, es decir, pasa de las 2:00 a la 1:00 pero al volver a llegar a las 2:00, no sigue avanzando sino que salta a las 3:00.

Necesito ayuda para corregir este problema.
 
Última edición por un moderador:
Hola; buenas.
Tengo una duda con esto, yo tengo la programación del relojito, pero tengo la duda para hacer comparaciones con la hora.
Porque yo quiero dejarle unas alarmas para que me activen unas luces a x hora y esta es la programación.
Código:
// MODULO DE CONECCION DE LCD
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// PINES DE SALIDA DE LA LCD

typedef struct
{
unsigned short hor,min,seg;
}hora;
typedef struct
{
unsigned short dia,fec,mes,ano;
}fecha;
unsigned short BcdToShort(unsigned short bcd);
unsigned short ShortToBcd(unsigned short valor);
 void DS1307Inicio(void);
 void DS1307SetHora(Hora h);
 void DS1307SetFecha(Fecha f);
 Hora DS1307GetHora(void);
Fecha DS1307GetFecha(void);
unsigned short DS1307GetHoras(void);
unsigned short DS1307GetMinutos(void);
unsigned short DS1307GetSegundos(void);
void DS1307SetHoras(unsigned short ho);
void DS1307SetMinutos(unsigned short mi);
void DS1307SetSegundos(unsigned short se);
unsigned short DS1307GetDias(void);
unsigned short DS1307GetFechas(void);
unsigned short DS1307GetMeses(void);
unsigned short DS1307GetAnos(void);
void DS1307SetDias(unsigned short di);
void DS1307SetFechas(unsigned short fe);
void DS1307SetMeses(unsigned short me);
void DS1307SetAnos(unsigned short an);
unsigned short config(char etiquetas[9],unsigned short DATO, unsigned short xi, unsigned short xf);
void DS1307SetDir(unsigned short dir)
{
 I2C1_Start();
 I2C1_Wr(0xD0);
 I2C1_Wr(dir);
}
void main()
{
     char text[4];
     unsigned short DATO;
     unsigned short modo=0,va1=0;
     int short bandera=0;
     ansel=anselh=0;
     trisd=255;
     DS1307Inicio(); //inicio y configuracion de reloj
     Lcd_Init();
     Lcd_Cmd(_LCD_CURSOR_OFF);
     DATO = DS1307GetSegundos(); //se leen los segundos del reloj
     while(1)
     {
           if (portd.b0==1)
           {
           if (bandera==0)
           {
            Lcd_Cmd(_LCD_CLEAR);
            bandera=1;
            }
            if (portd.b1==1);
            {
            do{
            }
            while (portd.b1==1);
            if (modo<6)
            {modo++;}
            else
            {modo=0;}
            Lcd_Cmd(_LCD_CLEAR);
            }
            switch(modo)
            {
            case 0:
                  DATO=DS1307GetHoras();
                  DATO=Config("HORAS:",DATO,0,23);
                  DS1307SetHoras(DATO);
                  break;
                  
            case 1:
                  DATO=DS1307GetMinutos();
                  DATO=Config("MINUTOS:",DATO,0,59);
                  DS1307SetMinutos(DATO);
                  break;
            
            case 2:
                  DATO=DS1307GetSegundos();
                  DATO=Config("SEGUNDOS:",DATO,0,59);
                  DS1307SetSegundos(DATO);
                  break;
               
            case 3:
                  DATO=DS1307GetDias();
                  DATO=Config("DIA:",DATO,1,7);
                  DS1307SetDias(DATO);
                  break;
            
            case 4:
                  DATO=DS1307GetFechas();
                  DATO=Config("FECHA:",DATO,1,31);
                  DS1307SetFechas(DATO);
                  break;
                  
            case 5:
                  DATO=DS1307GetMeses();
                  DATO=Config("MES:",DATO,1,12);
                  DS1307SetMeses(DATO);
                  break;
                  
            case 6:
                  DATO=DS1307GetAnos();
                  DATO=Config("AÑO:",DATO,0,99);
                  DS1307SetAnos(DATO);
                  break;
            }
             Lcd_Cmd(_LCD_CLEAR);
            }
            else{
                bandera=0;
                while(DATO==DS1307GetSegundos())
                {delay_ms(200);}
                LCD_Out(1,1,"HRS:");    //SE LEEN LAS HORAS Y SE TRASMITE POR USART
                DATO = DS1307GetHoras();
                ByteToStr(DATO,Text);
                LCD_Out(1,5,Text);
                LCD_Chr(1,8,":");
                DATO = DS1307GetMinutos();
                ByteToStr(DATO,Text);
                LCD_Out(1,9,Text);
                LCD_Chr(1,12,":");
                DATO = DS1307GetSegundos();  //se leen los segundos y se trasmite por usart
                ByteToStr(DATO,Text);
                LCD_Out(1,13,Text);
                DATO = DS1307GetDias();
                switch(DATO)
                {
                case 1: LCD_Out(2,1,"Dom"); break;
                case 2: LCD_Out(2,1,"Lun"); break;
                case 3: LCD_Out(2,1,"Mar"); break;
                case 4: LCD_Out(2,1,"Mie"); break;
                case 5: LCD_Out(2,1,"Jue"); break;
                case 6: LCD_Out(2,1,"Vie"); break;
                case 7: LCD_Out(2,1,"Sab"); break;
                }
                DATO = DS1307GetFechas();
                ByteToStr(DATO,Text);
                LCD_Out(2,5,Text);
                LCD_Chr(2,8,"/");
                DATO = DS1307GetMeses();
                ByteToStr(DATO,Text);
                LCD_Out(2,9,Text);
                LCD_Chr(2,12,"/");
                DATO = DS1307GetAnos();
                ByteToStr(DATO,Text);
                LCD_Out(2,13,Text);
               }
              }
             }
             unsigned short BcdToShort(unsigned short bcd){
             unsigned short LV,HV;
             LV=bcd&0x0F;
             HV=(bcd>>4)&0x0f;
             return LV + HV*10;
            }
             unsigned short ShortToBcd(unsigned short valor){
             unsigned short HV,LV;
             HV=valor/10;
             LV=valor-HV*10;
             return LV+HV*16;
            }
             void DS1307Inicio(void)
            {
             unsigned short VAL[7],HV,LV,DATO;
             I2C1_Init(100000);  //inicio del bus i2c
             delay_ms(50); //retardo
             DS1307SetDir(0);
             I2C1_repeated_Start();
             I2C1_Wr(0xD1);
             VAL[0]=I2C1_Rd(1);
             VAL[1]=I2C1_Rd(1);
             VAL[2]=I2C1_Rd(1);
             VAL[3]=I2C1_Rd(1);
             VAL[4]=I2C1_Rd(1);
             VAL[5]=I2C1_Rd(1);
             VAL[6]=I2C1_Rd(0);
             I2C1_Stop();
             delay_ms(50);
              DATO=BcdToShort(VAL[0]);
             if (DATO>59)VAL[0]=0;
              DATO=BcdToShort(VAL[1]);
             if (DATO>59)VAL[1]=0;
              DATO=BcdToShort(VAL[2]);
             if (DATO>23)VAL[2]=0;
              DATO=BcdToShort(VAL[3]);
             if (DATO>7||DATO==0)VAL[3]=1;
              DATO=BcdToShort(VAL[4]);
             if (DATO>31||DATO==0)VAL[4]=1;
              DATO=BcdToShort(VAL[5]);
             if (DATO>12||DATO==0)VAL[5]=1;
              DATO=BcdToShort(VAL[6]);
             if (DATO>99)VAL[6]=0;
             DS1307SetDir(0);
             I2C1_Wr(VAL[0]);
             I2C1_Wr(VAL[1]);
             I2C1_Wr(VAL[2]);
             I2C1_Wr(VAL[3]);
             I2C1_Wr(VAL[4]);
             I2C1_Wr(VAL[5]);
             I2C1_Wr(VAL[6]);
             I2C1_Wr(0x10); //SE ACTIVA LA SALIDA OSILANTE 1Hz
             I2C1_Stop();
             delay_ms(50);
            }
             void DS1307SetHora(Hora h)
            {
             DS1307SetDir(0);
             I2C1_Wr(ShortToBcd(h.Seg));
             I2C1_Wr(ShortToBcd(h.Min));
             I2C1_Wr(ShortToBcd(h.Hor));
             I2C1_Stop();
            }
             void DS1307SetFecha(Fecha f)
            {
             DS1307SetDir(3);
             I2C1_Wr(ShortToBcd(f.Dia));
             I2C1_Wr(ShortToBcd(f.Fec));
             I2C1_Wr(ShortToBcd(f.Mes));
             I2C1_Wr(ShortToBcd(f.Ano));
             I2C1_Stop();
            }
            Hora DS1307GetHora(void)
            {
             Hora H;
             unsigned short VAL[3];
             DS1307SetDir(0);
             I2C1_repeated_Start();
             I2C1_Wr(0xD1);
             VAL[0]=I2C1_Rd(1);
             VAL[1]=I2C1_Rd(1);
             VAL[2]=I2C1_Rd(0);
             I2C1_Stop();
             H.Seg=BcdToShort(VAL[0]);
             H.Min=BcdToShort(VAL[1]);
             H.Hor=BcdToShort(VAL[2]);
             return H;
            }
             Fecha DS1307GetFecha(void)
            {
             Fecha F;
             unsigned short VAL[4];
             DS1307SetDir(3);
             I2C1_repeated_Start();
             I2C1_Wr(0xD1);
             VAL[0]=I2C1_Rd(1);
             VAL[1]=I2C1_Rd(1);
             VAL[2]=I2C1_Rd(1);
             VAL[3]=I2C1_Rd(0);
             I2C1_Stop();
             F.Dia=BcdToShort(VAL[0]);
             F.Fec=BcdToShort(VAL[1]);
             F.Mes=BcdToShort(VAL[2]);
             F.Ano=BcdToShort(VAL[3]);
             return F;
            }
             unsigned short DS1307GetHoras(void)
            {
             Hora h;
             h=DS1307GetHora();
             return h.Hor;
            }
             unsigned short DS1307GetMinutos(void)
            {
             Hora h;
             h=DS1307GetHora();
             return h.Min;
            }
             unsigned short DS1307GetSegundos(void)
            {
             Hora h;
             h=DS1307GetHora();
             return h.Seg;
            }
             void DS1307SetHoras(unsigned short ho)
            {
             Hora h;
             h=DS1307GetHora();
             h.Hor=ho;
             DS1307SetHora(h);
            }
             void DS1307SetMinutos(unsigned short mi)
            {
             Hora h;
             h=DS1307GetHora();
             h.Min=mi;
             DS1307SetHora(h);
            }
             void DS1307SetSegundos(unsigned short se)
            {
             Hora h;
             h=DS1307GetHora();
             h.Seg=se;
             DS1307SetHora(h);
            }
             unsigned short DS1307GetDias(void)
            {
             Fecha f;
             f=DS1307GetFecha();
             return f.Dia;
            }
             unsigned short DS1307GetFechas(void)
            {
             Fecha f;
             f=DS1307GetFecha();
             return f.Fec;
            }
             unsigned short DS1307GetMeses(void)
            {
             Fecha f;
             f=DS1307GetFecha();
             return f.Mes;
            }
             unsigned short DS1307GetAnos(void)
            {
             Fecha f;
             f=DS1307GetFecha();
             return f.Ano;
            }
             void DS1307SetDias(unsigned short di)
            {
             Fecha f;
             f=DS1307GetFecha();
             f.Dia=di;
             DS1307SetFecha(f);
            }
             void DS1307SetFechas(unsigned short fe)
            {
             Fecha f;
             f=DS1307GetFecha();
             f.Fec=fe;
             DS1307SetFecha(f);
            }
             void DS1307Setmeses(unsigned short me)
            {
             Fecha f;
             f=DS1307GetFecha();
             f.Mes=me;
             DS1307SetFecha(f);
            }
              void DS1307SetAnos(unsigned short an)
            {
             Fecha f;
             f=DS1307GetFecha();
             f.Ano=an;
             DS1307SetFecha(f);
            }
             unsigned short config(char etiquetas[9],unsigned short DATO,unsigned short xi, unsigned short xf){
             char text[4];
             ByteToStr(DATO,Text);
             LCD_Out(1,2,etiquetas);
             LCD_Chr(2,10,Text);
             if(portd.b2==1);
            {
             do{
            }
             while (portd.b2==1);
             if (DATO<xf)
             {DATO=DATO+1;}
             else
             {DATO=xi;}
           }
             if(portd.b3==1)
             {
             do{
            }
             while (portd.b3==1);
             if(DATO>xi)
           {
             {DATO=DATO-1;}
            }
             else
             {DATO=xf;}
           }
             return DATO;
     }
Espero que me puedan ayudar por favor, y gracias.
 
Última edición por un moderador:
Atrás
Arriba