The following are some routines to write and read from the DS1307 RTC.
First must be changed in the library i2c.h
# define I2C_BIT_DELAY 20 us
# define I2C_CLOCK_DELAY 10 us
# define I2C_END_DELAY 10 us
This is because the DS1307 can not operate at timings below 4.7 us
The code:
' Write Address According to manual 1101000+0= Decimal 208
' Read Address According to manual 1101000+1= Decimal 209
'Clear Bit 7 of 00h register. Oscillator is enabled, clock start
'On first application of power to the device the time and date registers
'are typically reset to 01/01/00 01 00:00:00 (MM/DD/YY DOW HH:MM:SS).
'The CH bit in the seconds register will be set to a 1
Sub Enab_Osc
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , False
I2CStop
Sec=Sec&127
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CSend Sec , True
I2CStop
end sub
'Set Bit 7 of 00h register. Oscillator is disabled, clock stop
Sub Dis_Osc
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , False
I2CStop
Sec=Sec|128
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CSend Sec , True
I2CStop
End sub
' Resets the clock to 00:00:00 01 01/01/00
Sub ResetClock
I2CStart
I2CSend 208, True
I2CSend 0, True
I2CSend 0, True
I2CSend 0, True
I2CSend 0, True
I2CSend 1, True
I2CSend 1, True
I2CSend 1, True
I2CSend 0, True
I2CStop
end sub
'Self explained
Sub SetClock (In Hour , In Min , In Sec , In DayOfWeak , In CDate , in CMonth , in CYear)
DS1307WriteReg(0,DecToBcd(Sec))
DS1307WriteReg(1,DecToBcd(Min))
DS1307WriteReg(2,DecToBcd(Hour))
DS1307WriteReg(3,DecToBcd(DayOfWeak))
DS1307WriteReg(4,DecToBcd(CDate))
DS1307WriteReg(5,DecToBcd(CMonth))
DS1307WriteReg(6,DecToBcd(CYear))
End sub
'Self explained
Sub SetTime (in Hour , in Min , in Sec)
DS1307WriteReg(0,DecToBcd(Sec))
DS1307WriteReg(1,DecToBcd(Min))
DS1307WriteReg(2,DecToBcd(Hour))
End Sub
'Self explained
Sub SetDate (In CDate , in CMonth , in CYear)
DS1307WriteReg(4,DecToBcd(CDate))
DS1307WriteReg(5,DecToBcd(CMonth))
DS1307WriteReg(6,DecToBcd(CYear))
End Sub
'Self explained
Sub ReadClock (out Hour , out Min , out Sec , out DayOfWeak , out CDate , out CMonth , out CYear)
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStop
I2CStart
I2CSend 209 , True
I2CReceive Sec , True
Sec=BcdToDec(Sec & 127)
I2CReceive Min , True
Min=BcdToDec(Min & 127)
I2CReceive Hour , True
if Hour.6 then
Hour=BcdToDec(Hour &31)
Else
Hour=BcdToDec(Hour & 63)
End if
I2CReceive DayOfWeak , True
DayOfWeak=BcdToDec(DayOfWeak & 7)
I2CReceive CDate , True
CDate=BcdToDec(CDate & 63)
I2CReceive CMonth , True
CMonth=BcdToDec(CMonth & 31)
I2CReceive CYear , False
CYear=BcdToDec(CYear)
I2CStop
End Sub
'Self explained
Sub ReadTime (Out Hour , Out Min , Out Sec)
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , True
Sec=BcdToDec(Sec & 127)
I2CReceive Min , True
Min=BcdToDec(Min & 127)
I2CReceive Hour , False
I2CStop
if Hour.6 then
Hour=BcdToDec(Hour & 31)
Else
Hour=BcdToDec(Hour & 63)
End if
End sub
'Self explained
Sub ReadDate ( out CDate , out CMonth , out CYear)
I2CStart
I2CSend 208 , True
I2CSend 4 , True
I2CStart
I2CSend 209 , True
I2CReceive CDate , True
CDate=BcdToDec(CDate & 63)
I2CReceive CMonth , True
CMonth=BcdToDec(CMonth & 31)
I2CReceive CYear , False
CYear=BcdToDec(CYear)
I2CStop
end sub
'Set Bit 6 of 02h register. The DS1307 run in 12-hour mode
'The hours value must be re-entered whenever the 12/24-hour mode bit is changed.
Sub Set12HourMode
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CStart
I2CSend 209 , True
I2CReceive Hour , False
I2CStop
Hour.6=1
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CSend Hour , True
I2CStop
End sub
'Clear Bit 6 of 02h register. The DS1307 run in 24-hour mode
'The hours value must be re-entered whenever the 12/24-hour mode bit is changed.
Sub Set24HourMode
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CStart
I2CSend 209, True
I2CReceive Hour , False
I2CStop
Hour.6=0
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CSend Hour , True
I2CStop
End sub
' Enables The SQW/OUT pin of chip
' If RateSelect=1 then the outpout Frequency is 1Hz
' If RateSelect=4 then the outpout Frequency is 4.096KHz
' If RateSelect=8 then the outpout Frequency is 8.192KHz
' If RateSelect=32 then the outpout Frequency is 32.768KHz
Sub SQWEnable (RateSelect)
Select case RateSelect
Case 1 : DS1307WriteReg(7,16)
Case 4 : DS1307WriteReg(7,17)
Case 8 : DS1307WriteReg(7,18)
Case 32: DS1307WriteReg(7,19)
End Select
End sub
'Disable the SQW/OUT pin of chip (pin=off)
Sub SQDisable
DS1307WriteReg(7,0)
End Sub
'The contents of the time and calendar registers are in the BCD format.
Function DecToBcd(va) as Byte
DecToBcd=(va/10)*16+va%10
End Function
Function BcdToDec(va) as byte
BcdToDec=(va/16)*10+va%16
End Function
Sub DS1307WriteReg (DS1307Reg, DS1307Value)
I2CStart
I2CSend 208 , True
I2CSend DS1307Reg , True
I2CSend DS1307Value , True
I2CStop
End Sub
;Variables
Dim Sec As byte
Dim Min As byte
Dim Hour As byte
Dim DayOfWeak as byte
Dim CDate as byte
Dim CMonth as byte
Dim CYear as Byte
Dim va as byte
va=0
cls
InitI2C
Main:
Sec=0
Min=0
Hour=0
CDate=0
CMonth=0
CYear=0
Call ReadTime( Hour , Min , Sec)
locate 0,0
print Hour
print ":"
print Min
Print ":"
Print Sec
Call ReadDate(CDate , CMonth , CYear)
locate 1,0
print CDate
print "/"
print CMonth
print "/"
print CYear
wait 1 s
locate 0,0
print " "
locate 1,0
print " "
InitI2C
goto Main
Sorry for my poor English
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Great piece of work. Well done. I want to use the code. Thank you.
A few questions.
The timing changes to 12c.h makes sense.
Your example code which commences as the line 'The code of the program that made tests are' calls the function ReadDate. But where does your example code call the routines you defined?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
According to datasheet (page 3) in AC ELECTRICAL CHARACTERISTICS the minimum time of SCL Clock is 4.7 us for LOW end 4 us for HiGH Period. In i2c.h this periods is 1 us. The Controler is 10 times faster than DS1307 end communication its not established.
All these routines, i have put them into a library name DS1307.h and i use any routine i want from it.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The following are some routines to write and read from the DS1307 RTC.
First must be changed in the library i2c.h
# define I2C_BIT_DELAY 20 us
# define I2C_CLOCK_DELAY 10 us
# define I2C_END_DELAY 10 us
This is because the DS1307 can not operate at timings below 4.7 us
The code:
' Write Address According to manual 1101000+0= Decimal 208
' Read Address According to manual 1101000+1= Decimal 209
'Clear Bit 7 of 00h register. Oscillator is enabled, clock start
'On first application of power to the device the time and date registers
'are typically reset to 01/01/00 01 00:00:00 (MM/DD/YY DOW HH:MM:SS).
'The CH bit in the seconds register will be set to a 1
Sub Enab_Osc
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , False
I2CStop
Sec=Sec&127
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CSend Sec , True
I2CStop
end sub
'Set Bit 7 of 00h register. Oscillator is disabled, clock stop
Sub Dis_Osc
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , False
I2CStop
Sec=Sec|128
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CSend Sec , True
I2CStop
End sub
' Resets the clock to 00:00:00 01 01/01/00
Sub ResetClock
I2CStart
I2CSend 208, True
I2CSend 0, True
I2CSend 0, True
I2CSend 0, True
I2CSend 0, True
I2CSend 1, True
I2CSend 1, True
I2CSend 1, True
I2CSend 0, True
I2CStop
end sub
'Self explained
Sub SetClock (In Hour , In Min , In Sec , In DayOfWeak , In CDate , in CMonth , in CYear)
DS1307WriteReg(0,DecToBcd(Sec))
DS1307WriteReg(1,DecToBcd(Min))
DS1307WriteReg(2,DecToBcd(Hour))
DS1307WriteReg(3,DecToBcd(DayOfWeak))
DS1307WriteReg(4,DecToBcd(CDate))
DS1307WriteReg(5,DecToBcd(CMonth))
DS1307WriteReg(6,DecToBcd(CYear))
End sub
'Self explained
Sub SetTime (in Hour , in Min , in Sec)
DS1307WriteReg(0,DecToBcd(Sec))
DS1307WriteReg(1,DecToBcd(Min))
DS1307WriteReg(2,DecToBcd(Hour))
End Sub
'Self explained
Sub SetDate (In CDate , in CMonth , in CYear)
DS1307WriteReg(4,DecToBcd(CDate))
DS1307WriteReg(5,DecToBcd(CMonth))
DS1307WriteReg(6,DecToBcd(CYear))
End Sub
'Self explained
Sub ReadClock (out Hour , out Min , out Sec , out DayOfWeak , out CDate , out CMonth , out CYear)
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStop
I2CStart
I2CSend 209 , True
I2CReceive Sec , True
Sec=BcdToDec(Sec & 127)
I2CReceive Min , True
Min=BcdToDec(Min & 127)
I2CReceive Hour , True
if Hour.6 then
Hour=BcdToDec(Hour &31)
Else
Hour=BcdToDec(Hour & 63)
End if
I2CReceive DayOfWeak , True
DayOfWeak=BcdToDec(DayOfWeak & 7)
I2CReceive CDate , True
CDate=BcdToDec(CDate & 63)
I2CReceive CMonth , True
CMonth=BcdToDec(CMonth & 31)
I2CReceive CYear , False
CYear=BcdToDec(CYear)
I2CStop
End Sub
'Self explained
Sub ReadTime (Out Hour , Out Min , Out Sec)
I2CStart
I2CSend 208 , True
I2CSend 0 , True
I2CStart
I2CSend 209 , True
I2CReceive Sec , True
Sec=BcdToDec(Sec & 127)
I2CReceive Min , True
Min=BcdToDec(Min & 127)
I2CReceive Hour , False
I2CStop
if Hour.6 then
Hour=BcdToDec(Hour & 31)
Else
Hour=BcdToDec(Hour & 63)
End if
End sub
'Self explained
Sub ReadDate ( out CDate , out CMonth , out CYear)
I2CStart
I2CSend 208 , True
I2CSend 4 , True
I2CStart
I2CSend 209 , True
I2CReceive CDate , True
CDate=BcdToDec(CDate & 63)
I2CReceive CMonth , True
CMonth=BcdToDec(CMonth & 31)
I2CReceive CYear , False
CYear=BcdToDec(CYear)
I2CStop
end sub
'Set Bit 6 of 02h register. The DS1307 run in 12-hour mode
'The hours value must be re-entered whenever the 12/24-hour mode bit is changed.
Sub Set12HourMode
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CStart
I2CSend 209 , True
I2CReceive Hour , False
I2CStop
Hour.6=1
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CSend Hour , True
I2CStop
End sub
'Clear Bit 6 of 02h register. The DS1307 run in 24-hour mode
'The hours value must be re-entered whenever the 12/24-hour mode bit is changed.
Sub Set24HourMode
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CStart
I2CSend 209, True
I2CReceive Hour , False
I2CStop
Hour.6=0
I2CStart
I2CSend 208 , True
I2CSend 2 , True
I2CSend Hour , True
I2CStop
End sub
' Enables The SQW/OUT pin of chip
' If RateSelect=1 then the outpout Frequency is 1Hz
' If RateSelect=4 then the outpout Frequency is 4.096KHz
' If RateSelect=8 then the outpout Frequency is 8.192KHz
' If RateSelect=32 then the outpout Frequency is 32.768KHz
Sub SQWEnable (RateSelect)
Select case RateSelect
Case 1 : DS1307WriteReg(7,16)
Case 4 : DS1307WriteReg(7,17)
Case 8 : DS1307WriteReg(7,18)
Case 32: DS1307WriteReg(7,19)
End Select
End sub
'Disable the SQW/OUT pin of chip (pin=off)
Sub SQDisable
DS1307WriteReg(7,0)
End Sub
'The contents of the time and calendar registers are in the BCD format.
Function DecToBcd(va) as Byte
DecToBcd=(va/10)*16+va%10
End Function
Function BcdToDec(va) as byte
BcdToDec=(va/16)*10+va%16
End Function
Sub DS1307WriteReg (DS1307Reg, DS1307Value)
I2CStart
I2CSend 208 , True
I2CSend DS1307Reg , True
I2CSend DS1307Value , True
I2CStop
End Sub
The code of the program that made tests are
;Chip Settings
#chip 16F88,4
#config OSC=INTRC_IO, WDT=OFF
;Defines (Constants)
#define LCD_IO 4
#define LCD_RW PORTA.1
#define LCD_RS PORTA.0
#define LCD_Enable PORTA.2
#define LCD_DB4 PORTB.3
#define LCD_DB5 PORTB.5
#define LCD_DB6 PORTB.6
#define LCD_DB7 PORTB.7
#define I2C_MODE Master
#define I2C_DATA PORTB.1
#define I2C_CLOCK PORTB.4
#define DS1307_AddrWrite=208 ' According to manual 1101000+0
#define DS1307_AddrRead=209 ' According to manual 1101000+1
;Variables
Dim Sec As byte
Dim Min As byte
Dim Hour As byte
Dim DayOfWeak as byte
Dim CDate as byte
Dim CMonth as byte
Dim CYear as Byte
Dim va as byte
va=0
cls
InitI2C
Main:
Sec=0
Min=0
Hour=0
CDate=0
CMonth=0
CYear=0
Call ReadTime( Hour , Min , Sec)
locate 0,0
print Hour
print ":"
print Min
Print ":"
Print Sec
Call ReadDate(CDate , CMonth , CYear)
locate 1,0
print CDate
print "/"
print CMonth
print "/"
print CYear
wait 1 s
locate 0,0
print " "
locate 1,0
print " "
InitI2C
goto Main
Sorry for my poor English
Great piece of work. Well done. I want to use the code. Thank you.
A few questions.
The timing changes to 12c.h makes sense.
Your example code which commences as the line 'The code of the program that made tests are' calls the function ReadDate. But where does your example code call the routines you defined?
According to datasheet (page 3) in AC ELECTRICAL CHARACTERISTICS the minimum time of SCL Clock is 4.7 us for LOW end 4 us for HiGH Period. In i2c.h this periods is 1 us. The Controler is 10 times faster than DS1307 end communication its not established.
All these routines, i have put them into a library name DS1307.h and i use any routine i want from it.
Thank you. All make sense now and it compiles.
:-)