
Using the ATMEGA168/Arduino with a DS1307 Real Time Clock
by Lewis Loflin
[ My Homepage ] [ Electronics Mainpage ]
Explanation of program:
On power up or reset the "setup" is executed once, setting up the hardware and writing the time/date to the DS1307. Then the "loop" section will run over and over. The DS1307 is read and sent via the serial port to a computer running for example Hyper Terminal. This demonstrates the use of the Wire.h library, serial ports, and the DS1307.
For the basic structure of an Arduino program see page 7 of Arduino Programming Notebook by Brian Evans

Basic I2C setup.
The DS1307 is a low-power clock/calendar with 56 bytes of battery-backed SRAM. The clock/calendar
provides seconds, minutes, hours, day, date, month, and year information. The date at the end of the
month is automatically adjusted for months with fewer than 31 days, including corrections for leap year.
The DS1307 operates as a slave device on the I2C bus. Access is obtained by implementing a START
condition and providing a device identification code (0x68) followed by a register address. Subsequent registers
can be accessed sequentially. The DS1307 comes in an 8-pin dip package. The DS1307 counts in BCD format.
Bit 7 of Register 0 is the clock halt (CH) bit. When this bit is set to 1, the
oscillator is disabled. When cleared to 0, the oscillator is enabled.
In other words unless this is cleared the clock will not run!

DS1307 pin out
Only the first 8 bytes (0x00 - 0x07) are used by the clock itself while the other 56 bytes can be used a scratchpad RAM.
PIN DESCRIPTION
Pins 1, 2 Connections for Standard 32.768kHz Quartz Crystal. No capicitors r other parts needed.
Pin 3 VBAT Backup Supply Input for Any Standard 3V Lithium Cell
Diodes in series between the battery and the VBAT pin may prevent proper operation!
Pin 4 GND Ground
Pin 5 SDA Serial Data Input/Output. SDA is the data input/output for the I2C serial interface. The
SDA pin is open drain and requires an external pull-up resistor. Arduino pin 4.
Pin 6 SCL Serial Clock Input. SCL is the clock input for the I2C interface and is used to synchronize
data movement on the serial interface. Arduino pin 5.
7 SWQ/OUT
Square Wave/Output Driver. When enabled, the SQWE bit set to 1, the SQW/OUT pin
outputs one of four square-wave frequencies (1Hz, 4kHz, 8kHz, 32kHz). The SQW/OUT
pin is open drain and requires an external pull-up resistor. SQW/OUT operates with either
VCC or VBAT applied. An LED and 220 ohm resistor in series tied to VCC will produce a 1 HZ blink.
This is a good way to tell if the clock chip is working.
8 VCC (5 volts)

Schematic DS1307
For more information on the DS1307 see Dallas DS1307 Real Time Clock I2C plus RAM
#include <Wire.h> // specify use of Wire.h library.
byte blinkPin = 13;
byte SW0 = 4;
byte SW1 = 5;
byte SW2 = 6;
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600);
pinMode(blinkPin, OUTPUT);
digitalWrite(blinkPin, 0);
pinMode(SW0, INPUT); // for this use a slide switch
pinMode(SW1, INPUT); // N.O. push button switch
pinMode(SW2, INPUT); // N.O. push button switch
digitalWrite(SW0, HIGH); // pull-ups on
digitalWrite(SW1, HIGH);
digitalWrite(SW2, HIGH);
}
void loop()
{
Wire.beginTransmission(0x68);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
byte secs = Wire.receive();
byte mins = Wire.receive();
byte hrs = Wire.receive();
byte day = Wire.receive();
byte date = Wire.receive();
byte month = Wire.receive();
byte year = Wire.receive();
// hours, minutes, seconds
Serial.print("The time is ");
if (hrs < 10) Serial.print("0");
Serial.print(hrs,HEX);
Serial.print(":");
if (mins < 10) Serial.print("0");
Serial.print(mins, HEX);
Serial.print(":");
if (secs < 10) Serial.print("0");
Serial.println(secs, HEX);
// use MM-DD-YYYY
Serial.print("The date is ");
if (month < 10) Serial.print("0");
Serial.print(month,HEX);
Serial.print("-");
if (date < 10) Serial.print("0");
Serial.print(date, HEX);
Serial.print("-");
Serial.print("20");
if (year < 10) Serial.print("0");
Serial.println(year, HEX);
Serial.println();
if (!(digitalRead(SW0))) set_time(); // hold the switch to set time
delay(1000); //wait a second before next output
toggle(blinkPin);
}
// toggle the state on a pin
void toggle(int pinNum)
{
int pinState = digitalRead(pinNum);
pinState = !pinState;
digitalWrite(pinNum, pinState);
}
void set_time() {
byte minutes = 0;
byte hours = 0;
while (!digitalRead(SW0)) // set time switch must be released to exit
{
while (!digitalRead(SW1)) // set minutes
{
minutes++;
if ((minutes & 0x0f) > 9) minutes = minutes + 6;
if (minutes > 0x59) minutes = 0;
Serial.print("Minutes = ");
if (minutes >= 9) Serial.print("0");
Serial.println(minutes, HEX);
delay(750);
}
while (!digitalRead(SW2)) // set hours
{
hours++;
if ((hours & 0x0f) > 9) hours = hours + 6;
if (hours > 0x23) hours = 0;
Serial.print("Hours = ");
if (hours <= 9) Serial.print("0");
Serial.println(hours, HEX);
delay(750);
}
Wire.beginTransmission(0x68); // activate DS1307
Wire.send(0); // where to begin
Wire.send(0x00); //seconds
Wire.send(minutes); //minutes
Wire.send(0x80 | hours); //hours (24hr time)
Wire.send(0x06); // Day 01-07
Wire.send(0x01); // Date 0-31
Wire.send(0x05); // month 0-12
Wire.send(0x09); // Year 00-99
Wire.send(0x10); // Control 0x10 produces a 1 HZ square wave on pin 7.
Wire.endTransmission();
}
}
|

Setting Hours and Minutes
Assuming the switches are wired as shown above, close SW0 and while closed SW1 and SW2 will increment the hours and minutes as shown on the terminal. Release/open SW0 and new time will be written to the DS1307.
Basic Wire.h Library
Wire Library:
This library allows you to communicate with I2C devices. On the Arduino, SDA (data line) is on analog input pin 4 (A4), and SCL (clock line) is on analog input pin 5 (A5). Tie both through 10k resistors to VCC. (+ 5 volts.) Functions are listed below.
Wire.begin() // for master
Wire.begin(address) // for slave
Description: Initiate the Wire library and join the I2C bus as a master or slave. The 7-bit slave address (optional) if not specified, the device defaults as a master. Returns: None
Wire.requestFrom(address, quantity)
Request bytes from another device. The bytes may then be retrieved with the available() and receive() functions.
Address: the 7-bit address of the device to request bytes from
Quantity: the number of bytes to request
Wire.beginTransmission(address) // address is a 7-bit address of the device to transmit to.
Description: Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the send() function and transmit them by calling endTransmission(). This acts as a position pointer for the device.
Wire.send(value)
Wire.send(string)
Wire.send(data, quantity)
Description: Sends data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to beginTransmission() and endTransmission()).
Parameters:
value: a byte to send (byte);
string: a string to send (char *);
data: an array of data to send (byte *);
quantity: the number of bytes of data to transmit (byte).
Wire.endTransmission()
Description: Ends a transmission to a slave device that was begun by beginTransmission() and actually transmits the bytes that were queued by send().
Wire.available()V
Description: Returns the number of bytes available for retrieval with receive(). This should be called on a master device after a call to requestFrom() or on a slave inside the onReceive() handler.
byte Wire.receive()
Retrieve a byte that was transmitted from a slave device to a master after a call to requestFrom or was transmitted from a master to a slave.
Returns the next byte received.
Wire.onReceive(handler)
Description: Registers a function to be called when a slave device receives a transmission from a master.
Parameters: handler: the function to be called when the slave receives data; this should take a single int parameter (the number of bytes received from the master) and return nothing, e.g.: void myHandler(int numBytes)
Wire.onRequest(handler)
Description: Register a function to be called when a master requests data from this slave device.
Parameters: handler: the function to be called, takes no parameters and returns nothing, e.g.: void myHandler()
There are both 7- and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it's being written to or read from. The Wire library uses 7 bit addresses throughout. If you have a data sheet or sample code that uses 8 bit address, you'll want to drop the low bit (i.e. shift the value one bit to the right), yielding an address between 0 and 127.

Home built test console for ATMEGA168 Arduino
Pictures and schematics:
Digital inputs for ATMEGA168/Arduino
Digital outputs for ATMEGA168/Arduino
ATMEGA168/Arduino test jig part A
ATMEGA168/Arduino test jig part B
LED Circuits connected to ATMEGA168/Arduino
Using the ATMEGA168/Arduino with a DC motor
Using the ATMEGA168/Arduino with a relay
Basic relay