|
|
View previous topic :: View next topic |
Author |
Message |
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
Is there a correct way to read a real time clock? |
Posted: Thu Oct 30, 2014 8:56 am |
|
|
Hi folks,
Two posts in one day - a personal best!
This is an unusual one - is there a "correct" order in which to read the registers of a real time clock?
I've used various real time clocks over the years, both internal and external and have seen this behaviour on both.
The reason I ask is this. I've done a project a couple of years ago to control outside clocks running on synchronous ac motors, and to make sure they display the correct time. (Basically involves turning the motor off for 1H or 11H to do summer/winter time changes - and in the event of a power cut, not restarting the motor until the time is equal to the time the power went off)
I am running one of these clocks on the outside of our building, and have also used a spare relay output to drive the dinner bell for the workshop.
At 9:00:00 the bell starts work
at 12:30:00 the bell stops work
at 13:30:00 the bell restarts work
at 18:00 the bell stops work
The bell involved a bit of a hack into the normal code of the unit and basically involves adding into the main loop a bit of code to read the RTC and saying something like :
Code: |
if ( (hours == 9) && (minutes == 0) && (Seconds == 0) )
{
output_high(RELAY);
BellTimer = 5;
}
|
and so on for the other times (Bell timer is decremented in an IRQ and when it reaches zero, stops decrementing and turns the relay off;
This works great - but once or twice a week the bell also goes off at 10am and 7pm. (not 14:30 though - which I think is key).
Do real time clocks actually cascade the time? - so if read in the wrong order could potentially actually give me two 9am's and 6pm's if only for a fraction of a second?
If so - is there a correct order to read the registers in order to prevent this happening.
Thanks in advance
James |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Oct 30, 2014 9:46 am |
|
|
Which RTC?.
It matters.
Normally chips like the DS1307, 'latch' all the registers when one particular one is read (normally the lowest in memory), so that the others won't update, until a 'complete' read is performed.
In many cases, 'sequential' tests are much safer performed on a 'tick'. If (for instance), you have a simple 1/second counter from the RTC interrupt, which then counts minutes, and is reset at midnight, then
your 'bell' becomes:
Code: |
if (mins>=540 && mins<750)
|
Which will work correctly, even if the exact count 'at' 540 is missed.
For the internal RTCC, there is an RTSYNC bit which goes true, when the registers are about to update. You wait for this to go off, then read all 4 word registers into RAM, and do your calculations on the RAM copy. |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Thu Oct 30, 2014 11:45 am |
|
|
Thanks again.
The RTC is a DS1305 that I'm having the issues with.
Do the CCS routines they have supplied for the internal RTC's take into account the RTSYNC when you do a read, or should you do that yourself?
if so, I assume a basic bit test like this, will work?
Code: |
#word RCFGCAL = 0x0860
if (bit_test(RCFGCAL, 12) == 0)
{
/* UPDATE TIME HERE */
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Oct 31, 2014 2:06 am |
|
|
OK.
The reason for your problem, is that the CCS supplied DS1305 driver doesn't take advantage of the latching of the chip. They use sequential single reads, rather than the burst read needed to ensure this.
The code needed (with the ds1305 driver already included), is:
Code: |
void rtc_get_time_burst(unsigned int8 & hr, unsigned int8 & min, unsigned int8 & sec) {
int8 buffer[3];
int8 ctr;
output_high(RTC_RST); //select chip
write_ds1305_byte(0); //start at register 0
for (ctr=0;ctr<3;ctr++)
buffer[ctr]=DS1305_SPI_XFER(0);
//Burst read three bytes
output_low(RTC_RST); //de-select
hr = rm_bcd(buffer[2]); //Now decode the received bytes
min = rm_bcd(buffer[1]);
sec = rm_bcd(buffer[0]);
}
|
and use this to get the time. |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Fri Oct 31, 2014 11:54 am |
|
|
I will give it a go, and keep you posted.
Thanks
James |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Re: Is there a correct way to read a real time clock? |
Posted: Fri Nov 07, 2014 5:10 pm |
|
|
JamesW wrote: | Hi folks,
Two posts in one day - a personal best!
This is an unusual one - is there a "correct" order in which to read the registers of a real time clock?
I've used various real time clocks over the years, both internal and external and have seen this behaviour on both.
The reason I ask is this. I've done a project a couple of years ago to control outside clocks running on synchronous ac motors, and to make sure they display the correct time. (Basically involves turning the motor off for 1H or 11H to do summer/winter time changes - and in the event of a power cut, not restarting the motor until the time is equal to the time the power went off)
I am running one of these clocks on the outside of our building, and have also used a spare relay output to drive the dinner bell for the workshop.
At 9:00:00 the bell starts work
at 12:30:00 the bell stops work
at 13:30:00 the bell restarts work
at 18:00 the bell stops work
The bell involved a bit of a hack into the normal code of the unit and basically involves adding into the main loop a bit of code to read the RTC and saying something like :
Code: |
if ( (hours == 9) && (minutes == 0) && (Seconds == 0) )
{
output_high(RELAY);
BellTimer = 5;
}
|
and so on for the other times (Bell timer is decremented in an IRQ and when it reaches zero, stops decrementing and turns the relay off;
This works great - but once or twice a week the bell also goes off at 10am and 7pm. (not 14:30 though - which I think is key).
Do real time clocks actually cascade the time? - so if read in the wrong order could potentially actually give me two 9am's and 6pm's if only for a fraction of a second?
If so - is there a correct order to read the registers in order to prevent this happening.
Thanks in advance
James |
I ran this code to test how often the seconds counter rolls over without the minutes counter appearing to advance.
Code: | // Clock roll over test
#include <18F252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
int8 year, mth, day, hr, min, sec;
int16 roll_over = 0;
int16 no_min_change = 0;
#include "DS1302.C"
int8 old_sec, old_min;
void main()
{
rtc_init();
rtc_get_time (hr, min, sec);
old_sec = sec;
old_min = min;
while (1)
{
while (old_sec == sec) {rtc_get_time (hr, min, sec);}
if (sec == 0x59)
{
printf (" \n\r ");
printf( " clock roll over test %xhr %xmin %xsec \n\r ", hr, min, sec);
}
if (sec == 0x00)
{
printf( " clock roll over test %xhr %xmin %xsec \n\r ", hr, min, sec);
roll_over++;
if (min == old_min) {no_min_change++; }
printf( " %ld roll_over %ld with no_min_change \n\r " , roll_over, no_min_change );
}
old_sec = sec;
old_min = min;
}
} |
The result was that on roughly 1 in 3 occasions the seconds display rolled over to zero before the minutes counter appeared to advance.
For example, 23min 59sec was followed by 23min 00sec, rather than the correct 24min 00sec.
This tallies with your observation and supports Mr T's assertion regarding the CCS driver.
I've used a DS1302 rather than your DS1305, but suspect the problem lies in the CCS supplied driver.
The CCS driver reads hr, min, sec in turn.
If the seconds counter rolls over during the read_hr my code detects NO error.
If the seconds counter rolls over during the read_min my code WILL detect an error.
If the seconds counter rolls over during the read_sec my code detects NO error.
My code spends virtually all its time reading the DS1302 clock.
It should detect an error roughly once per three readings, which agrees with my measurements.
I don't know anything about the internal workings of the DS1302 chip.
I would hope the clock chip's counters operate synchronously and do not introduce significant reading errors.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Nov 08, 2014 1:52 am |
|
|
Yes, and no....
Reading the data sheet of the 1305, it specifically says that you have to use burst mode, then the registers will all be latched till the read completes.
The 1302, is fractionally different, it latches the registers, till CE rises. So with this you can do 'separate' reads, provided you don't release CE. The burst mode implementation is slightly different on this chip, making it less convenient to use, which is probably 'why' they give this alternative.
However the CCS driver, as written releases the CE line between each read, so will give the same problem...
The old 'read the data sheet' problem at CCS..... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|