The DS1307 is a classic staple of DIY clocks.http://www.maxim-ic.com/datasheet/index.mvp/id/2688
Read the datasheet, it contains the commands for the chip and other details. You'll need to know this stuff when you look at my source code so you know what's going on.
What does it do? It tracks time, so your microcontroller doesn't have to. It'll even track time using a coin cell battery while its main power is off, so you don't get that classic 12:00 blinking that happens to old alarm clocks when the power goes out. Oh and it tracks the date too.
Note that there are much better alternatives to the DS1307 today with better features, however, I found this chip in my collection of odd parts, so I'm going to use it.
This chip requires the following things around it: a watch crystal, a battery backup (3V coin cell from the dollar store will last 9 years), a power supply, and a decoupling capacitor.
The microcontroller will communicate to the DS1307 via the I2C (inter-integrated circuit) bus. The I2C bus is also known as TWI (two wire interface, it only uses two wires). It is designed for communication between multiple integrated circuits. Please refer to Appendix D to learn more about I2C and TWI.
What we need to do with the DS1307 is simple, we just need to set the time, and read the time.
The DS1307 keeps its data in several registers. Refer to the datasheet, table 2, page 8. It shows the data being stored in binary coded decimal format, which our source code will encode and decode. We will write to these registers when we set the time, and read from the same registers to retrieve the time.
A good description of the I2C bus is given on page 10 of the datasheet. The AC electrical characteristics section of the datasheet says our I2C bus must run at 100 KHz or lower (this is configurable inside our source code), keep this in mind. The address of the DS1307 is 1101000, remember that too.
For example, we want to set the seconds, so the register is 0x00. We first send over I2C
this addresses the DS1307, and says we want to write
then we send
to indicate the register 0x00
then we send the number we want to set, coded in binary coded decimal format
Then, if we want to read back the seconds, the register is again, 0x00, we first send
notice that this is the address, but we are still specifying that we want to write
why specify "write" when we want to read? Because we have not told the DS1307 where we want to read from (setting the register address inside the DS1307). So we send
then we end the data transfer
now we are addressing the DS1307 and indicating we want to read
we then drive the clock to read back the data, which the DS1307 will place on the data line for us. We can then decode the data from binary coded decimal format.
It's important to understand that because we are using our AVR's built-in TWI module for I2C communication, it knows to automatically release the SDA line when we indicate "read" in the first byte we send. The hardware and software (we are using "twi.c" from "Wire" library of the Arduino). EVERYTHING is automated, even the acknowledgements.
For our purposes, we will be reading and writing all of the time settings in one go, for efficiency. The details of how this works is in the datasheet. You can also see my source code later. The idea is the same for single registers, but we repeatedly read/write without ending the transfer. You'll see how this works through the datasheet, my source code, and my logic analyzer waveforms.
Attached is a demonstration of a simple program that sets the time and then displays the time on your LCD. It will demonstrate using the TWI bus to perform single/multiple byte read/write operations (view the waveforms I've provided).
Add the DS1307 to your circuit according to my diagram first. A higher resolution picture is within the .ZIP package. The important point is that the DS1307 needs 5V, and we've modified the Teensy++ to run at 3.3V, the diagram shows you where to get 5V from the Teensy++.
You'll need the LCD still connected if you want to see the clock working. The serial terminal will still show you debug messages.
I've included the logic analyzer waveforms so you can clearly see what I2C looks like, the datasheet of the DS1307 also shows similar waveforms, study the waveforms together while also examining the data being exchanged (such as what command is sent, what was the reply), try matching the events to the points in the source code.