Hello friends,
I'm having some confusion when working with my clock, specifically the hour byte. It works fine except when it turns over from 1900 to 2000, the hour byte goes to "0". My question would be do we mask the bit when writing the byte, reading it, or both? I'm not sure where to begin on this so I thought I might start with this.
Bit 7 of the hour byte is MilTime==1 and bit 5 is pm==1. I dont think it matters which clock because I'm sure this applies to all of them, but just to be sure, datasheet here (corrected link ) http://www.intersil.com/content/dam/Intersil/documents/isl1/isl1208.pdf . Runs in 12hr mode fine, just 24hr mode where I'm having problems.
The register is storred in BCD. Sounds like you are masking off the top three bits so the value can't exceed 0x1F. When it tries to roll from 0x19 (hour 19 in BCD) to 0x20 (hour 20 in BCD) it gets clipped and comes out 0x00. Since the 12-hour format doesn't use that 6th bit it works OK.
I was reluctant to post the whole code because of the state of disarray its in due to me trying things to correct the issue, but I will. John, thats exactly whats wrong, I'm just unsure of how to correct it.
The DS1307 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12-hour or 24-hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20 to 23 hours).
You read bit 6 to decide what to do with bits 5/4.
If 6 is low, then 5/4 are interpreted as 0,1,2, and bits 3-2-1-0 will read out as 0 to 9.
If 6 is high, then 4 will be 0 or 1, 5 can be used for an AM/PM indicator, and bits 3-2-1-0 will read out as 0 to 9.
You have not linked the data sheet for the RTC you are using, and the exact register structure, but if the hour register is equivalent to the DS 1307, then the read mask should be OX3F to get the first 6 bits (0>5) which contain the bcd hour value.
No, it's 4 bits for the ones of hours, 0 to 9, then 1 bit for tens of hours 12 hour mode, or 2 bits for tens of hours in 23 hour mode. Just like the extract of datasheet I posted says.
The mask would also be 0x (zero), not Ox (letter O).
So one could do this:
tensHours = (hours & 0x30) >> 4; // two bits for 24 hour mode
tensHours = (hours & 0x10) >> 4; // one bit for 12 hour mode
No I'm not interpreting to the 1307, it's my confusion thats confusing everyone I think, and oh noobie strikes again, the datasheet came up different, but the registers are the same for this device (same company). I believe my confusion got in the way perhaps. If I'm not mistaken, bit 7 should be high for 24 hr mode?
datasheet = If the MIL bit of the HR register is “1”, the RTC uses a
24-hour format. If the MIL bit is “0”, the RTC uses a 12-hour
format and HR21 bit functions as an AM/PM indicator with a
“1” representing PM. The clock defaults to 12-hour format
time with HR21 = “0”.
Yes, it appears bits 6 & 7 are swapped between the 2 devices.
Still need to interpret 4 bits and 1 or 2 bits?
If the MIL bit is “0”, the RTC uses a 12-hour
format and HR21 bit functions as an AM/PM indicator with a
“1” representing PM. The clock defaults to 12-hour format
time with HR21 = “0”.
Only need 4 bits to count from 1 to 12, and 5 bits from 0 to 23, so one can assume that 4 +1 and 4+2 format is still used.
Yes, if you want to be in the 24 hour mode then bit 7 of the hour register should be set to 1. Then to read from that register in 24 mode the mask is 0x3F for the first 6 bits which you pass into your bcdToDec function.
ok Cat, I'm gonna try that. Check this board out, I made it last night in my basement, its running Uno optiboot, 5volts with crystal (no resonator) and I only brokeout the pins I wanted for my project. Pretty nice eh? BUT I CANT SET MY CLOCK BECAUSE IM A NOOB!!!! Help me guys!!! I also appreciate the time everyone is giving me on this.
That puts the "| 0x80" part outside the call to .write() so that bit is set on the value returned by the function and the result is never used. Maybe it rolls from 19:59:59 to 0:00:00 because 20:00:00 isn't valid for 12-hour time. That should probably be:
Wire.write(decToBcd(19) | 0x80);
You could improve readability by using some named constants like:
I was thinking that the 0x80 which is setting bit 7 should be within the Wire.write() and the dectoBcd() which was probably incorrect since its not decimal and I don't know what the conversion math does with it. Edit-- I think John has the correct arrangement of the brackets in the post above this one.
Until we get this straight, let's stop using both dec and hex expressions mixed together.
We know the register wants to wind up like 10011001 which is the bcd representation of 19hrs i.e. 1x10 + 9 with the top bit set to mil time.
10011001 is decimal 153 or 0x99.
Try Wire.write(dectoBcd(153)) to set the time to 19 hrs with the 24 hr bit set to 1..
You do not clear the top bit to read this. If you do not leave it alone, you will come out of mil time. Your are only going to read the lowest 6 bits of the hours register with the 0x3F mask. Leave the top two bits alone.
SOLVED. I appreciate all the posts, I've learned a bit from each one, which is after all why we are all here. To advance a really fun board (Arduino) with knowlegde!!!
The fix was Johns idea. This is what is working for this chip now:
Wire.write(decToBcd(19) | 0x80);
and
hours=bcdToDec(hours & 0x7f);
Now if I could only write a library for this chip LOL.
But thank you all for you time and help today.
Cheers,
Louie