cover.450

The DS1307 is a simple, inexpensive I2C real-time clock, it’s somewhat similar to the PCF8563 that was previously demonstrated with the Bus Pirate.

This chip has some nice features. It has internal capacitors on both oscillator pins, the only required external part is a 32.768kHz time-keeping crystal. It also has a backup battery input so it can keep time during power failures. The battery backup also applies to 56byte of general purpose RAM.

Keep reading for a complete DS1307 demo using the Bus Pirate universal serial interface. If you’re not using a Bus Pirate, that’s OK, you can still follow along and get a better understanding of how to implement this chip in your own application.

Chip: DS1307, I2C real-time clock.
Bus: I2C, pull-up resistors required.
Power requirements: 5volts (4.25-5.525volts).
References: datasheet [PDF].
Complete Bus Pirate session log for this demonstration.

Setup

cct

The schematic above shows the DS1307 pinout and minimum circuit. The oscillator has internal capacitors, so an external 32.768kHz crystal is the only required external component. The chip requires a 5volt power supply.

Bus Pirate DS1307 (pin)
MOSI/SDA SDA (5)
CLOCK/SCL SCL (6)
+5volts, Vpullup +5volts (8)
GND GND (4)

Connect the Bus Pirate to the DS1307 as shown in the table. We powered the DS1307 from the Bus Pirate’s 5volt supply, and used the on-board pull-up resistors to hold the I2C bus high.

I2C>W<< power supplies on
POWER SUPPLIES ON
I2C>p<< configure pull-up resistors
1. Pull-ups off
2. Pull-ups on
(1) >2
Pull-up resistors ON
I2C>(1)<< address scan macro
Searching 7bit I2C address space.
Found devices at:
0xD0(0x68 W) 0xD1(0x68 R)
I2C>

In the Bus Pirate terminal select the mode menu (m) and choose I2C. Choose software I2C, any speed 400kHz or less is fine. Turn on the Bus Pirate power supplies (big W) and enable the pull-up resistors (p). We used the I2C scan macro (1) to find the DS1307 address, you could also refer to the datasheet.

If you’re not using a Bus Pirate, that’s OK, you can still follow along and get a better understanding of how to implement this chip in your own application.

Interfacing

table2-pg8

Table 2 from page 9 of the datasheet shows the location of values in the DS1307 memory. The first 8 bytes hold the time and configuration settings (0x00-0x07), the upper bytes are blank and can be used as extra RAM (0x08-0x3f).

Set the time by writing to the first eight memory locations of the DS1307.

I2C>[0xd0 0 0 0b00110000 0b00001001 0b00000010 0b00000111 0b00001001 0b00001001 0]
I2C START BIT
WRITE: 0xD0 ACK<< DS1307 write address
WRITE: 0x00 ACK<< location to write
WRITE: 0x00 ACK<< 0 seconds, reset CH bit to 0
WRITE: 0x30 ACK<< 30 minutes
WRITE: 0x09 ACK<< 9 hours, 24 hour clock mode
WRITE: 0x02 ACK<< Monday (day 2)
WRITE: 0x07 ACK<< 7th (date)
WRITE: 0x09 ACK<< September (month)
WRITE: 0x09 ACK<< ’09 (year)
WRITE: 0x00 ACK<< Set control register to 0
I2C STOP BIT
I2C>

0xd0 is the write address, followed by the memory location to write (0). Next come the time settings: 9:30:00 Monday 09/07/09.

Note that the numbers are represented as digits on a clock, rather than as decimal numbers. To represent 35minutes write 3 to bits 4-6, and write 5 to bits 0-3.

The CH bit of address 0x00 indicates a power failure, and is reset by our update. Bit 6 of address 0x02 toggles between 12 and 24 hour time, we cleared it for 24 hour time. The control register configures the square wave output pin (pin1), see page 9 of the datasheet for an overview of its functions.

Now, read back the time.

I2C>[0xd0 0 [0xd1 rrrrrrrr]
I2C START BIT
WRITE: 0xD0 ACK<< DS1307 write address
WRITE: 0x00 ACK<< set write pointer
I2C START BIT
WRITE: 0xD1 ACK<< DS1307 read address
READ: 0x30 ACK<< 30 seconds
READ: 0x30 ACK<< 30 minutes
READ: 0x09 ACK<< 9 hours, 24 hour clock mode
READ: 0x02 ACK<< Monday (day 2)
READ: 0x07 ACK<< 7th (date)
READ: 0x09 ACK<< September (month)
READ: 0x09 ACK<< ’09 (year)
READ: 0x00 NACK<< Control register
I2C STOP BIT
I2C>

Read the time by setting the address pointer to 0 with a partial write operation ([0xd0 0), then reading 8 bytes from the read address (0xd1). We could have used a repeated read command (r:8), but we wanted to address each individual byte in the demonstration. We did this immediately after setting the time, so only 30 seconds have elapsed: 9:30:30 Monday 09/07/09.

The DS1307 also has a bit of additional RAM that can be used for general purpose storage.

I2C>[0xd0 8 3 2 1]
I2C START BIT
WRITE: 0xD0 ACK<< DS1307 write address
WRITE: 0x08 ACK<< set write pointer to 0x08
WRITE: 0x03 ACK<< write these values
WRITE: 0x02 ACK
WRITE: 0x01 ACK
I2C STOP BIT
I2C>

The RAM starts at memory address 0x08, and continues to 0x3f. Write to it just like the previous registers: send the I2C write address (0xd1), the location to start writing (8), and the values to store (3 2 1).

I2C>[0xd0 8 [ 0xd1 r:3]
I2C START BIT
WRITE: 0xD0 ACK<< DS1307 write address
WRITE: 0x08 ACK<< set write pointer to 0x08
I2C START BIT
WRITE: 0xD1 ACK<< DS1307 read address
READ 0x03 BYTES:<< read back three values
0x03 ACK 0x02 ACK 0x01 NACK
I2C STOP BIT
I2C>

Reading from the RAM is also straight forward. Set the starting memory address with a partial write command ([0xd0 8), then read data from the read address ([0xd1 r:3]). We got the same values we entered (3 2 1).

If you liked this chip demonstration, there’s a bunch more in the Bus Pirate manual. We love special requests, please post them in the comments.

Advertisements