Swordfish Tutorial - DS1307 Date Time Chip (DTC)

The DS1307 is a great piece of kit, it provides real time date and clock values, and interfaces with the PIC micro via I2C. The values it holds for date/time are, Secs, Mins, Hours, Day, Date, Month and Year. I hear you asking, why use this when you could make a small program do the same with a PIC;

  • The DS1307 has leap year compensation until 2100
  • A 32.768Khz crystal is far more accurate than a 4Mhz+ crystal
  • In back-up mode, the DS1307 consumes less than 500nA

Example of interfacing with a DS1307. Note that on the DS1037 Pin 8 is connected to 5V, Pin 4 is connected to GND and Pin 3connected to ground if no backup battery is used!

(LCD, 5v Regulator and Contrast Control not shown for ease of illustration)

18f13071

If you wish to use a battery backup for the DS1307, then connect the positive of the battery to Pin 3, and the earth to Pin 4. When ever Vcc (Pin 8) is lower than Pin 3 (Batt), the device will enter backup mode and consume less than 500nA.

Notice that the DS1307 also requires an external oscillator, both the chip and crystal (part# CRY32)  can be found at Futurlec. Be sure to connect the 4.7K pull-up resistors on SCL and SDA as shown aswell.

Example Program
Device = 18F452
Clock = 20
 
// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
 
// import LCD library...
Include "LCD.bas"
Include "utils.bas"
Include "convert.bas"
Include "I2C.bas"
 
Structure TTime
 Second As Byte // Second (0..59)
 Minute As Byte // Minute (0..59)
 Hour As Byte // Hour (0..11 or 0..23)
End Structure
 
Structure TDate
 Day As Byte // Date (0..31)
 Month As Byte // Month (1..12)
 Year As Byte // Year (0..99)
 DayOfWeek As Byte // day of the week (1..7)
End Structure
 
Dim Time As TTime,
 Date As TDate,
 Seconds_Poll As Byte
 
Sub SetTime(Hour, Minute, Second, DayOfWeek, Day, Month, Year As Byte)
 
 I2C.Start
 I2C.WriteByte(%11010000) // Send the RTC address, and put it in write mode
 I2C.WriteByte($00) // Move the pointer to first register
 I2C.WriteByte(DecToBCD(Second)) // Write each byte
 I2C.WriteByte(DecToBCD(Minute)) //
 I2C.WriteByte(DecToBCD(Hour)) //
 I2C.WriteByte(DecToBCD(DayOfWeek)) //
 I2C.WriteByte(DecToBCD(Day)) //
 I2C.WriteByte(DecToBCD(Month)) //
 I2C.WriteByte(DecToBCD(Year)) //
 I2C.WriteByte(0) //
 I2C.Stop 
 
End Sub
 
Sub GetTime()
 
 I2C.Start
 I2C.WriteByte(%11010000)
 I2C.WriteByte($00)
 I2C.Restart 
 I2C.WriteByte(%11010001)
 Time.Second = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE))
 Time.Minute = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE))
 Time.Hour = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE))
 Date.DayOfWeek = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE))
 Date.Day = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE))
 Date.Month = BCDToDec(I2C.ReadByte(I2C_ACKNOWLEDGE)) 
 Date.Year = BCDToDec(I2C.ReadByte(I2C_NOT_ACKNOWLEDGE))
 I2C.Stop
 
End Sub
 
 
// Start Of Program...
SetAllDigital // Make all pins digital I/O's
I2C.Initialize() // Set up the I2C
 
DelayMS(150)
Cls
 
SetTime(03,42,00,07,06,05,07)
 
Main:
 
 GetTime
 
 If Time.Second = Seconds_Poll Then
 GoTo Main // If there is update in Secs, display time and Date
 EndIf
 
 // Display the new details on the LCD
 WriteAt(1,1,"Time: ", DecToStr(Time.Hour,2), ":", DecToStr(Time.Minute,2), ":", DecToStr(Time.Second,2))
 WriteAt(2,1,"Date: ", DecToStr(Date.Day,2), "-", DecToStr(Date.Month,2), "-", DecToStr(Date.Year,2))
 
 Seconds_Poll = Time.Second // Update the seconds polling register
 
 GoTo Main

Forum Activity

Member Access