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

Timers - what you should know

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



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

Timers - what you should know
PostPosted: Wed Apr 06, 2005 12:52 am     Reply with quote

There's been so many timer posts lately. Hopefully this helps to clear up some of the confusion regarding timers. I will use an example that is driven by the internal (system) clock.

Whatever the master crystal frequency is, the internal (system) clock is always the crystal frequency divided by 4.

Example:

Crystal: 4 MHz
System clock: 1 MHz (1 microsecond period)


The system clock is what drives the timer modules (if set up to use the internal clock.) However, there is a prescaler which can also be set. A prescaler is a programmable "divide by N" block where N is the number of input clock cycles it takes to get one output cycle out of the prescaler.

Example:

Let's assume that you want to use timer 0. Timer 0's prescaler can be set to 1 (no divide at all), 2, 4, 8, ....., all the way up to 256. If it was set to 256, then it would take 256 system clock cycles to get one cycle out of the prescaler. Therefore timer 0 would then count up at a rate of one count every 1 microsecond (system clock) x 256 (prescaler setting) = 256 microseconds/count.

Note that some timers can also have postscalers.

A timer will generate an interrupt every time it overflows, and if its' interrupt is enabled. Timer 0 can be set to either 8 bit mode or 16. In 8 bit mode, it overflows every 256 counts. It would take 65,536 counts in 16 bit mode.

To completely set up timer 0 in 8 bit mode with the system clock as its source and with a prescaler of 256, you would code:

Code:
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);


The constants used in this function, and the functions for the other timers are found in the device's header file. For instance, 18F452.h. Look for it in the PICC\devices directory.

Extending our example:

In 8 bit mode, timer 0 would overflow (interrupt) every 256 microseconds/count x 256 counts/overflow = 65,536 microseconds = 65.536 milliseconds.
In 16 bit mode, timer 0 would overflow (interrupt) every 256 microseconds/count x 65,536 counts/overflow = 16,777,216 microseconds = 16.777216 seconds.


So, with all this in mind, it's up to you to choose
a) the clock source,
b) whether you need an 8 or 16 bit counter, and
c) the prescaler value.

So, as a starting point, if I had to create a 1 ms "tick" and my crystal frequency was 4 MHz, I would do it this way (again as a starting point; greater accuracy may require different values).

Timer 0: 8 bit mode, driven by the internal clock. Now the (harder) part: choosing the prescale value.

If the prescaler was set to 1, I'd get an interrupt every 256 us. This is probably too fast - I wouldn't want to tie up the processor with all of the interrupt services this would take - about 4 per millisecond.

If the prescaler was set to 2, there would be an interrupt every 512 us. Again, probably too fast.

If the prescaler was set to 4, there would be an interrupt every 1,024 us = 1.024 ms. Bingo. If timing isn't absolutely critical, I'd just let timer 0 free run. If timing is critical, then you'll need to tweak this just a bit.

With the prescaler set to 4, timer 0 counts up once every 4 us. So how many 4 us clicks are in 1 ms? 0.001s/0.000004s = 250. This is the number of counts of timer 0 in 1 ms (note that 250 is 6 less than 256 - this will be important later). Aha. Now we have everything we need.

Timer 0's ISR:

Code:
#byte timer0low = 0xfd6

#int_RTCC
void RTCC_isr(void) {
   timer0low = timer0low + 6;
   one_millisecond = TRUE;
}


All you look for in the main routine is for one_millisecond to be set. There's your 1ms tick.

The reason why I directly add 6 to whatever timer 0's count is at is because 6 is the number of ticks I need to skip in order for timer 0 to count 250 times before it rolls over. If used:

Code:
set_timer0(6);


instead, the accuracy of the 1 ms tick would be very poor. That is because it takes quite a long time for the processor to stop what it is doing and service the interrupt. With a 4 MHz clock, this may be 60 - 80 us or more. By the time that the processor gets around to servicing the interrupt, timer 0 will have counted up to 15 - 20 already; by setting it back to 6, what we think is our 1 ms tick will be way too slow.

And the location of timer 0's register is found in the PIC's data sheet. Look in the memory organization section for the special function registers. You'll find all of their memory addresses there.

Lastly, EXPERIMENT FOR GOD'S SAKE!!!! Hook up an led and flash the stupid thing at an easily measurable/discernable rate so you can confirm your calculations. Setting up a timer isn't rocket science.
bb



Joined: 06 Apr 2005
Posts: 7
Location: Germany

View user's profile Send private message

PostPosted: Wed Apr 06, 2005 2:05 pm     Reply with quote

Setting up a timer isn't rocket science, but you'll have to take the following into account.

Mid-Range MCU Family Reference Manual:
Quote:

Any write to the TMR0 register will cause a 2 instruction cycle (2TCY) inhibit. That is, after the
TMR0 register has been written with the new value, TMR0 will not be incremented until the third
instruction cycle later (Figure 11-2). When the prescaler is assigned to the Timer0 module, any
write to the TMR0 register will immediately update the TMR0 register and clear the prescaler. The
incrementing of Timer0 (TMR0 and Prescaler) will also be inhibited 2 instruction cycles (TCY). So
if the prescaler is configured as 2, then after a write to the TMR0 register TMR0 will not increment
for 4 Timer0 clocks.


PIC18 Reference manual:
Quote:

Writes to TMR0H do not clear the Timer0 prescaler in 16-bit mode, because a write to TMR0H
only modifies the Timer0 latch and does not change the contents of Timer0. The prescaler is only
cleared on writes to TMR0L.

Any write to the TMR0 register will cause a 2 instruction cycle (2TCY) inhibit. That is, after the
TMR0 register has been written with the new value, TMR0 will not be incremented until the third
instruction cycle later (Figure 13-6). When the prescaler is assigned to the Timer0 module, any
write to the TMR0 register will immediately update the TMR0 register and clear the prescaler.
The incrementing of Timer0 (TMR0 and Prescaler) will also be inhibited 2 instruction cycles
(TCY). So if the prescaler is configured as 2, then after a write to the TMR0 register, TMR0 will
not increment for 4 Timer0 clocks (Figure 13-7). After that, TMR0 will increment every prescaler
number of clocks later.


Best regards,
Bernd
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Wed Apr 06, 2005 2:24 pm     Reply with quote

Thanks for the information. But like I said in the original post:

Quote:
So, as a starting point, if I had to create a 1 ms "tick" and my crystal frequency was 4 MHz, I would do it this way (again as a starting point; greater accuracy may require different values).


My issue is with people who show up and say "I need to do this....Anyone have any code?" That's why I posted this in the first place. If they had any initiative at all, they'd quickly find their own solution.

Sorry. I guess that my present job (teaching) has jaded me. I can't stand a student who expects everything to be handed to them on a platter. They have to think for themselves and more importantly make mistakes; that's the only way anyone truly learns something.

I'll add your comments to the other post in the code library too.
bb



Joined: 06 Apr 2005
Posts: 7
Location: Germany

View user's profile Send private message

PostPosted: Wed Apr 06, 2005 3:03 pm     Reply with quote

I'm sorry if I offended you, it was definitely not my intent. I just wanted to add some useful information. Please consider that English isn't my native language.

Best regards,

Bernd
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Wed Apr 06, 2005 3:25 pm     Reply with quote

No offense taken at all - in fact I'm grateful that you offered that information. I learned something, and hopefully it will be of use to someone else.

Once again, sorry.
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