Pages: [1]   Go Down
Author Topic: DS1307 library for Arduino 1.0 and above  (Read 1611 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*
   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:
/*
   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:
#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!
Logged

Austin, TEXAS
Offline Offline
Full Member
***
Karma: 0
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Pages: [1]   Go Up
Jump to: