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 CCS Technical Support

General clock, timing, and interval question

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







General clock, timing, and interval question
PostPosted: Tue Feb 24, 2004 11:27 am     Reply with quote

Advice from the experts, please:
Question If I need a basic PIC to do something at periodic intervals (like take an ADC measurement, or send data out the RS232 port), what is the best way to do this when the time between these events is very, very long wrt the clock cycle?

For example, I want to do something every hour for 1000 hours - this is a made-up but maybe practical example. Is it best to use the internal timers and interrupts, or would one use a real-time clock? Are the internal timers (assuming the code is written correctly, temperature is stable, etc.) precise enough for such long-term measurements? Or does the cumulative error get too big (I don't mean the error from rounding of integers - I assume the code is written to minimize this if possible)? Does one then use an off-board clock and use this to time the events? What do people do in this case?

General comments appreciated. Thanks.
Bill
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Tue Feb 24, 2004 11:44 am     Reply with quote

This is for a 4Mhz crystle

Code:
int1  Clock_Been_Initialized=0;

Int16 Miliseconds;
#locate Miliseconds = Registry_Map+6
Int16 Seconds;
#locate Seconds = Registry_Map+8
int1  Second_Tick=0;

// Global Real Time Clock Information
#int_TIMER2                                                 // Clock interrupt adjusted to occurs ~ 1ms
void TIMER2_isr()
{  Miliseconds++;
   if(Miliseconds>999)
   {  Miliseconds=0;
      Seconds++;
      Second_Tick=1;
   }
}
/***********************************************************
*    Service Hardware Modules                              *
***********************************************************/
#inline
void Clock_Service(void)
{  if(!Clock_Been_Initialized)
   {  setup_timer_2(T2_DIV_BY_4,249,1);                     // Set 1mS period
      enable_interrupts(INT_TIMER2);
      Seconds=0;
      Clock_Been_Initialized=1;
   }
   if(Second_Tick)
   {  Second_Tick=0;
       if(++seconds>59) seconds=0;
       if(++Minutes>59)
       {   bla bla hour event.....
       }
   }
}
plehman



Joined: 18 Feb 2004
Posts: 12

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 24, 2004 11:54 am     Reply with quote

It might help to know what type of timing error you can tolerate. If you are reading every hour for 1000 hours, then a couple of seconds either way may not make a difference. If that's the key, you could probably use the RTC or the timers on the PIC.

If you were to right the clock service as an interrupt service routine, and you timed out how long it was going to take, you could probably "calibrate" out the error on a gross scale, though this would be easier in Assembly language.

Consider the following:

PIC clocked from 4MHz crystal => 1MHz instruction rate
Timer1 used (its 16-bits long on most if not all PICs)
Timer1 set up with a 1:8 prescaler

To get an interrupt every 1/2 second, set Timer1's initial count to 0x0BDB so that an interrupt from overflow will be generated in 62500 clocks (0.5seconds). From the data sheet and looking at the .LST file, you can determine the number of clock cycles it takes to execute your isr for Timer1 (remember to account for CALLs and RETurns into and outof the isr and sub-routines).

you could set up the isr using the code as follows for a good idea

Code:

static long HoursWorthOfHalfSecs = 0;
static boolean A2DConvertFlag = 0;

#int_TIMER1
void TIMER1_isr()
{
    HoursWorthOfHalfSecs++;
    if (HoursWorthOfHalfSecs == 7200)
    {
        HoursWorthOfHalfSecs = 0;
        ConvertA2DFlag = 1;
     }
     set_timer1(XXXX);      // XXXX is new count to set it to to account for timing of routine
}

void main()
{
    ........  // Setup, etc.
    while(1)
    {
        if (ConvertA2DFlag == 1)
        {
            convert_adc();
            ConvertA2DFlag = 0;
        }
    }
}


Now check the assembly created for the TIMER1_isr() in the .LST file, count the clock cycles used, and add them to 0x0BDB to get the new value to set the Timer1 count to before returning from the isr. Now you can minimize the while(1) loop to determine how many clocks from the end if the isr that the code will execute, and the implication is that the A/D conversion would be taken within a few cycles of each other at pretty close to exactly an hour interval.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Tue Feb 24, 2004 2:22 pm     Reply with quote

This will get an exact 1mS interupt period when using a 4Mhz crystle

setup_timer_2(T2_DIV_BY_4,249,1); // Set 1mS period

This says count exactly 1000 instruction periods and then sets the interupt flag. There is no drift unless interupts are disabled.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Tue Feb 24, 2004 2:44 pm     Reply with quote

Consider that a generic micrprocessor crystal has a tollerance of about +/-30ppm, that gives +/-100ms/hour. What sort of accuracy do you require?
_________________
The search for better is endless. Instead simply find very good and get the job done.
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