Simple timer with 20mHz clock

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

regards

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

regards

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nikm wrote:

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

The slowest you can run a timer is /1024 so on 20MHz that means 19,531Hz. At that speed 1 "tick" is therefore 1/19531 = 51.2us. The most of these an 8 bit timer can count is 256 so 256 * 51.2us is 13,107us which is 13.107ms. So if you are looking for 2ms then it is in range. Even if you'd been looking for 250ms (out of range) it's still do-able. You'd actually set the timer to some fraction of this (maybe 10ms) then only take action each time you have counted 25 of these.