Timers: How does one acquire a one second delay using timers.

4 posts / 0 new
Author
Message

Hi everyone. I am quite confused about this code, specifically on the timers. My friend sent me this code and we want to know how did he got a value of 65520 relating to 1 second delay. Initially, He just played around with arduino's libraries and got the idea about the "millis" and how it works with the timer giving a 1 second delay (or not, we're not sure). He copied a chunk of the "millis" code from the library and put it into our own code. The code works as a counter using an atmega328p chip (arduino) and some 7 segment display. We just wanted to know how he got the 65520 value, relating to the timers' giving a delay. We are trying to figure an equation that correlates that of the 65520 value, we've read the manual about timers and we just couldn't get it. Any help?? I've attached a screenshot and a C file for reference.

Attachment(s):

Several considerations here:

The program is defining F_CPU as 12MHz (although I suspect the actual frequency is 16MHz).

Let me modify the comments a bit

```	cli();                          // Clear global interrupt.
TCCR1B = (1<<CS10)|(1<<CS12);   // Set for Divide-by-1024
TCNT1 = 65520;                  // Set for count of 16 (65536-65520 = 16)
TIMSK1 |= (1<<TOIE1);           // Set timer interrupt mask. (I would use "=" instead of "|=")
sei();                          // Set global interrupt flag.
```

If the uC is running at 16MHz, then setting TCCR1B to divide by 1024 means the timer is will increment 15,625 times per second.

Setting the TCNT1 register to 65520 will cause the overflow interrupt to occur 16 timer ticks later (as it rolls over from 65535 to 0).

Thus, the overflow interrupt will occur 15,625/16= 976.6 times per second or every 1.024 ms.

Remember, defining F_CPU only allows the compiler to calculate timing and delays. It does not actually set the uC operating frequency.

I have several issues with this method of using the timer; however, YMMV...

David (aka frog_jr)

Yup. Tell "your friend" he has an error of 2.4% in his millisecond timing.

Handling the timer in this way will also introduce an error due to the latency between the timer wrapping to zero and the actual assignment of the timer register. It will be on the order of a few clock cycles, so we are talking about an error on the order of a microsecond. Still, it's an error introduced by the way "your friend" is handling the timer.

If "your friend" had used a less "coarse" prescaler he could have gotten a smaller error. Even a /1 prescaler and setting TCCR1 to 53536 would work, which would yield an interrupt frequency of

12000 / 1 / (65536-53536) = 1 ms

apart from the latency error (and any in fCPU).

[EDIT: A prescaler of /8 would also work to get you to 1ms (again ignoring the latency error, and any error in fCPU), and the advantage will be 8 times less invocations of the ISR.]

If "your friend" had looked into the CTC modes of the timer he could get rid of the latency error, and have a slightly lesser load on the CPU as CTC modes handles things in hardware that in mode 0 must be handled in software.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Nov 11, 2017 - 01:46 PM

The formula you are looking for is rather straight forward if you know how the prescaler and the timer works:

The prescaler divides the "CPU clock" before it goes to the timer. Let's call the CPU clock frequency fCPU. Lets call the prescaler divisor simply prescalerLet's call the frequency of the incoming clock signal to the timer fTimerTick.

`fTimerTick = fCPU / prescaler                                               [1]`

The timer counts from a start value (the one "your friend" sets in the ISR) up to 65536 and then wraps to zero. At this point the interrupt occurs and the ISR is executed. Let's call the value "your friend" sets in the ISR TimerStartValue. Let's call the the frequency with which ISRs occur fISR.

`fISR = fTimerTick / (65536 - TimerStartValue)                               [2]`

Now you can use your algebraic knowledge and combine those two and you get  formulas for

• Determining the ISR frequency given CPU frequency, prescaler and timer start value, or
• determining timer start value given CPU frequency, prescaler and desired ISR frequency.

Nothing in this takes the latency error into account. It is just partly depending on hardware. It can vary with what code the compiler generates for the ISR entry (this is the true interrupt latency), and the code it generates for the (this is latency between ISR entry and assignment of TCCR1).

Both latency errors are avoided by using a CTC timer mode. In those modes everything is happening in the timer hardware. The timer immediately starts "a new round" while the ISR executes. Thus, while there still is latency (time from timer wrap until ISR is entered) this will not add to the time it takes for the counter to "do a round". The period between two ISR invocations will not include the latency. With this you can get a millisecond ticks whose only error is the error in fCPU. If you are running off a crystal this error will be on the order of 50 ppm (0.0050%).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]