## Simple timer with 20mHz clock

14 posts / 0 new
Author
Message

Hi Guys,

I'm trying to implement a simple counter to generate an interrupt every 2ms (roughly) so I can monitor pin change speed based on the counter.

I've looked at some of the online calculators and read some of the tutorials on timers, but my head's starting to spin a little I have to say.

Using one of the calculators i've come out with some figures but I'm not sure if these are suitable

Timer1

F_CPU 20000000UL

prescaler CLK/32

real time: 0.002 seconds

total timer ticks: 1250

Frequency: 500Hz

remainder ticks: 1250

overflow:0

All the ISR will do is increment a value

Am I on the right track?

regards

20M / 32 is 625k so the length of one "tick" is 1/625000 which is 1.6us. If you count 1250 of these the timer period will be 2,000us which is, indeed 2ms :-)

Thank you.

My question then is, how do I get the timer to generate an interupt at 1,250? and would a prescaler of CLK/64 be better? (625 ticks)?

regards

nikm wrote:
My question then is, how do I get the timer to generate an interupt at 1,250? and would a prescaler of CLK/64 be better? (625 ticks)?

Remember that to get 1250 total ticks you set the compare-match value to 1249 since 0 is counted.

Remember 1250/64 isn't 625.

Remember that an 8-bit timer can only count to 255.

All of this and much more is covered, and in a much better fashion, by articles on timers in the Tutorials forum.

https://www.avrfreaks.net/forum/...

...and more.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Nov 20, 2020 - 12:39 PM

Thanks,

However all the examples have a prescaler of 64

ie

// set up timer with prescaler = 64 and CTC mode

TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);

I cannot figure out, which part of the above sets that value.  In my case I want a prescaler of 1, where would that be set?

regards

where would that be set?

What does that data sheet say?  Did you search for prescaler

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Since you said (roughly) every 2ms, don't waste a valuable 16-bit timer.  Use an 8-bit timer that gets you close enough.  You can use either a prescale of 256 and a count of 156, or a prescale of 1024 and a count of 39.  Either one will give you a tick every 1.9968ms, or 0.16% off.

Last Edited: Fri. Nov 20, 2020 - 07:48 PM

Ah, thank you, I assumed it was a standard formula

Atmega324PB -  for no prescaler, CS11 is not set. so

TCCR1B |= (1 << WGM12)|(1 << CS10);

should do the trick I guess

regards

Good point, though I have 3 16bit timers in the Atmega324PB

regards

I would also recommend using an 8-bit timer with a prescaler of 256.   I always use the overflow interrupt with timers, for no other reason than it works and I know how to do it.

Load the timer with a value of 100 (256-156):100.   After 156 counts the 8-bit timer will overflow and cause an interrupt.  In the IRQ routine, set a flag for the main code that lets the main code know that a 2mS interval has passed.   Use a bool variable that has been declared 'volatile'.   Then reload the 8-bit timer with the value:100, and exit the IRQ  In the main code, poll for this flag being set.   When it is, do the 2mS activity and don't forget to clear the boolean flag.

I might be wrong, but with a clock speed of 20mHz, I don't think an 8bit timer would work would it?

regards

nikm wrote:

I might be wrong, but with a clock speed of 20mHz, I don't think an 8bit timer would work would it?

Note: mHz is milliHertz.  MHz is MegaHertz. :)

The question is, what is the biggest division that an 8-bit timer can produce.  Assuming a prescaler setting of 1024, an 8-bit timer can divide the clock by 1024*256 or 2^18 (262,1440).  20 MHz divided by 262,144 = 76.3 ticks/sec, or a max tick interval of 13.1ms.

Simonetta wrote:

I would also recommend using an 8-bit timer with a prescaler of 256.   I always use the overflow interrupt with timers, for no other reason than it works and I know how to do it.

Load the timer with a value of 100 (256-156):100.   After 156 counts the 8-bit timer will overflow and cause an interrupt.  In the IRQ routine, set a flag for the main code that lets the main code know that a 2mS interval has passed.   Use a bool variable that has been declared 'volatile'.   Then reload the 8-bit timer with the value:100, and exit the IRQ  In the main code, poll for this flag being set.   When it is, do the 2mS activity and don't forget to clear the boolean flag.

Note that this requires the timer to be reloaded within 256 clocks (which is very relaxed timing, should be trivial to do).  Similarly, a prescale of 1024 needs to have the timer reloaded within 1024 clocks.  This only gets to be an issue when using much smaller prescale values.

BTW, in the bad old days, this was the only way most timers worked.  We are so much more fortunate in today's timer universe.

Last Edited: Fri. Nov 20, 2020 - 09:45 PM