Autor Tema: Ayuda para manejo de reloj dallas DS1307  (Leído 7585 veces)

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

Desconectado Petrihp

  • PIC10
  • *
  • Mensajes: 8
Ayuda para manejo de reloj dallas DS1307
« en: 22 de Julio de 2004, 06:45:00 »
Saludos a todos.!!

Gracias por la ayuda que me han prestado pero hoy de nuevo necesito de ustedes.

Estoy manejando 2 PIC (uno en forma esclavo y otro en maestro), habia tenido dificultades por que era la primera vez que manejaba la comunicacion I2C pero ahora eso esta superado y es realmente facil.

Ahora quiero adicionar un reloj en tiempo real dallas DS1307 que tambien trabajo bajo I2C, el CCS dispone del driver para manejo del DS1302 pero no de este. y el DS1302 no maneja I2C, tengo el PDF del DS1307 pero no entiendo algunas cosas que son:


El pin 7: (SQW/OUT) es un pin que genera una señal de 1HZ,4 - 8 y 32 KHZ, segun como se configure, pero para que me sirve esta señal. la informacion no viaja atraves del bus I2C, ¿Para que me sirve esta salida? Es indispensable utilizarla o sin ella puedo leer y escribir informacion.


Sobre la rutina de lectura y escritura apenas estoy empezando y estoy algo confuso. si alguien me puede ayudar sobre la secuencia le agradezco.


Desconectado gfp

  • PIC18
  • ****
  • Mensajes: 274
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #1 en: 22 de Julio de 2004, 08:55:00 »
Dale un ojo a este archivo, te puede ser de mucha utilidad. La verdad lo encontré en un rincón de la web, y aún no lo he probado.

/*********************************************************************
   DS1307.C

   This file handles the Dallas DS1307 Real Time Clock on Horoscas
   board.

   It use the mbus driver to communicate with the DS1307.
**********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
#include "ds1302.h"

#define DS1307_ADDR      0xd0

static int mbus_fd;

/*******************************************************************
   Setup_1302_Port
   
   Initialize Port Pins to access DS1302 Clock.

   Note that all three pins are defined initialliy as outputs.
   When you want to read a port pin, you have to turn it
   around.

   MCF5206...
   PP0 = CLOCK
   PP1 = RST*
   PP2 = DATA
********************************************************************/
void Setup_1302_Port(void)
{
   if ((mbus_fd = open("/dev/mbus", O_RDWR)) < 0) {
      perror("/dev/mbus";
      exit(1);
   }
}

/*******************************************************************
   Lock_1302

   This routine will LOCK the clock and stop its oscillator to
   preserve Battery Life.
   Uses TimeBuffer[] as temporary storage.
********************************************************************/
void Lock_1302 (void)
{
   int result;
   unsigned char buffer[4];            //temp storage

   buffer[0] = DS1307_ADDR;
   buffer[1] = 0;
   if ((result = read(mbus_fd, buffer, 3)) != 3) {
      fprintf(stderr, "DS1307 returned %d
", result);
      exit(1);
   }
   buffer[2] |= 0x80;
   if ((result = write(mbus_fd, buffer, 3)) != 3) {
      fprintf(stderr, "DS1307 returned %d
", result);
      exit(1);
   }
} /* end proc Lock_1203() */


/*******************************************************************
   Set_Time

   This routine SETs the clock and start its oscillator, write-
   protecting the clock registers.
   Obtains time from TimeBuffer[].
********************************************************************/
void Set_Time(unsigned char * TimeBuffer)
{
   int result;
   unsigned char buffer[10];

   TimeBuffer[7] = "x80";         //write protect the chip after write
   buffer[0] = DS1307_ADDR;
   buffer[1] = 0;
   memcpy(&buffer[2], TimeBuffer, 8);

   if ((result = write(mbus_fd, buffer, 10)) != 10) {
      fprintf(stderr, "DS1307 returned %d
", result);
      exit(1);
   }
} /* end proc Set_Time() */

/*******************************************************************
   Get_Time

   This routine GETs the time from the Dallas 1302 clock.
   The time is returned in TimeBuffer.
   This function returns 0 when the clock is operating properly.
   If the clock was locked (stopped) the default time is returned
   as 1/1/99, 12:00Noon and the function returns non-zero.
********************************************************************/
unsigned int Get_Time(unsigned char * TimeBuffer)
{
   unsigned int clock_locked;
   int result;
   unsigned char buffer[10];

   buffer[0] = DS1307_ADDR;
   buffer[1] = 0;
   if ((result = read(mbus_fd, buffer, 10)) != 10) {
      fprintf(stderr, "DS1307 returned %d
", result);
      exit(1);
   }
   memcpy(TimeBuffer, &buffer[2], 8);
   clock_locked = ((TimeBuffer[0] & 0x80) != 0);
   return(clock_locked);
} /* end proc Get_Time() */

Desconectado gfp

  • PIC18
  • ****
  • Mensajes: 274
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #2 en: 22 de Julio de 2004, 09:05:00 »
Dale un ojo a estas páginas, allí hay mucho relacionado con lo que buscas.
http://www.ccsinfo.com/forum/viewtopic.php?t=19926&highlight=ds1307

O bien si deseas utiliza el buscador e insertas ds1307.

http://www.ccsinfo.com/forum/search.php

Desconectado gfp

  • PIC18
  • ****
  • Mensajes: 274
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #3 en: 22 de Julio de 2004, 09:53:00 »
Aqui está lo que necesitas:

// DS1307.C
//
// Writes a base time and date to DS1307.  About every second reads
// time and date and displays to serial LCD on RA.0.
//
// Offers a good example of working with structures.  Note that
// structures may only be passed using pointers.
//
//    DS1307                         DS1307
//
// SCL (term 18)------------------- SCL (term 6) ----- To Other
// SDA (term 23) ------------------- SDA (term 5) ----- I2C Devices
//
// Note that there is no provision for the user defining the
// secondary I2C address using straps.
//

#case

#device PIC16F877 *=16 ICD=TRUE

#include <defs_877.h>
#include <lcd_out.h>
#include <i2c_mstr.h>

#define TRUE !0
#define FALSE 0

struct Time
{
   byte hr;
   byte mi;
   byte se;
};

struct Date
{
   byte yr;
   byte mo;
   byte da;
   byte weekday;
};

// routines used for DS1307
void set_up_clock(int control_reg);
void write_clock(struct Time *p_t, struct Date *p_d);
void read_clock(struct Time *p_t, struct Date *p_d);

void main(void)
{
   byte mem_adr;
   byte n;

   struct Time t_base={0x23, 0x59, 0x00}, t;
   struct Date d_base={0x00, 0x02, 0x28, 0x07}, d;

   lcd_init();
   i2c_master_setup();

   set_up_clock(0x10);  // sqwe enabled, 1 Hz output
   write_clock(&t_base, &d_base);

   while(1)
   {
      read_clock(&t, &d);
      lcd_init();
      printf(lcd_char, "%x/%x/%x %x:%x:%x",
                              d.yr, d.mo, d.da, t.hr, t.mi, t.se);
      lcd_clr_line(1);
      printf(lcd_char, "%x", d.weekday);
      delay_ms(1000);
   }
}

void set_up_clock(int control_reg)
{
   i2c_master_start();
   i2c_master_out_byte(0xd0);
   i2c_master_out_byte(0x07);  // control register address
   i2c_master_out_byte(control_reg);
   i2c_master_stop();
}

void write_clock(struct Time *p_t, struct Date *p_d)
{
   i2c_master_start();
   i2c_master_out_byte(0xd0);     // address
   i2c_master_out_byte(0x00);     // first address
   i2c_master_out_byte(p_t->se);
   i2c_master_out_byte(p_t->mi);
   i2c_master_out_byte(p_t->hr);  // 24 hour format - 0x40 for 12 hour time
   i2c_master_out_byte(p_d->weekday);
   i2c_master_out_byte(p_d->da);
   i2c_master_out_byte(p_d->mo);
   i2c_master_out_byte(p_d->yr);
   i2c_master_stop();
}

void read_clock(struct Time *p_t, struct Date *p_d)
{
   i2c_master_start();
   i2c_master_out_byte(0xd0);   // 1101 000 0
   i2c_master_out_byte(0x00);  // first address
   i2c_master_stop();

   i2c_master_repeated_start();
   i2c_master_out_byte(0xd1);
   p_t->se = i2c_master_in_byte(TRUE) & 0x7f;
   p_t->mi = i2c_master_in_byte(TRUE);
   p_t->hr = i2c_master_in_byte(TRUE) & 0x3f;

   p_d->weekday = i2c_master_in_byte(TRUE) & 0x07;
   p_d->da = i2c_master_in_byte(TRUE) & 0x3f;
   p_d->mo = i2c_master_in_byte(TRUE) & 0x3f;
   p_d->yr = i2c_master_in_byte(FALSE);
   // no ack prior to stop
   i2c_master_stop();
}

#include <lcd_out.c>
#include <i2c_mstr.c>

Desconectado pendexgabo

  • PIC16
  • ***
  • Mensajes: 222
    • www.SosaGabriel.com.ar
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #4 en: 22 de Julio de 2004, 20:40:00 »
mira hace un tiempo hice una libreria para el manejo del RTC que vos necesitas, la verdad que no puede probarlo.. pero sera cuestion de que vos nos digas que pasa !!

el archivo se llama ds1307.h y esta por algun lado de las biblotecas de archivos del foro ya que cualdo la hice, este foro ya no disponia de lugar para adjuntar archivos.

ALGUIEN POR FAVOR QUE NOS PASE LA DIR DEL ALMECEN DE ARCHIVOS!!

si lo podes probar, decime luego que tal te fue!!

saludos
gabriel


aca encontre la pagina donde deje el archivo!!!

http://miarroba.com/foros/ver.php?foroid=256746&temaid=1515603

Desconectado Petrihp

  • PIC10
  • *
  • Mensajes: 8
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #5 en: 23 de Julio de 2004, 10:04:00 »
Ok. Gracias a todos por la ayuda


Utilice la libreria DS1307.C que aparece en el foro de CCS en la dirección que arriba ya dieron y funciono de pelos, aunque hay que hacer una pequeña modificacion ya que por un error de escitura una funcion la uilizaron diferente a como la definieron pero es solo unos caracteres que falta. En este ejemplo no utilizan el pin 7 (SQW) y la verdad no se para que me seria util la señal que arroja por este pin, Si alguien sabe para que es utili este señal favor decirmelo.

Bueno si tienen alguna no duden en preguntar ..




Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #6 en: 23 de Julio de 2004, 10:42:00 »
Este pin lo suelen utilizar para hacer una alarma o aviso, ya que este reloj no trae ninguna integrada.

Puedes meter este pin en el micro y procesar con esa frecuencia una parte de codigo que active una sirena o lámpara, o un led, etc que actue en señal de aviso o alarma, o incluso más simple. A lo mejor se puede conectar a la base de un transitor que forme una red con un buzzer y así ya tienes una señal sonora a la frecuencia que te de ese pin.


Saludos.

Desconectado YF-21

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 185
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #7 en: 08 de Enero de 2005, 19:28:00 »
Disculpen foristas, no he encontrado solucion a este integrado Llorando

Bajé la libreria del foro de CCS y me parece que es esta ...

Codigo:
//=========================================
// ds1307.c -- Functions for the Dallas Semiconductor DS1307
// real time clock and NVRAM chip.
//
// The DS1307 uses BCD as its internal format, but we use it
// in binary format, outside of this module. So we have code
// to convert to/from BCD to binary in the functions below.

//----------------------------------------------------------------------
// Set the date and time.

/*
The registers inside the ds1307 are in this format. The values are in BCD.

DS1307_SECONDS_REG 0
DS1307_MINUTES_REG 1
DS1307_HOURS_REG 2
DS1307_DAY_OF_WEEK_REG 3 // We don"t use this register. Set it to 0.
DS1307_DATE_REG 4
DS1307_MONTH_REG 5
DS1307_YEAR_REG 6
*/

#define DS1307_I2C_WRITE_ADDR 0xd0
#define DS1307_I2C_READ_ADDR 0xd1

// DS1307 register offsets
#define DS1307_SECONDS_REG 0
#define DS1307_MINUTES_REG 1
#define DS1307_HOURS_REG 2
#define DS1307_DAY_OF_WEEK_REG 3
#define DS1307_DATE_REG 4
#define DS1307_MONTH_REG 5
#define DS1307_YEAR_REG 6
#define DS1307_CONTROL_REG 7


#define DS1307_DATE_TIME_BYTE_COUNT 7 // Includes bytes 0-6

#define DS1307_NVRAM_START_ADDR 8

// We disable the SQWV output, because it uses
// a lot of battery current when it"s enabled.
// Disable it by setting Out = Open Collector.

#define DS1307_CONTROL_REG_INIT_VALUE 0x80


char gca_ds1307_regs[DS1307_DATE_TIME_BYTE_COUNT];

void ds1307_set_date_time(void);
void ds1307_read_date_time(void);
char ds1307_read_byte(char addr);
char bcd2bin(char bcd_value);
char bin2bcd(char bin_value);
void ds1307_write_byte(char addr, char value);


void ds1307_set_date_time(void)
{
char i;
// Convert the binary ds1307 data, which is passed in a global array,
// into bcd data. Store it in the same array.

for(i = 0; i < 7; i++)
{
gca_ds1307_regs = bin2bcd(gca_ds1307_regs);
}

// There are two control bits embedded in the following data.
// The Clock Halt bit is in bit 7 of the DS1307 Seconds register.
// We need to make sure that it"s = 0, to make the clock run.
// The other bit is the 24/12 hour clock format bit, in bit 6 of
// the DS1307 Hours register. We need 24 hour mode, so set it = 0.

gca_ds1307_regs[DS1307_SECONDS_REG] &= 0x7f;
gca_ds1307_regs[DS1307_HOURS_REG] &= 0x3f;

// Now write the 7 bytes of BCD data to the ds1307,
// using inline code for speed.
disable_interrupts(GLOBAL);

i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
// Start reading at the Seconds register.
i2c_write(DS1307_SECONDS_REG);

// Write 7 bytes, to registers 0 to 6.

for(i = 0; i < 7; i++)
{
i2c_write(gca_ds1307_regs);
}

// After setting the time in registers 0-6, also set the
// Control register. (index = 7)

// This just turns off the squarewave output pin.
// Doing it here, every time we set the clock registers,
// seems less risky than setting it near the
// start of the program, every time the unit powers-up.
i2c_write(DS1307_CONTROL_REG_INIT_VALUE);

i2c_stop();

enable_interrupts(GLOBAL);
}

//----------------------------------------------------------------------
// Read the date and time.

// The registers inside the ds1307 are in this order.
// The values inside the registers are in 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

// We return the data in a global array. The data in is binary.

// 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 ds1307_read_date_time(void)
{
char i;
disable_interrupts(GLOBAL);

i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
// Start reading at the Seconds register.
i2c_write(DS1307_SECONDS_REG);

i2c_start();
i2c_write(DS1307_I2C_READ_ADDR);

// Read the 7 bytes from the ds1307. Mask off the unused bits.
gca_ds1307_regs[DS1307_SECONDS_REG] = i2c_read() & 0x7f;
gca_ds1307_regs[DS1307_MINUTES_REG] = i2c_read() & 0x7f;
gca_ds1307_regs[DS1307_HOURS_REG] = i2c_read() & 0x3f;
gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG] = i2c_read() & 0x07;
gca_ds1307_regs[DS1307_DATE_REG] = i2c_read() & 0x3f;
gca_ds1307_regs[DS1307_MONTH_REG] = i2c_read() & 0x1f;
gca_ds1307_regs[DS1307_YEAR_REG] = i2c_read(0);

i2c_stop();

enable_interrupts(GLOBAL);

// Now convert the data from BCD to binary.
// Do it after reading the bytes, so that
// the i2c reads can be done quickly.

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

}

//------------------------------------------------------------------------
// Read one byte at the specified address.
// This function is used to access the control byte
// or the NVRAM bytes.

char ds1307_read_byte(char addr)
{
char retval;

disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);

i2c_start();
i2c_write(DS1307_I2C_READ_ADDR);
retval = i2c_read(0); // Don"t ACK the last byte read
i2c_stop();
enable_interrupts(GLOBAL);

return(retval);
}

//----------------------------------------------------------------------
// Write one byte to the DS1307.
// This function is used to access the control byte
// or the NVRAM bytes.

void ds1307_write_byte(char addr, char value)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);
i2c_write(value);
i2c_stop();
enable_interrupts(GLOBAL);
}
//-------------------------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.

char bin2bcd(char binary_value)
{
char temp;
char retval;

temp = binary_value;
retval = 0;

while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += temp;
break;
}
}

return(retval);
}

//--------------------------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.

char bcd2bin(char bcd_value)
{
char temp;

temp = bcd_value;
// Shifting upper digit right by 1 is same as multiplying by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;

// Now return: (Tens * 8) + (Tens * 2) + Ones

return(temp + (temp >> 2) + (bcd_value & 0x0f));

}


y el programa que utilizo para probarlo es este ...

[code]#include <16F877a.h>
//test.c
///////////////////////////////////////////////////////////////////////////////
//
//
// DS1307 Driver file from PCM Programmer 18-11-03
// Version 1
//
//
////////////////////////////////////////////////////////////////////////////////

// If your demo board is running at 4 MHz, then change
// the HS to be XT, in the line below.

#fuses HS,NOWDT,NOPROTECT,NOPUT,NOLVP,XT

// If you are using a 4 MHz crystal (or 20 MHz) then change
// the value in the next line, to match your crystal frequency.
#use delay(clock=4000000)
#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)
#use rs232 (baud=9600, xmit=PIN_C6,rcv=PIN_C7)

//========================================

#include <ds1307.c>
#include "lcd.c"
lcd_init ();
#use fast_io (d)
#use fast_io (b)
#use fast_io (c)

// DS1307 register offsets
//#define DS1307_SECONDS_REG 0
//#define DS1307_MINUTES_REG 1
//#define DS1307_HOURS_REG 2
//#define DS1307_DAY_OF_WEEK_REG 3
//#define DS1307_DATE_REG 4
//#define DS1307_MONTH_REG 5
//#define DS1307_YEAR_REG 6
//#define DS1307_CONTROL_REG 7


//#define DS1307_DATE_TIME_BYTE_COUNT 7 // Includes bytes 0-6

//#define DS1307_NVRAM_START_ADDR 8

// We disable the SQWV output, because it uses
// a lot of battery current when it"s enabled.
// Disable it by setting Out = Open Collector.

//#define DS1307_CONTROL_REG_INIT_VALUE 0x80

// 32.768 KHz output
//#define DS1307_CONTROL_REG_INIT_VALUE 0x13

main()
{
char sec;
char min;
char hrs;
char day;
char date;
char month;
char yr;

lcd_putc ("fStart
"Giño;

delay_ms (5000);
// Put some date and time values into the global date & time array.
gca_ds1307_regs[DS1307_SECONDS_REG] = 0; // 0 seconds
gca_ds1307_regs[DS1307_MINUTES_REG] = 10; // 10 minutes
gca_ds1307_regs[DS1307_HOURS_REG] = 8; // 8 AM
gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG]= 0; // Skip this.
gca_ds1307_regs[DS1307_DATE_REG] = 19; // 19th
gca_ds1307_regs[DS1307_MONTH_REG] = 4; // April
gca_ds1307_regs[DS1307_YEAR_REG] = 02; // 2002

// Write these values to the DS1307, for testing.
ds1307_set_date_time();

// Now read the date and time once every second, and display it.
while(1)
{
delay_ms(1000);

ds1307_read_date_time();

// Get these into variables with shorter names, so I can
// put them into printf more easily.
sec = gca_ds1307_regs[DS1307_SECONDS_REG];
min = gca_ds1307_regs[DS1307_MINUTES_REG];
hrs = gca_ds1307_regs[DS1307_HOURS_REG];
day = gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG];
date = gca_ds1307_regs[DS1307_DATE_REG];
month = gca_ds1307_regs[DS1307_MONTH_REG];
yr = gca_ds1307_regs[DS1307_YEAR_REG];


lcd_putc (printf("f%d/%d/%02d
%02d:%02d:%02d",month,date,yr, hrs,min,sec));
}
}[/code]

Lo que hace al conectarlo es aparecer en la lcd simbolos raros y despues se llena la lcd con simbolos raros (ni siquiera ejecuta bien el lcd_putc ("fStart
"Giño...
alguna idea del porque ??

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #8 en: 09 de Enero de 2005, 00:26:00 »
Yo creo que el problema puede venir por la conexión del integrado, creo que el datasheet lo deja bastante claro, pero el caso es que picamos muchos.

El pin Vbat, tiene que estar con una tensión de 3,5V, (no pruebes con otra tensión porque irá mal), o si no quieres poner batería de respaldo asegurate de que el pin lo pones a masa, nunca lo dejes "al aire".


Si no es problema de conexión yo tengo un código que funciona, aunque no es muy diferente de los que ya están posteados.

Un saludo.

Desconectado YF-21

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 185
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #9 en: 10 de Enero de 2005, 14:27:00 »
Por favor oshow podrias postearlo ?? o si no enviarmelo por un privado??

De cualquier manera esta vez lo intentaré conectar con programacion i2c ya que en una pagina encontré que se escribía y se leía como cualquier otro dispositivo i2_c, el mapa de memoria viene en el datasheet, asi que probaré suerte de esa manera. Por cierto yo le conectaba 3 V de bateria, pero esta vez la conectaré a tierra. En el siguiente post espero comentar mi victoria ( o mi fracaso Enfurruñado ).

PD: oshow recuerda postear el codigo (y un ejemplo si se puede por favor ... Giño)

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #10 en: 10 de Enero de 2005, 15:48:00 »
Hola, repito lo de la conexión porque es bastante importante, en su día perdí un par de horas por culpa de la conexión, o le metes 3,5V o lo pones a masa, sino el relojito no te hace ni caso y no hay más que hablar, así que lo de la batería no debería darte más problema si es de 3,5V.



Codigo:

#include <16F876A.h>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD
#use delay (clock=4000000)
#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3,force_hw)
#include <lcd.c>
#include <libreria_ds1307.c>


void main( void )
{

  lcd_init();
  lcd_putc("Empezando...");
  delay_ms(2000);

//escribimos la fecha en los registros

      registros_ds1307[0] = 15; //  segundos
      registros_ds1307[1] = 24; // minutos
      registros_ds1307[2] = 17; // horas
      registros_ds1307[3]= 0;
      registros_ds1307[4] = 6; // dia
      registros_ds1307[5] = 9; // Mes
      registros_ds1307[6] = 04; // año

// Escribir valores al DS1307
      ajustar_hora_fecha();
      lcd_putc("f");

  while ( TRUE )
  {

      leer_hora_fecha();

      lcd_gotoxy(1,1);
      printf(lcd_putc,"%02u:%02u:%02u",registros_ds1307[horas],registros_ds1307[minutos],registros_ds1307[segundos]);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"%02u%s%02u",registros_ds1307[fecha],meses1[registros_ds1307[mes]-1],registros_ds1307[anio]);
      delay_ms(500);
  }
}




Y el driver del reloj:

Codigo:

////////////////////////////////////////////////////////////////////////////
////                             libreria_ds1307.c                      ////
////            Driver para reloj i2c de Dallas semiconductors          ////
////                                                                    ////
////                                                                    ////
////                                                                    ////
////                                                                    ////
////                                                                    ////
////            Adaptación por ....                                     ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////
//Prototipos del reloj:                                                       //
//    -ajustar_fecha_hora(): Escribimos via i2c la hora, fecha, mes, año...   //
//    -leer_hora_fecha(): Leemos via i2c todos los datos del reloj            //
//    -bin2bcd(): Rutina para comnvertir de binario a bcd                     //
//    -bcd2bin(): Rutina para convertir de bcd a binario                      //
////////////////////////////////////////////////////////////////////////////////

void ajustar_hora_fecha(void);
void leer_hora_fecha(void);

void escribir_byte_ds1307(char direccion, char val);
char leer_byte_ds1307(char direccion);

char bin2bcd(char valor_binario);
char bcd2bin(char valor_bcd);




////////////////////////////////////////////////////////////////////////////////
//    Registros definiciones y variables usadas por el reloj, para almacenar  //
//    registros, comandos y funciones.                                        //
////////////////////////////////////////////////////////////////////////////////

/*Registros del reloj, los valores de éstos estan siempre en bcd
Según la posicion dentro del array almacenamos distintos registros:

   SEGUNDOS             registros_ds1307[0]
   MINUTOS              registros_ds1307[1]
   HORAS                registros_ds1307[2]
   DIA DE LA SEMANA     registros_ds1307[3]
   FECHA                registros_ds1307[4]
   MES                  registros_ds1307[5]
   AÑO                  registros_ds1307[6]
*/


////////////////////////////////////////////////////////////////////////////////
//     Registros del ds1307.                                                  //
////////////////////////////////////////////////////////////////////////////////

#define segundos 0
#define minutos 1
#define horas 2
#define dia_semana 3
#define fecha 4
#define mes 5
#define anio 6
#define registro_de_control 7

////////////////////////////////////////////////////////////////////////////////
/// Direcciones para leer/escribir al reloj.                                  //
////////////////////////////////////////////////////////////////////////////////

#define escribir_ds1307 0xd0
#define leer_ds1307 0xd1

// Definimos un array global que contendrá los 7 registros del reloj...
#define DS1307_DATE_TIME_BYTE_COUNT 7


//para escribir en la memoria NVRAM qu etrae el 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

//    Para activar el pin SQW a una frecuencia de 32768Hz
//    Descomentaremos esta definicion
//
//#define DS1307_CONTROL_REG_INIT_VALUE 0x13


////////////////////////////////////////////////////////////////////////////////
//    Con este array visualizamos el mes actual en formato texto.             //
////////////////////////////////////////////////////////////////////////////////

const char meses1[12][4]=
   {
      "Ene",
      "Feb",
      "Mar",
      "Abr",
      "May",
      "Jun",
      "Jul",
      "Ago",
      "Sep",
      "Oct",
      "Nov",
      "Dic"
    };

////////////////////////////////////////////////////////////////////////////////
//    Esta es la variable global donde irán almacenados                       //
//    los registros del reloj.                                                //
////////////////////////////////////////////////////////////////////////////////

char registros_ds1307[DS1307_DATE_TIME_BYTE_COUNT];


////////////////////////////////////////////////////////////////////////////////
//  Esta función convierte un valor comprendido entre 0 y 99 de binario a BCD //
////////////////////////////////////////////////////////////////////////////////

char bin2bcd(char valor_binario)
{
      char temp;
      char 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);
}

////////////////////////////////////////////////////////////////////////////////
// Esta función convierte un valor comprendido entre 0 y 99 de BCD a binario  //
////////////////////////////////////////////////////////////////////////////////

char bcd2bin(char valor_bcd)
{
      char temp;

      temp = valor_bcd;

      temp >>= 1;

      temp &= 0x78;



   return(temp + (temp >> 2) + (valor_bcd & 0x0f));

}



////////////////////////////////////////////////////////////////////////////////
//    Con esta función escribimos la hora y la fecha mediante i2c en el reloj //
//    DS1307.                                                                 //
//                                                                            //
//    Primero convertiremos los valores de binario a BCD para poder           //
//    almacenarlos, seguidamente desactivaremos las interrupciones            //
//    para no interrumpir la transmision, y los enviaremos con las            //
//    funciones del compilador para el manejo de i2c.                         /7
////////////////////////////////////////////////////////////////////////////////


void ajustar_hora_fecha(void)
{
      char i;


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

      // Existen 2 bits de control en los registros del reloj, hay uno
      //para parar el reloj en el bit 7 del registro de los segundos.
      // tenemos que asgurarnos que éste es cero para que el reloj funcione
      //hay otro bit para seleccionar modo 12/24 horas, para poner en modo de
      // 24 horas, lo ponemos a cero,sino a 1

      registros_ds1307[segundos] &= 0x7f;
      registros_ds1307[horas] &= 0x3f;

      // escribimos los datos en bcd al array global

      disable_interrupts(GLOBAL);

      i2c_start();
      i2c_write(escribir_ds1307);
      // se empieza leyendo los segundos
      i2c_write(segundos);

      // y luego se escriben 7 bytes más....

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

      // despues de ajustar los registros
      // modificamos el registro de control
      i2c_write(DS1307_CONTROL_REG_INIT_VALUE);

      i2c_stop();

      enable_interrupts(GLOBAL);
}

////////////////////////////////////////////////////////////////////////////////
//    Con esta función leemos la hora y la fecha mediante i2c del array       //
//    global que contiene todos los registros en BCD                          //
//                                                                            //
//    Primero desactivaremos las interrupciones para evitar que interrumpan   //
//    la transmision, seguidamente usamos las funciones del compialdor        //
//    para el manejo de i2c y por último convertiremos de BCD a binario       //
//    para poder visualizarlas correctamente.                                 //
////////////////////////////////////////////////////////////////////////////////
//    Los valores almacenados en el array podrán estar comprendidos entre:    //
//                                                                            //
//    Segundos       0-59                                                     //
//    Minutos        0-59                                                     //
//    Horas          0-23                                                     //
//    Dia semana     1-7                                                      //
//    Dia            1-31                                                     //
//    Mes            1-12                                                     //
//    Año            00-99 (a partir del año 2000)                            //
////////////////////////////////////////////////////////////////////////////////

void leer_hora_fecha(void)
{
      char i;
      disable_interrupts(GLOBAL);

      i2c_start();
      i2c_write(escribir_ds1307);
      // empezamos leyendo los segundos
      i2c_write(segundos);

      i2c_start();
      i2c_write(leer_ds1307);

      // 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[fecha] = i2c_read() & 0x3f;
      registros_ds1307[mes] = i2c_read() & 0x1f;
      registros_ds1307[anio] = 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 NVRAM que trae           //
//    incorporada el reloj DS1307.                                            //
////////////////////////////////////////////////////////////////////////////////

char leer_byte_ds1307(char direccion)
{
      char retval;

      disable_interrupts(GLOBAL);
      i2c_start();
      i2c_write(escribir_ds1307);
      i2c_write(direccion);

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

      enable_interrupts(GLOBAL);

   return(retval);
}

////////////////////////////////////////////////////////////////////////////////
//    Funcion para escribir en un registro de la memoria NVRAM que trae       //
//    incorporada el reloj DS1307.                                            //
////////////////////////////////////////////////////////////////////////////////

void escribir_byte_ds1307(char direccion, char val)
{
      disable_interrupts(GLOBAL);

      i2c_start();
      i2c_write(escribir_ds1307);
      i2c_write(direccion);
      i2c_write(val);
      i2c_stop();

      enable_interrupts(GLOBAL);
}



El código funciona, lo he comprobado en una pequeña plaquita que tengo por aquí.


Un saludo.

PD: No sé porque co... deja un espacio de separación entre lineas al postearlo, alguien sabe porque??

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #11 en: 11 de Enero de 2005, 11:20:00 »
Oshow, cuando yo posteo código usando el Internet Explorer no sale el doble espacio, pero cuando lo posteo o leo con Netscape, sale el doble espacio, tal vez sólo sea tu browser.

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #12 en: 11 de Enero de 2005, 12:00:00 »
Oye.. pues tienes toda la razón del mundo... es el navegador... que curioso...

Un saludo

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #13 en: 11 de Enero de 2005, 13:57:00 »
mira a ver si en el navegador puedes configurar el interlineado, pq no esq deje dos espacios, creo q es que la separacion es mayor de lo normal :P

Salu2!!!

Desconectado YF-21

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 185
RE: Ayuda para manejo de reloj dallas DS1307
« Respuesta #14 en: 11 de Enero de 2005, 22:15:00 »
Victoria !!! Rebotado

Aqui esta un codigo que me funcionó con una lcd 16*2 ...

Codigo:
// Este programa maneja la comunicacion i2c con un reloj de tiempo //
// real y los datos son visualizados en una lcd de 2X16 caracteres //
// del       foro      todopic       por      yf-21              //

#include "16f877a.h"
#use delay (clock=4000000)
#fuses xt,noput,nolvp,noprotect,nowdt
#use i2c (master, sda=pin_c4, scl=pin_c3)
#include "lcd.c"

// DS1307 control bytes
#define WRITE_DS1307 0xd0     //Direccion i2c obtenido del datasheet
#define READ_DS1307 0xd1      //Si cambias el 0 a 1 la siguiente accion será
                              //leer el dispositivo

// Registros del DS1307
#define seg 0            //Echale un ojo al datasheet
#define min 1
#define hrs 2
#define day 3
#define date 4
#define month 5
#define year 6
#define ctrl 7
#define DATE_TIME 7
#define DS1307_RAM_ADDR 8           //La ram abarca de (0x08) a (0x3F)
#define CONTROL_INIT_VAL 0x80       //SQWE deshabilitada pero el pin esta a 1

//Variables globales //
int regs[DATE_TIME];        // buffer (arreglo) para los bytes del ds1307
int8 temp_r;                // final BCD temp result

BOOLEAN i2c_ready()
   {
      int1 ack;
      i2c_start();            // If the write command is acknowledged,
      ack = i2c_write(WRITE_DS1307);  // then the device is ready.
      i2c_stop();
      return ack;
   }


// this function converts an 8 bit binary value
// to an 8 bit BCD value. Input range from 0 to 99.

char toBCD(char bin_val)
{
   char temp;              //Variable temporal
   char retval;            //Valor convertido

   temp = bin_val;         //La variable temporal=valor binario
   retval = 0;             //Valor convertido =0 (hasta ahora)

   while(1)
   {
   // get tens digit by multiple subtraction
   // of 10 from bin_val
      if(temp >= 10)
      {
         temp -= 10;
         retval += 0x10; // increment tens digit
      }
         else            // get ones digit by adding remainder
      {
         retval += temp; // adjusted result
         break;
      }
   }
         return(retval);
}

// set time & date on power-up
void set_time(void)
{
   char i;

   // put initial date/time into array
   regs[seg]  = 55;// seconds
   regs[min]  = 59;// minutes
   regs[hrs]  = 21;// hour
   regs[day]  = 0; // not used
   regs[date] = 14;// date
   regs[month]= 07;// month
   regs[year] = 04;// year

   // convert to BCD

   for(i=0; i<7; i++)
   {
      regs = toBCD(regs);
   }

   regs[seg] &= 0x7f;
   regs[hrs] &= 0x3f;

   // write 7 bytes of BCD data to ds1307
   i2c_start();
   i2c_write(WRITE_DS1307);

   // start at seconds register
   i2c_write(seg);

   // write 7 bytes to registers 0 to 6
   for(i=0; i<7; i++)
   {
      i2c_write(regs);
   }
   i2c_write(CONTROL_INIT_VAL);
   i2c_stop();
}

// read time & date from DS1307
void read_time(void)
{
   i2c_start();
   i2c_write(WRITE_DS1307);

   // start i2c read at seconds register
   i2c_write(seg);

   i2c_start();
   i2c_write(READ_DS1307);

   // read the 7 bytes from the ds1307. Mask off the unused bits
   regs[seg] = i2c_read() & 0x7f;
   regs[min] = i2c_read() & 0x7f;
   regs[hrs] = i2c_read() & 0x3f;
   regs[day] = i2c_read() & 0x07;
   regs[date] = i2c_read() & 0x3f;
   regs[month] = i2c_read() & 0x1f;
   regs[year] = i2c_read(0);

   i2c_stop();

}

void main ()
{
   lcd_init ();               //A inicializar la lcd
   set_time ();               //Escribimos la fecha
   do
   {
   }while (i2c_ready());  //Esperamos a que se desocupe la linea i2c

   while (1)
   {
      read_time ();           //Leemos la hora
      printf (lcd_putc,"f%02x:%02x:%02x
",regs[2],regs[1],regs[0]);
      printf (lcd_putc,"
%02x/%02x/%02x
",regs[4],regs[5],regs[6]);
      delay_ms (1000);
   }
}


Como podran ver, es "otra version del codigo del foro de ccs" ( Ahora que lo modifiqué, ya lo entendí Vacilando ).
Aunque me quedé con la duda de si el retraso "en el peor de los casos" de +-2 seg por mes que dice el datasheet será cierto ... habrá que averiguarlo Muchas risas

Gracias foristas por leer los posts !!!  Giño


 

anything