Real Time Clock DS1307 SparkFun BOB-12708


This article is about the 12hour mode and Day Light Saving Time of the SparkFun BOB-12708 (DS1307) RTC and assumes the use of Arduino IDE with #include “Wire.h” and references to code published by First of all, the function decToBcd does not result in binary coded decimal (BCD). The result is a binary representation unique to the DS1307. Bits 0-3 which could hold a value of 12 (1100) or more in BCD is restricted to a value of 9 (1001). Bit 4 represents the value of 10, so decimal 12 is (10010). Bit 5, if in 24hour mode represents the value of 20, so decimal 23 is (100011). Fortunately, the function bcdToDec returns this unique binary to the appropriate decimal value. After establishing connection with the DS1307 Timekeeper registers with the following: Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x00); Wire.requestFrom(DS1307_ADDRESS,7); seconds = bcdToDec(; minutes = bcdToDec(; hr =; //reg 2 hours = bcdToDec(hr); //hour without controls (AM/PM,12/24hr) day = bcdToDec(; date = bcdToDec(; month = bcdToDec(; yr =; //reg 6 year = bcdToDec(yr); //year without dst The third or Wire.write will access the hour’s register (02h), see table below. If you are going to use the 24hour mode, Wire.write(decToBcd(hour)); will be fine. However, if you want the 12hour mode, the read and write statements need some help. To retrieve the hour in 12hour mode, you need to mask out the control bits (5 and 6) saving the bit 5 information. So the statements would look like this: tempVar =; Serial.print(bcdToDec(tempVar & 0x1f); //remove control bits (5 and6) if(bitRead(tempVar, 6)){ //check for 12hour mode, bit 6 = 1 if(bitRead(tempVar, 5)) Serial.print(“PM”); //bit 5 = 1 (PM) else Serial.print(“AM”);} //bit 5 = 0 (AM) To write the hour in 12hour mode you must consider the control bits (5 and 6). By Or’ing the hour variable with 0x60, the 12hour mode is set to PM: Wire.write(decToBcd(hour) | 0x60); By Or’ing the hour variable with 0x40, the 12hour mode is set to AM: Wire.write(decToBcd(hour) | 0x40); Now for dealing with Day Light Saving Time (DST). The 2nd Sunday in March, time changes from 2am to 3am. The 1st Sunday in November, time changes from 3am to 2am. Just because not everyone recognizes DST, I have an external switch to indicate that. So you test for: 1) DST recognition, 2) the 3rd or 11th month, 3) whether you already increased or decreased the hour. 4) the day of the week (Sunday), 5) a date >7 for March or a date <8 for November, 6) the hour of 2am for March or the hour of 3am for November, I choose to use bit 8 of the RTC register 06h to keep track of when its DST. This bit will only be used for years 2080 and above. Here is an example code to test for the above conditions: if(digitalRead(dstPin) == 0){ //DST participant if(month == 3){ if(dstAct == 0x00){ if(weekDay == 1){ if(monthDay > 7){ if((hour == 2)&(AMPM == 0)){ hour = hour +1; //ensure you haven't already increased the hour. dstAct = 0x80; //DST status if(month == 11){ if(dst == 0x80){ if(weekDay == 1){ if(monthDay < 8){ if((hour == 3)&(AMPM == 0)){ hour = hour - 1; dstAct = 0x00; //DST status Here is the code to save the DST status: Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x06); Wire.write(decToBcd(yr) | dstAct); //yr as read above Wire.endTransmission(); Here is the code to retrieve the DST status: Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x06); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 1); dstAct = ( & 0x80); Wire.endTransmission();  

Comment reply to