CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Is there a correct way to read a real time clock?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

View user's profile Send private message Visit poster's website

Is there a correct way to read a real time clock?
PostPosted: Thu Oct 30, 2014 8:56 am     Reply with quote

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: 19260

View user's profile Send private message

PostPosted: Thu Oct 30, 2014 9:46 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Thu Oct 30, 2014 11:45 am     Reply with quote

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: 19260

View user's profile Send private message

PostPosted: Fri Oct 31, 2014 2:06 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 31, 2014 11:54 am     Reply with quote

I will give it a go, and keep you posted.

Thanks

James
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Re: Is there a correct way to read a real time clock?
PostPosted: Fri Nov 07, 2014 5:10 pm     Reply with quote

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: 19260

View user's profile Send private message

PostPosted: Sat Nov 08, 2014 1:52 am     Reply with quote

Yes, and no.... Smile

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.....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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