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

32KHz oscillator is not running accurately with PIC18F26K22

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



Joined: 24 Jun 2012
Posts: 2
Location: Aloha, Oregon

View user's profile Send private message

32KHz oscillator is not running accurately with PIC18F26K22
PostPosted: Mon Jun 25, 2012 12:28 am     Reply with quote

I am trying to make an accurate time of day clock.

I have used this exact code with the PIC18F2620 and other PICs and got accurate results.

What am I doing wrong?

Code:

//------------------------------------------------------------------------------
// 32,768Hz Oscillator
//------------------------------------------------------------------------------
#if XTAL_32768HZ_EXISTS

#define X32768_TICK_EVERY_SEC      1 // Once per second.
#define X32768_TICK_EVERY_TWOSEC   0 // Once every two seconds.

unsigned int32   x32768_tod_seconds;   // Increment once per second.
unsigned int   timer3_timeout;   // Increment 100 times per second.
extern void   tod_clk_tick();


//------------------------------------------------------------------------------
// Initialize timer 3 for use with the 32,768Hz crystal.
//------------------------------------------------------------------------------

#if X32768_TICK_EVERY_TWOSEC || X32768_TICK_EVERY_SEC
void init_timer3() {

   // Setup timer 3 to for 32,768Hz.
   setup_timer_3(T3_EXTERNAL|T3_DIV_BY_1|T3_ENABLE_SOSC); // ASYNC mode.
   T3RD16   = FALSE;
   enable_interrupts(INT_TIMER3);
   timer3_timeout = 0;
}
#endif


//------------------------------------------------------------------------------
// Execute timer3 once per second if the 32,768Hz crystal is installed.
// A 32,768Hz crystal is connected to PIC pins C0,C1 which is configured as
// an external oscillator to operate timer3.
//
// BUG: Clock runs fast in this code. XXX
//------------------------------------------------------------------------------

#if X32768_TICK_EVERY_SEC // Once per second.

unsigned int tmr3h_val1;
unsigned int tmr3l_val1;
unsigned int tmr3h_val2;
unsigned int tmr3l_val2;
unsigned int32 tmr3l_err;

#INT_TIMER3
void timer3_isr() {

   bit_set(TMR3H,7); // Cause overflow every second.
   isr2_status.x32768_sec_flag = TRUE;
   isr2_status.x32768_running = TRUE;
   if (isr2_status.sync_status == SYNC_NONE) {
      isr2_status.sync_status = SYNC_32KHZ;
   }
   timer3_timeout = 0;
   x32768_tod_seconds++;

   tod_clk_tick();
}
#endif


//------------------------------------------------------------------------------
// Execute timer3 once per second if the 32,768Hz crystal is installed.
// A 32,768Hz crystal is connected to PIC pins C0,C1 which is configured as
// an external oscillator to operate timer3.
// The clock is accurate with this code.
//------------------------------------------------------------------------------

#if X32768_TICK_EVERY_TWOSEC // Once every two seconds.
#INT_TIMER3
void timer3_isr() {

   isr2_status.x32768_sec_flag = TRUE;
   isr2_status.x32768_running = TRUE;
   if (isr2_status.sync_status == SYNC_NONE) {
      isr2_status.sync_status = SYNC_32KHZ;
   }
   timer3_timeout = 0;
   x32768_tod_seconds++;
   x32768_tod_seconds++;
   tod_clk_tick();
   tod_clk_tick();

}
#endif

[/code]
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Jun 25, 2012 2:04 am     Reply with quote

You are making a classic assumption about interrupt latency.

If you want to make accurate repeatable time intervals you need to either let the timer free run, as you do in the two second code, or use the hardware reloading timers, such as timer 2 which reload themselves.

The problem with reloading any timer in firmware is that it happens some time after the hardware event that triggered the interrupt. That's tens of us late. This is due to the time the processor takes to respond to the interrupt - the hardware interrupt latency - and the time the CCS code in this instance, takes to process the interrupt and steer it to your code. By the time your code gets round to resetting the timer, it has already ticked on quite a few clocks. The result is obvious: it runs slow.

For many applications this is not noticable and is often ignored in blissful ignorance. For clocks which are required to keep good time its a big issue.

RF Developer
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Mon Jun 25, 2012 4:38 am     Reply with quote

It'd help if you gave an idea of how far out things are.

There are so many things in the code, lacking their external definitions (and calls to functions without the code), that it is difficult to even 'hope' to answer. Personally, I'd simplify the code, throwing away the define tests, and the duplication, and just trying with the simplest subset code to begin with.
Now, obviously, you can't have used the same code on chips like the 2620, since these don't have a secondary oscillator like this, etc. etc..

Latency shouldn't be the problem. He is using an old PIC trick, of just setting the top bit in the high timer register, to effectively add 32768, in one instruction, while leaving the low bits (set by the time you get here), to run. The only problem that might apply, was if there was a wrap from the top bit of TMR3L exactly at the instruction where this bit is set in TMR3H. However with a 32KHz clock, assuming a reasonable clock rate on the main CPU, this should be unlikely. It could be happening though if there is another interrupt that is taking a long time to service, or the main CPU clock rate is slow (not given). This might actually be the most likely problem.
Other likely things are covered in the MicroChip application notes. The Sosc pins are _very_ susceptible to pickup, and (for example), having a port pin running on the board adjacent to these, can lead to extra counts. Again a likely possibility.

So, is the timer running slow or fast?. How much by?. How is the board laid out round here (normally I use the trick of having a separate 'ground ring' running round such oscillators, and removing the ground plane (because of the capacitance), in this area.
Try simplified code, and see if anything changes. How fast is the CPU oscillator?.

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jun 25, 2012 8:13 am     Reply with quote

'accurate' ?

hmm..other possible areas to look at..

1) xtal itself...tolerence 1ppm, 1/2ppm, ???

2) power supply...rock stable ?, any induced AC 'hum' ??

3) external noise...EMI, welders,uwaves,???

4) 32KHz xtal caps...correct for the overall circuit ??

5) PCB layout,cleanliness,etc..

6) As this is a sw RTC, you do have a battery backup with glitchless turnover when the AC power supply fails ?

7) Have you looked at the SW RTC code in the code library ? I know it works flawlessley...

just some ideas....

The fact your code ,as presented ,works fine in other PICs leads me to believe you may have a hardware issue,though what is the problem....too fast,too slow,random, over what time period(seconds, days, hours, weeks).
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Mon Jun 25, 2012 9:07 am     Reply with quote

Have a look at Microchip AN1288. Also, as an example of the general warnings about this type of circuit, look at <http://www.emmicroelectronic.com/webfiles/product/other/EM7604_C7_DS.pdf>, and in particular the bottom right corner of page 28, and the subsequent paragraphs. Sound familiar?. This also describes the ground ring circuit that I use. There are similar warnings from every manufacturer doing chips that use such circuits. I think the ground ring reference I use, originally came from about a 30 year old TI note.

Best Wishes
terrylang



Joined: 24 Jun 2012
Posts: 2
Location: Aloha, Oregon

View user's profile Send private message

The newer PICs just are not quite the same.
PostPosted: Mon Jun 25, 2012 10:16 am     Reply with quote

I was using the trick of just modifying the high register for force a 1 second clock. It always worked for other PICs that I have used.

Interrupt latency is not the problem since the clock runs FAST, not slow. It gains about one minute per day.

I am running a 20MHz main PIC clock.

I cannot use the special interrupt trigger with CCP3 since I also need to use sleep mode.

My solution, for now, is to run a parallel clock that ticks at one second that is run off the millisecond timer that I already have in place for other parts of my code. And sync this timer from the 32KHz timer.

The 32KHz clock running at 2 second intervals, is accurate to one second in two days. This clock always runs while the PIC is running or in sleep ode. When I wake up, I will re synch the one second clock that is operated from the millisecond timer.

Has any one had a similar problem using the old PIC trick? Or is there another simpler solution?
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