RTC1307 - Real Time Clock

From Combustory
(Difference between revisions)
Jump to: navigation, search
Line 9: Line 9:
 
=== I2C ===
 
=== I2C ===
  
There are basically only two operations that you control this chip, a read or write to 64 data registers and the process is similar for both read or write.
+
There are basically only two operations that control this chip, a read or write to 64 data registers and the process is similar for both read or write.
  
 
* Read date/time
 
* Read date/time
** Send 1st byte - Address (my circuit - 01011010 or 0x2D)(binary - 0101 A3 A2 A1 A0) A values are actual pins set to high or low for an address.
+
** Open the I2C communication in write mode.
** Send 2nd byte - Instruction (binary - 1001 (1/0)(1/0) 00) - The two bits are used to choose the potentiometer
+
** Set the register pointer to (0x00) - To read the date/time you reset the pointer to the first register.
** Read WCR requested Byte
+
** End write mode.
 +
** Open I2C in read mode and read seven bytes of data.
 +
<pre>
 +
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  // Open I2C line in write mode
 +
  Wire.send(0x00);                            // Set the register pointer to (0x00)
 +
  Wire.endTransmission();                      // End Write Transmission
 +
 
 +
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);  // Open the I2C line in send mode
 +
 
 +
  second    = bcdToDec(Wire.receive() & 0x7f); // Read seven bytes of data
 +
  minute    = bcdToDec(Wire.receive());
 +
  hour      = bcdToDec(Wire.receive() & 0x3f); 
 +
  dayOfWeek  = bcdToDec(Wire.receive());
 +
  dayOfMonth = bcdToDec(Wire.receive());
 +
  month      = bcdToDec(Wire.receive());
 +
  year      = bcdToDec(Wire.receive());
 +
 
 +
</pre>
 +
 
 
* Write date/time or memory value.
 
* Write date/time or memory value.
** Send 1st byte - Address (my circuit - 01011010 or 0x2D)(binary - 0101 A3 A2 A1 A0) A values are actual pins set to high or low for an address.
+
** Open the I2C communication in write mode.
** Send 2nd byte - Instruction (binary - 1010 (1/0)(1/0) 00) - The two bits are used to choose the potentiometer
+
** Set the register pointer to (0x00) - To write the date/time you reset the pointer to the first register.
** Send WCR Byte - Potentiometer value (binary - 00 D5 D4 D3 D2 D1 D0) - D values are the 0-63 potentiometer positions
+
** Write seven bytes of data.
 +
** End write mode.
 +
 
 +
<pre>
 +
 
 +
Wire.beginTransmission(DS1307_I2C_ADDRESS);  // Open I2C line in write mode
 +
  Wire.send(0x00);                          // Set the register pointer to (0x00)
 +
  Wire.send(decToBcd(second));              // Write seven bytes
 +
  Wire.send(decToBcd(minute));
 +
  Wire.send(decToBcd(hour));     
 +
  Wire.send(decToBcd(dayOfWeek));
 +
  Wire.send(decToBcd(dayOfMonth));
 +
  Wire.send(decToBcd(month));
 +
  Wire.send(decToBcd(year));
 +
  Wire.endTransmission();                    // End write mode
  
 +
</pre>
  
 
==== RTC_DS1307_v.01 code ====
 
==== RTC_DS1307_v.01 code ====
Line 167: Line 200:
 
             Serial.println(test, DEC);
 
             Serial.println(test, DEC);
 
           }
 
           }
          Wire.endTransmission();
 
 
           Serial.println(" RTC1307 Dump end");
 
           Serial.println(" RTC1307 Dump end");
 
         }  
 
         }  

Revision as of 20:41, 6 February 2009

Welcome to Combustory


Any questions or comments:

  • Send them to - combustor@combustory.com

Contents

Summary

This code shows how to communicate with the RTC DS1307 Real Time Clock, which is used to set and retrieve the date/time of the chip. As a bonus there is some additional bytes of data that can be used as general purpose memory. The main purpose for my use of this code is to be able to log events that occur in my applications. I recommend for you to get the RTC1307 data sheet to help with understanding what was done here. The bottom line is that I have created this program to accept commands via serial communication with a PC to instruct the Arduino to send or receive data via I2C to the storage registers of the RTC DS1307 chip.

Note of gratitude to Maurice Ribble - http://www.glacialwanderer.com/hobbyrobotics/?p=12 for the majority of the RTC DS1307 code. To not repeat his excellent instructions on this chip I highly recommend you visit his site on this topic. All I did here was expand his code a to get a little more functionality out of the DS1307 chip.

Method

I2C

There are basically only two operations that control this chip, a read or write to 64 data registers and the process is similar for both read or write.

  • Read date/time
    • Open the I2C communication in write mode.
    • Set the register pointer to (0x00) - To read the date/time you reset the pointer to the first register.
    • End write mode.
    • Open I2C in read mode and read seven bytes of data.
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  // Open I2C line in write mode
  Wire.send(0x00);                             // Set the register pointer to (0x00)
  Wire.endTransmission();                      // End Write Transmission 

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);  // Open the I2C line in send mode

  second     = bcdToDec(Wire.receive() & 0x7f); // Read seven bytes of data
  minute     = bcdToDec(Wire.receive());
  hour       = bcdToDec(Wire.receive() & 0x3f);  
  dayOfWeek  = bcdToDec(Wire.receive());
  dayOfMonth = bcdToDec(Wire.receive());
  month      = bcdToDec(Wire.receive());
  year       = bcdToDec(Wire.receive());

  • Write date/time or memory value.
    • Open the I2C communication in write mode.
    • Set the register pointer to (0x00) - To write the date/time you reset the pointer to the first register.
    • Write seven bytes of data.
    • End write mode.

 Wire.beginTransmission(DS1307_I2C_ADDRESS);  // Open I2C line in write mode
   Wire.send(0x00);                           // Set the register pointer to (0x00)
   Wire.send(decToBcd(second));               // Write seven bytes
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();                    // End write mode

RTC_DS1307_v.01 code

/*
 * RTC Control v.01
 * by <http://www.combustory.com> John Vaughters
 * Credit to:
 * Maurice Ribble - http://www.glacialwanderer.com/hobbyrobotics for RTC DS1307 code
 *
 * With this code you can set the date/time, retreive the date/time and use the extra memory of an RTC DS1307 chip.  
 * The program also sets all the extra memory space to 0xff.
 * Serial Communication method with the Arduino that utilizes a leading CHAR for each command described below. 
 * Commands:
 * T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) - T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) - T Sets the date of the RTC DS1307 Chip. 
 * Example to set the time for 02-Feb-09 @ 19:57:11 for the 3 day of the week, use this command - T1157193040209
 * Q(1-2) - (Q1) Memory initialization  (Q2) RTC - Memory Dump
 */

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address


// Global Variables

int command = 0;       // This is the command char, in ascii form, sent from the serial port     
int i;
long previousMillis = 0;        // will store last time Temp was updated
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte test; 
  
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.
 
void setDateDs1307()                
{

   second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
   minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   dayOfWeek = (byte) (Serial.read() - 48);
   dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0x00);
   Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0x00);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  second     = bcdToDec(Wire.receive() & 0x7f);
  minute     = bcdToDec(Wire.receive());
  hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  dayOfWeek  = bcdToDec(Wire.receive());
  dayOfMonth = bcdToDec(Wire.receive());
  month      = bcdToDec(Wire.receive());
  year       = bcdToDec(Wire.receive());
  
  Serial.print(hour, DEC);
  Serial.print(":");
  Serial.print(minute, DEC);
  Serial.print(":");
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(year, DEC);

}


void setup() {
  Wire.begin();
  Serial.begin(57600);
 
}

void loop() {
     if (Serial.available()) {      // Look for char in serial que and process if found
      command = Serial.read();
      if (command == 84) {      //If command = "T" Set Date
       setDateDs1307();
       getDateDs1307();
       Serial.println(" ");
      }
      else if (command == 81) {      //If command = "Q" RTC1307 Memory Functions
        delay(100);     
        if (Serial.available()) {
         command = Serial.read(); 
         if (command == 49) {      //If command = "1" RTC1307 Initialize Memory - All Data will be set to 255 (0xff).  Therefore 255 or 0 will be an invalid value.  
          Wire.beginTransmission(DS1307_I2C_ADDRESS); // 255 will be the init value and 0 will be cosidered an error that occurs when the RTC is in Battery mode.
          Wire.send(0x08); // Set the register pointer to be just past the date/time registers.
         for (i = 1; i <= 27; i++) {
             Wire.send(0xff);
            delay(100);
         }   
         Wire.endTransmission();
         getDateDs1307();
         Serial.println(": RTC1307 Initialized Memory");
         }
         else if (command == 50) {      //If command = "2" RTC1307 Memory Dump
          getDateDs1307();
          Serial.println(": RTC 1307 Dump Begin");
          Wire.beginTransmission(DS1307_I2C_ADDRESS);
          Wire.send(0x00);
          Wire.endTransmission();
          Wire.requestFrom(DS1307_I2C_ADDRESS, 64);
          for (i = 1; i <= 64; i++) {
             test = Wire.receive();
             Serial.print(i);
             Serial.print(":");
             Serial.println(test, DEC);
          }
          Serial.println(" RTC1307 Dump end");
         } 
        }  
       }
      Serial.print("Command: ");
      Serial.println(command);     // Echo command CHAR in ascii that was sent
      }
      
      command = 0;                 // reset command 
      delay(100);
    }
//*****************************************************The End***********************

RTC_DS1307_v.01 User Guide

Commands

Personal tools
Sponsers
Your Ad Here
Your Ad Here