Go Down

Topic: DS1307 library for Arduino 1.0 and above (Read 1 time) previous topic - next topic

picoPAN

Hello everybody,

some of you might want to work with the DS1307 real time clock (RTC) on an Arduino board.
The libraries that I could find so far seemed to me mostly a bit difficult to work with.

So I adapted a different one for Arduino 1.0 and above that I found much more comfortable to use. It was tested to work fine with Arduino 1.5.

I am not the original author of this library. Though I can't trace back it's origin anymore.

Here the header:
Code: [Select]
/*
  DS1307.h - library for DS1307 RTC
 
  for Arduino 1.0 and above
  June 28th, 2013
*/

// ensure this library description is only included once
#ifndef DS1307_h
#define DS1307_h

// include types & constants of Wiring core API
//#include <WConstants.h>
#include <Arduino.h>
// include types & constants of Wire ic2 lib
#include <Wire.h>

#define DS1307_SEC 0
#define DS1307_MIN 1
#define DS1307_HR 2
#define DS1307_DOW 3
#define DS1307_DATE 4
#define DS1307_MTH 5
#define DS1307_YR 6

#define DS1307_BASE_YR 2010

#define DS1307_CTRL_ID B1101000  //DS1307

// Define register bit masks  
#define DS1307_CLOCKHALT B10000000

#define DS1307_LO_BCD  B00001111
#define DS1307_HI_BCD  B11110000

#define DS1307_HI_SEC  B01110000
#define DS1307_HI_MIN  B01110000
#define DS1307_HI_HR   B00110000
#define DS1307_LO_DOW  B00000111
#define DS1307_HI_DATE B00110000
#define DS1307_HI_MTH  B00110000
#define DS1307_HI_YR   B11110000

// library interface description
class DS1307
{
 // user-accessible "public" interface
 public:
   DS1307();
   void init();
   void get(int *rtc, boolean);
   int get(int, boolean);
     void set(int, int);
   void start(void);
   void stop(void);

 // library-accessible "private" interface
 private:
   byte rtc_bcd[7]; // used prior to read/set ds1307 registers;
     void read(void);
     void save(void);
};

//extern DS1307 RTC;

#endif


the source:
Code: [Select]
/*
  DS1307.cpp - library for DS1307 RTC

  for Arduino 1.0 and above
  June 28th, 2013
*/
#include <Arduino.h>
#include <Wire.h>
#include "DS1307.h"

DS1307::DS1307()
{
 //Wire.begin();
}

//DS1307 RTC=DS1307();


void DS1307::init(){
Wire.begin();
}

// PRIVATE FUNCTIONS

// Aquire data from the RTC chip in BCD format
// refresh the buffer
void DS1307::read(void)
{
 // use the Wire lib to connect to tho rtc
 // reset the resgiter pointer to zero
 Wire.beginTransmission(DS1307_CTRL_ID);
 byte val = 0x00;
 Wire.write(val);
 Wire.endTransmission();

 // request the 7 bytes of data    (secs, min, hr, dow, date. mth, yr)
 Wire.requestFrom(DS1307_CTRL_ID, 7);
 for(int i=0; i<7; i++)
 {
   // store data in raw bcd format
   rtc_bcd[i]=Wire.read();
 }
}

// update the data on the IC from the bcd formatted data in the buffer
void DS1307::save(void)
{
 Wire.beginTransmission(DS1307_CTRL_ID);
 byte val = 0x00;
 Wire.write(val); // reset register pointer
 for(int i=0; i<7; i++)
 {
   Wire.write(rtc_bcd[i]);
 }
 Wire.endTransmission();
}


// PUBLIC FUNCTIONS
void DS1307::get(int *rtc, boolean refresh)   // Aquire data from buffer and convert to int, refresh buffer if required
{
 if(refresh) read();
 for(int i=0;i<7;i++)  // cycle through each component, create array of data
 {
     rtc[i]=get(i, 0);
 }
}

int DS1307::get(int c, boolean refresh)  // aquire individual RTC item from buffer, return as int, refresh buffer if required
{
 if(refresh) read();
 int v=-1;
 switch(c)
 {
 case DS1307_SEC:
   v=(10*((rtc_bcd[DS1307_SEC] & DS1307_HI_SEC)>>4))+(rtc_bcd[DS1307_SEC] & DS1307_LO_BCD);
     break;
 case DS1307_MIN:
   v=(10*((rtc_bcd[DS1307_MIN] & DS1307_HI_MIN)>>4))+(rtc_bcd[DS1307_MIN] & DS1307_LO_BCD);
     break;
 case DS1307_HR:
   v=(10*((rtc_bcd[DS1307_HR] & DS1307_HI_HR)>>4))+(rtc_bcd[DS1307_HR] & DS1307_LO_BCD);
     break;
 case DS1307_DOW:
   v=rtc_bcd[DS1307_DOW] & DS1307_LO_DOW;
     break;
 case DS1307_DATE:
   v=(10*((rtc_bcd[DS1307_DATE] & DS1307_HI_DATE)>>4))+(rtc_bcd[DS1307_DATE] & DS1307_LO_BCD);
     break;
 case DS1307_MTH:
   v=(10*((rtc_bcd[DS1307_MTH] & DS1307_HI_MTH)>>4))+(rtc_bcd[DS1307_MTH] & DS1307_LO_BCD);
     break;
 case DS1307_YR:
   v=(10*((rtc_bcd[DS1307_YR] & DS1307_HI_YR)>>4))+(rtc_bcd[DS1307_YR] & DS1307_LO_BCD)+DS1307_BASE_YR;
     break;
 } // end switch
 return v;
}

void DS1307::set(int c, int v)  // Update buffer, then update the chip
{
 switch(c)
 {
 case DS1307_SEC:
   if(v<60 && v>-1)
   {
     //preserve existing clock state (running/stopped)
     int state=rtc_bcd[DS1307_SEC] & DS1307_CLOCKHALT;
     rtc_bcd[DS1307_SEC]=state | ((v / 10)<<4) + (v % 10);
   }
   break;
 case DS1307_MIN:
   if(v<60 && v>-1)
   {
     rtc_bcd[DS1307_MIN]=((v / 10)<<4) + (v % 10);
   }
   break;
 case DS1307_HR:
 // TODO : AM/PM  12HR/24HR
   if(v<24 && v>-1)
   {
     rtc_bcd[DS1307_HR]=((v / 10)<<4) + (v % 10);
   }
   break;
 case DS1307_DOW:
   if(v<8 && v>-1)
   {
     rtc_bcd[DS1307_DOW]=v;
   }
   break;
 case DS1307_DATE:
   if(v<31 && v>-1)
   {
     rtc_bcd[DS1307_DATE]=((v / 10)<<4) + (v % 10);
   }
   break;
 case DS1307_MTH:
   if(v<13 && v>-1)
   {
     rtc_bcd[DS1307_MTH]=((v / 10)<<4) + (v % 10);
   }
   break;
 case DS1307_YR:
   if(v<13 && v>-1)
   {
     rtc_bcd[DS1307_YR]=((v / 10)<<4) + (v % 10);
   }
   break;
 } // end switch
 save();
}

void DS1307::stop(void)
{
     // set the ClockHalt bit high to stop the rtc
     // this bit is part of the seconds byte
   rtc_bcd[DS1307_SEC]=rtc_bcd[DS1307_SEC] | DS1307_CLOCKHALT;
   save();
}

void DS1307::start(void)
{
     // unset the ClockHalt bit to start the rtc
     // TODO : preserve existing seconds
   rtc_bcd[DS1307_SEC]=0;
     save();
}



And an example .ino
Code: [Select]
#include <Wire.h>
#include "DS1307.h"

int rtc[7];  
DS1307 RT = DS1307();

void setup()
{
 Serial.begin(9600);
 RT.init();
 //*
 RT.stop();
 RT.set(DS1307_SEC,1);
 RT.set(DS1307_MIN,0);
 RT.set(DS1307_HR,18);
 RT.set(DS1307_DOW,2);
 RT.set(DS1307_DATE,11);
 RT.set(DS1307_MTH,6);
 RT.set(DS1307_YR,3);
 RT.start();
 //*/
}

void loop()
{
 RT.get(rtc,true);

 for(int i=0; i<7; i++)
 {
   Serial.print(rtc[i]);
   Serial.print(" ");
 }
 Serial.println();

 delay(1000);

}


Hope, it helps you as much as it helped me!

Cheers!

av8or1

Thanks!  I plan to give this a try when the new boards come in.  Will report back with the results.

Go Up