DS3231 RTC Enhancements

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
I have added a button to increase the minutes or seconds of a DS3231 module by 1 (one) each time it is pushed:
Code:
Increment
     movlw     7   
     addwf     min_sec,w      ;test if low nibble =9
     btfsc     STATUS,1       ;test DC
     goto      Done         
     incf      min_sec,w
Done
     nop                      ;this will be a call with value in w to "WriteOneByte"
Note: "min_sec" is the current read of the appropriate register in the RTC.

There is no check for reaching "60." Of course, it is no big strain to add that test. Does anyone know what happens if you try to write a "60" in BCD to the minutes or seconds registers?

Just FWI, since some of you may not have played with these devices in awhile: BCD "59" = b'01011001'
and BCD "60" = b'01100000'

I thought I would ask before just trying it.

Regards, John
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
@jpanhalt Looks OK. Don't forget to save your result in min_sec.

You can also save a jump and a Tcyc or two by:
Code:
  incf min_sec,F   ; bump time
  movlw 06h     ; add 6 to LSnibble to see if its >= Ah
  addwf min_sec,W
  btfsc STATUS,DC   ; if digit carry it rolled 9-> 0 and is adjusted
  movwf min_sec   ; save incremented/adjusted result - it may be out of range
 
  addlw 0A0h     ; test for wrap around by adding complement of 60h
  btfsc STATUS,C   ; C if copy of incremented/adjusted BCD value was >=60h
  clrf min_sec   ; 60h->00h ; min_sec needs wrapping 60h -> 00h
  movf min_sec,W   ; min_sec is incremented, adjusted and wrapped. Get result to W
You can also do to the test for 59h before the increment but that probably means a jump. Lots of ways to do it.

Have fun!
EDIT: @jpanhalt tested and corrected code - sheesh..
 
Last edited:

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Thank you for the code. I will play with it tomorrow. It would be nice to save that jump.

I will try not to forget where the answer is. ;) I often call with it in W, but I am not certain I will do that in this instance. If someone doesn't speak up about what happens when values that are not possible are written, I will just try it.

John
 

JohnInTX

Joined Jun 26, 2012
4,787
W is great for passing parameters. I make it a habit to maintain values in RAM and use W for rank temporary stuff. Otherwise, I forget to save things..
As far as writing out of range values, if it is specified in the datasheet what happens when you do, you might be OK. If it isn't, don't do it. Unspecified things have a way of changing without notice and can work differently even from legitimate 2ed source manufacturers. You don't have control over that but you do have control over writing valid values so I'd recommend you stay within the lines.

Best regards,
John

PS I tweaked the code to save a byte.
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
The datasheet is silent on that subject. As was Google, best I could tell. I would be extremely surprised if the seconds rolled over. My guess is it is either ignored, i.e, 60 might be read as 20, read as zero, doesn't read at all, or is read as hash. I favor the latter two. I have 3 of these modules and if I brick one, it is no great loss. Besides, that will give me a chance to test my un-bricking routine.

I am actually more interested in getting experience with the I2C interface and have a list of questions regarding error handling which I plan to post when they are more refined. Since getting some minor glitches fixed in January, I have yet to get an error (1 master, 1 slave), but what worries me is the somewhat vague discussion of error handling in the Microchip notes. Today was not my day -- a rare "migraine." I even cancelled a trip into Cleveland. Will be much better tomorrow.

Thanks for the tweak.

John
 

NorthGuy

Joined Jun 28, 2014
611
Something of that sort:

Code:
movlw 0xA7       ; we want to set DC if there's a carry and/or C if it's 0x59
addwf min_sec,f
movlw 0xA6       ; we're going to subtract this back if there's no carries
btfsc STATUS,1   ; but if there was DC carry, we only need to subtract back 0xA0
movlw 0xA0
btfss STATUS,0   ; and if we had 0x59, there's no need to subtract - zero is already there
subwf min_sec,f
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
This old chemist just had to do the experiment: What happens when you write a BCD >59 to minutes or seconds?
1) Both registers seems to behave the same wary. Testing the seconds (register 0x00) doesn't take as long as testing minutes. I did not fully test the minutes register.
2) When written with bcd 60 (or any of several numbers >60), that value is displayed and counts up "normally" (i.e., the low nibble counts and high nibble increments ) until "79" is displayed. At that point, the display changes to 40 and continues to work normally thereafter. Thus, looking only at the high nibble:
Code:
0110
0111
x100
Interesting that x111 doesn't roll over to x000 but rather goes to x100.
Testing the low nibble of the seconds register with 0x5A gave in sequence:
Code:
01011010   (displayed as 5A)
01011011   (displayed as 5B)
00000100   (displayed as 04) and minutes increment
Thank you both for the code advice. I will avoid writing 60.

John

Edit: Of course, my print algorithm may affect what is displayed.
 
Last edited:

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Just in case someone in the future finds this thread, I followed NorthGuy's lead and rewrote my code for decrement of the packed BCD registers.
Code:
Decrement                     ;decrement minute or second packed BCD registers
     movlw     -1
     addwf     min_sec,f
     btfss     STATUS,0       ;Carry clear on borrow
     goto      err            ;err routine simply ignores decrement request
     movlw     6              
     btfss     STATUS,1       ;DC clear on borrow, result goes back to original subtraction
     subwf     min_sec,f      ;BCD correction for carrying 15 to low nibble
     nop
Thanks again for the help.

John
 
Top