Autor Tema: DS1307, valla con el RTC de los coj****  (Leído 4565 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
DS1307, valla con el RTC de los coj****
« en: 13 de Agosto de 2005, 07:11:00 »

Perdonen por el asunto pero ya me tiene un poco loco, llebo toda la mñn con el y no se ni si quiera que puedo estar haciendo mal.

Segun el datasheet, el mapa de memoria de este es tal cual:



Con esto, para guardar/configurar en los registros, por ejemplo yo intentando para probar los segundos, hay que seguir esto:



Y luego para leerlo y tal, esto otro:



Teniendo en cuenta la direccion del periferico en el bus i2c, que cambia segun sea leer o escribir, ¡¡no quiere funcionar!! Llorica

Codigo:

  #use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)
 
  void main(void)
  {
   int segundos;

   lcd_init();
   printf(lcd_putc,"fRTC DS1307
"Giño;
   
   i2c_start();
   i2c_write(0xd0);
   i2c_write(0);
   i2c_write(30);
   i2c_stop();
   
   delay_ms(10);
   
   i2c_start();
   i2c_write(0xd1);
   segundos = i2c_read(0);
   i2c_stop();
   
   delay_ms(10);
   
   printf(lcd_putc,"segundos = %d", segundos);
  }
   

Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #1 en: 13 de Agosto de 2005, 08:39:00 »
pq no usas una libreria??? prueba con esta, comparando veras el fallo

void escribir_ds1307(unsigned int8 direccion, unsigned int8 val);
void leer_ds1307(void);
unsigned int8 bin2bcd(unsigned int8 valor_binario);
unsigned int8 bcd2bin(unsigned int8 valor_bcd);


// direcciones para leer/escribir al reloj
#define  escribir_ds1307_cmd  0xd0
#define  leer_ds1307_cmd      0xd1


// registros del ds1307
#define  segundos             0
#define  minutos              1
#define  horas                2
#define  dia_semana           3
#define  dias                 4
#define  meses                5
#define  anios                6
#define  registro_de_control  7


// indice del array global que contiene los registros del reloj
#define DS1307_DATE_TIME_BYTE_COUNT 7


//para escribir en la memoria del reloj
#define DS1307_NVRAM_START_ADDR 8


// Con este valor desactivamos la señal de salida por el pin SQW
// porque consume mucha bateria si está activada.


#define DS1307_CONTROL_REG_INIT_VALUE 0x80

// 32.768 KHz para activar esta frecuencia de salida
//#define DS1307_CONTROL_REG_INIT_VALUE 0x13


//--------------------------------------------------------------------------
// GLOBAL VARIABLES

// Esta es la variable global donde irán almacenados los registros del reloj
//char registros_ds1307[DS1307_DATE_TIME_BYTE_COUNT];
unsigned int8 registros_ds1307[registro_de_control];


void escribir_ds1307(unsigned int8 direccion, unsigned int8 val)
{
      disable_interrupts(GLOBAL);

      val = bin2bcd(val);

      i2c_start();
      i2c_write(escribir_ds1307_cmd);
      i2c_write(direccion);
      i2c_write(val);
//      i2c_write(DS1307_CONTROL_REG_INIT_VALUE);
      i2c_stop();

      enable_interrupts(GLOBAL);
}

//----------------------------------------------------------------------
// Leer fecha y hora

// los registros del reloj están en este orden...
// y en bcd

// DS1307_SECONDS_REG_ADDR 0
// DS1307_MINUTES_REG_ADDR 1
// DS1307_HOURS_REG_ADDR 2
// DS1307_DAY_OF_WEEK_REG_ADDR 3
// DS1307_DATE_REG_ADDR 4
// DS1307_MONTH_REG_ADDR 5
// DS1307_YEAR_REG_ADDR 6


// seconds // 0-59 seconds
// minutes // 0-59 minutes
// hours // 0-23 hours
// day_of_week // 1-7
// date // 1-31 date
// month // 1-12 month
// year // 00-99 year (based on year 2000)

void leer_ds1307(void)
{
//      char i;
      unsigned int8 i;
//      disable_interrupts(GLOBAL);

      i2c_start();
      i2c_write(escribir_ds1307_cmd);
      // empezamos leyendo los segundos
      i2c_write(segundos);
      i2c_start();
      i2c_write(leer_ds1307_cmd);

      // leemos los 7 bytes restantes. hacemos mascaras para los bits que no usamos
      registros_ds1307[segundos] = i2c_read() & 0x7f;
      registros_ds1307[minutos] = i2c_read() & 0x7f;
      registros_ds1307[horas] = i2c_read() & 0x3f;
      registros_ds1307[dia_semana] = i2c_read() & 0x07;
      registros_ds1307[dias] = i2c_read() & 0x3f;
      registros_ds1307[meses] = i2c_read() & 0x1f;
      registros_ds1307[anios] = i2c_read(0);

      i2c_stop();

//      enable_interrupts(GLOBAL);

      // convertimos de bcd a binario

      for(i = 0; i < 7; i++)
         {
            registros_ds1307 = bcd2bin(registros_ds1307);
         }

}
/*
//------------------------------------------------------------------------
// funcion para leer en un registro de la memoria que trae incorporada el reloj

//char leer_byte_ds1307(char direccion)
unsigned int8 leer_byte_ds1307(unsigned int8 direccion)
{
//      char retval;
      unsigned int8 retval;

      disable_interrupts(GLOBAL);
      i2c_start();
      i2c_write(escribir_ds1307_cmd);
      i2c_write(direccion);
      i2c_start();
      i2c_write(leer_ds1307);
      retval = i2c_read(0); // no esperamos por ack
      i2c_stop();

      enable_interrupts(GLOBAL);

   return(retval);
}

*/
//-------------------------------------------------------------
// Esta función convierte de binario a bcd
//  Solo de 0 a 99

unsigned int8 bin2bcd(unsigned int8 valor_binario)
{
      unsigned int8 temp;
      unsigned int8 retval;

      temp = valor_binario;
      retval = 0;

      while(1)
         {
               // coge las decenas y les resta 10
               // para obtener unidades
               if(temp >= 10)
                  {
                     temp -= 10;
                     retval += 0x10;
                  }
               else
                  {
                     retval += temp;
                     break;
                  }
         }

   return(retval);
}

//--------------------------------------------------------------
// convierte de bcd a binario (0/99)

//char bcd2bin(char valor_bcd)
unsigned int8 bcd2bin(unsigned int8 valor_bcd)
{
      unsigned int8 valor_bin;
      valor_bin = valor_bcd;
      valor_bin >>= 1;
      valor_bin &= 0x78;

   return(valor_bin + (valor_bin >> 2) + (valor_bcd & 0x0f));
}




main.c

#include <18F2520.h>

#fuses NOWDT, WDT128, XT, NOPROTECT, BROWNOUT, BORV45, NOPUT, NOCPD
#fuses NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN
#fuses NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, NOLPT1OSC, MCLR, NOXINST

#use delay(clock=4000000)
#use i2c(Master, SDA=PIN_A0, SCL=PIN_A1)

#include <lcd.h>
#include <ds1307.h>

void main()
{
   port_b_pullups(true);
   setup_adc_ports(NO_ANALOGS);

   lcd_init();

   while(true)
   {
   leer_ds1307();
   delay_ms(1000);
   lcd_gotoxy(4,1);
   printf(lcd_putc,"%02u:%02u %02u/%02u/%02u",registros_ds1307[horas],registros_ds1307[minutos],registros_ds1307[dias],registros_ds1307[meses],registros_ds1307[anios]);
   }
}


con esto deberia fucionar ok

saludos! Giño

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #2 en: 13 de Agosto de 2005, 09:10:00 »
Gracias j1m !!

He conseguido hacerlo andar antes de leer tu post Helado pero de todas formas muchisimas gracias por la colaboración Sonrisa Gigante, en el codigo que he encontrado por los foros (uno de tantos, pero solo andaba este, otros ni compilaban) no convierte nada a BCD ni viceversa, es lo que no comprendo y funciona muy bien, lo tengo ahora mismo andando en la entrenadora y le corto la alimentacion y al encender continua bien con una pila de 3 V (no una tension de 3,5V que escuchado por el foro en Vbat).

Lo que hare es hacerme mi propia libreria con este codigo, ahi va ... y ademas ¡¡es veridico y aseguro que funciona!!

Codigo:

///////////////////////////////////////////////////////////////////////////
//// Práctica con el RTC DS1307                                        ////
//// Por Daniel G - by RaDoN (8/8/05)                                  ////
///////////////////////////////////////////////////////////////////////////

  #include <16f877.h>
  #fuses NOLVP,XT,NOWDT,NOPROTECT,PUT
  #use delay(clock=4000000)

  #include "LCD.C"
  //#include "24256.C"
  //#include "MOV_BOT.C"
  #include "DECO_RC5.C"
  #include "BUZZER.C"

  #ORG 0x1F00,0x1FFF {} //for the 8k 16F876/7 bootloader

  //#use fast_io(A)
  //#use fast_io(B)
  //#use fast_io(C)

  #byte port_a = 5
  #byte port_b = 6
  #byte port_c = 7
  #byte port_d = 8

  //#define bumper_izq PIN_B6   // pulsado = 0
  //#define bumper_drcha PIN_B7 // pulsado = 0

  #use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)

  //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

  void main(void)
  {

   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;

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

   //Justo cuando prende circuito, la fecha que establece es la siguiente
   seconds= 0x00;
   minutes= 0x56;
   hours = 0x15; //modo 24 hrs
   day = 0x07; //1 es domingo
   date = 0x13;
   month = 0x08;
   year = 0x05;
   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"Giño; //Limpia LCD
   lcd_putc("Real Time Clock
"Giño; //rtc
   lcd_putc(" ds1307"Giño;
   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();

      //Representa datos en la LCD
      printf(lcd_putc,"f%2x-%2x-20%2x
",date,month,year); //dd-mm-year
      printf(lcd_putc,"%2x:%2x:%2x",hours,minutes,seconds); //23:59:59
   }
  }



Lo he sincronizado con este reloj (creo que es atomico), http://www.time.gov/timezone.cgi?Eastern/d/-5/java
Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #3 en: 13 de Agosto de 2005, 09:17:00 »
enhorabuena Giño

posiblemente se desincronizará debido al cristal de 32Khz, lei en algun lado que se soluciona poniendole un par d condensadores (igual q en los pics), tendré q probarlo pq la verdad se suele atrasar unos 2 o 3 minutos al mes :S

saludos!

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #4 en: 13 de Agosto de 2005, 09:20:00 »
Aqui os dejo una foto, esta vivo el RTC!! jeje (no se asusteis por el ventilador) pero esque el 7805 se calienta bastante aun con el generoso disipador porque mi fuente es de 13.8V (aparte el bot consume como 200mA ... tantos modulos ... Avergonzado)




Edito: ahora la duda es par que otros codigos usan la conversion BCD y tal cuando este funciona y parece muy simple Idea
Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #5 en: 13 de Agosto de 2005, 09:51:00 »
no entiendo como te funciona, no le veo muxa logica ...... mira esto:


      seconds = i2c_read();

      minutes = i2c_read();

      hours = i2c_read();

      day = i2c_read();

      date = i2c_read();

      month = i2c_read();

aquí siempre está leyendo lo mismo no??? es decir, obtiene siempre la misma cadena... como distingues sino le aplicas la mascara entre segundos, minutos, horas, etc...??? amos... q no deberia funcionar bien :S

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #6 en: 13 de Agosto de 2005, 10:01:00 »
En el bus i2c tengo entendido que cuanod lees un byte de un registro, se posiciona en el siguiente, así pasa incluso con las memorias 24lcxx, y para grabar = Idea
Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #7 en: 13 de Agosto de 2005, 12:33:00 »
ok apuntado queda eso Giño

sobre el BCD ... estas seguro q eso funciona perfectamente??? prueba a meterle distintos valores de fecha y hora, pq yo al principio tmpc lo usaba la conversión, pero como dice en el DS del ds1307 es un reloj en BCD ... por lo q tendras q pasarle los datos en BCD, y los lees en BCD, por lo que para representarlos tendras q hacer la conversion binario normal. observa los segundos desde el 0 hasta el 59 ... creo que despues del 9 (0000 1001  esto es el BCD que te da el ds1307) te debería dar (0001 0000) es decir, "10" si haces la conversión, y como no la haces deberia salir "16" por el LCD, si te lo represnta bien... tonces no lo entiendo :P

saludos!

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #8 en: 13 de Agosto de 2005, 15:26:00 »
Si llebas razon, en la variable en este momento del 9 al 16 realmente, pero cuando lo representas en el LCD en vez de usar un entero normal (%d) lo hago representando en hexadecimal (%x), para probar esta bien. Pero si luego uno quiere trastear con las variables ahi que convertirlas a binario como bien dices RollEyes
Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #9 en: 13 de Agosto de 2005, 17:05:00 »
ummm y con hexadecimal no se da ese problema???  tb debería estar no??

yo lo el uso q le doy al DS1307 es un temporizador, y claro, tengo q "jugar" con los valores enteros de los minutos y las horas.

xao! Giño

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #10 en: 13 de Agosto de 2005, 17:43:00 »
Pues tratandolo como hexadecimal va perfecto ... la verdad esque entre hexadecimal y BCD no se que diferencia hay RollEyes
Si juegas contra el mejor, pierdes como los demás.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: DS1307, valla con el RTC de los coj****
« Respuesta #11 en: 13 de Agosto de 2005, 18:32:00 »
haberla haila :p no es lo mismo 0x10 que 0x0A ...aunq ya entiendo el pq...

0001 1001 ... 0x19 ... no se puede interpretar como un valor hexadecimal, seria algo así como un BCHex lo que tu estas usando Sonrisa Gigante

Desconectado RaDoN

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1498
RE: DS1307, valla con el RTC de los coj****
« Respuesta #12 en: 13 de Agosto de 2005, 18:38:00 »
Me voi a dejar de tonterias y lo paso a binario que total ni que costara mucho Flash
Si juegas contra el mejor, pierdes como los demás.

Desconectado sanpic

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 430
RE: DS1307, valla con el RTC de los coj****
« Respuesta #13 en: 17 de Agosto de 2005, 07:09:00 »
Hola amigos.
Aqui te dejo el codigo en Proton+. A mi me funciona perfecto.



Dim sec                 As Byte " segundos
Dim mins                As Byte " minutos
Dim hr                  As Byte " horas
Dim day                 As Byte " dia de la semana
Dim date                as BYTE " fecha
Dim mon                 As Byte " mes
Dim yr                  As Byte " anio


Read_1307:
                Busin  $D0,$00,[sec,MINs,hr,day,date,mon,yr]
                delayms 10
                hserout ["Fecha/Hora  : ",hex2 date,"/",hex2 mon,"/", hex2 yr,"  -  ",HEX2 hr, ":", HEX2 MINs, ":", HEX2 sec,13,10]
                "    LCDOUT $FE,1, hex2 date,"/",hex2 mon,"/", hex2 yr
                "    LCDOUT $FE,$c0, HEX2 hr, ":", HEX2 MINs, ":", HEX2 sec
               
                "    GoTo Leo_presion



Write_1307:
                            " seteo DIA/HORA  23/07/2005  1:20:00
        yr=$05
        mon=$07
        date=$23
        day=$06
        hr=$01
        sec=$00
        mins=$20
        Busout $D0,$00,[sec,mins,hr,day,date,mon,yr]
        delayms 100
        Return


Como dice el amigo J1M , tiene unos segundos de diferencia al mes , pero bueno , si la aplicacion no es crítica , no es determinante.
Si lo desean les paso un ejemplo para el DS1337 ,  este integrado tiene opcion para programarle 2 alarmas.  Me llevo 1 noche poder programarle la alarma , por no prestarle atencion al datashet  Ardiendo


Un abrazo a todos.

Angelito
IF you_know = true THEN                                 
     share_it
ENDIF

Desconectado pastito2003

  • PIC12
  • **
  • Mensajes: 65
RE: DS1307, valla con el RTC de los coj****
« Respuesta #14 en: 17 de Agosto de 2005, 11:12:00 »

Ayer compré un DS1302. Supongo que es lo mismo... revisando las librerías
de funciones del PCW PICC, tengo una para hacerlo funcionar, con un simple
ejemplo. Me parece simple y corto así es que lo pego.

Cuando lo arme les cuento.


Saludos
Para RADON: ¿No sería más elegante poner un 7809 por delante del 7805?
En vez del ventilador...



//////////////////////////////////////////////////////////////////////////
////                               DS1302.C                           ////
////                     Driver for Real Time Clock                   ////
////                                                                  ////
////  rtc_init()                                   Call after power up////
////                                                                  ////
////  rtc_set_datetime(day,mth,year,dow,hour,min)  Set the date/time  ////
////                                                                  ////
////  rtc_get_date(day,mth,year,dow)               Get the date       ////
////                                                                  ////
////  rtc_get_time(hr,min,sec)                     Get the time       ////
////                                                                  ////
////  rtc_write_nvr(address,data)                  Write to NVR       ////
////                                                                  ////
////  data = rtc_read_nvr(address)                 Read from NVR      ////
////                                                                  ////
//////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,1997 Custom Computer Services            ////
//// This source code may only be used by licensed users of the CCS C   ////
//// compiler.  This source code may only be distributed to other       ////
//// licensed users of the CCS C compiler.  No other use, reproduction  ////
//// or distribution is permitted without written permission.           ////
//// Derivative programs created using this software in object code     ////
//// form are not restricted in any way.                                ////
////////////////////////////////////////////////////////////////////////////

#ifndef RTC_SCLK

#define RTC_SCLK PIN_B1
#define RTC_IO   PIN_B3
#define RTC_RST  PIN_B2

#endif


void write_ds1302_byte(byte cmd) {
   byte i;

   for(i=0;i<=7;++i) {
      output_bit(RTC_IO, shift_right(&cmd,1,0) );
      output_high(RTC_SCLK);
      output_low(RTC_SCLK);
   }
}

void write_ds1302(byte cmd, byte data) {

   output_high(RTC_RST);
   write_ds1302_byte(cmd);
   write_ds1302_byte(data);
   output_low(RTC_RST);
}

byte read_ds1302(byte cmd) {
   byte i,data;

   output_high(RTC_RST);
   write_ds1302_byte(cmd);

   for(i=0;i<=7;++i) {
      shift_right(&data,1,input(RTC_IO));
      output_high(RTC_SCLK);
      delay_us(2);
      output_low(RTC_SCLK);
      delay_us(2);
   }
   output_low(RTC_RST);
   return(data);
}

void rtc_init() {
   byte x;
   output_low(RTC_RST);
   delay_us(2);
   output_low(RTC_SCLK);
   write_ds1302(0x8e,0);
   write_ds1302(0x90,0xa6);
   x=read_ds1302(0x81);
   if((x & 0x80)!=0)
     write_ds1302(0x80,0);
}

void rtc_set_datetime(byte day,byte mth,byte year,byte dow,byte hr,byte min) {
   write_ds1302(0x86,day);
   write_ds1302(0x88,mth);
   write_ds1302(0x8c,year);
   write_ds1302(0x8a,dow);
   write_ds1302(0x84,hr);
   write_ds1302(0x82,min);
   write_ds1302(0x80,0);
}

void rtc_get_date(byte & day,byte & mth,byte & year,byte & dow) {
   day = read_ds1302(0x87);
   mth = read_ds1302(0x89);
   year = read_ds1302(0x8d);
   dow = read_ds1302(0x8b);
}


void rtc_get_time(byte & hr,byte & min,byte & sec) {
   hr = read_ds1302(0x85);
   min = read_ds1302(0x83);
   sec = read_ds1302(0x81);
}

void rtc_write_nvr(byte address,byte data) {
   write_ds1302(address|0xc0,data);
}

byte rtc_read_nvr(byte address) {
    return(read_ds1302(address|0xc1));
}