## [TUT] [C] Newbie's Guide to AVR Timers

483 posts / 0 new

## Pages

Total votes: 0

Quote:
So if those things don't vary much you can just have a fixed value to tweak the OSCCAL register to bring it back to accuracy.

thank you, so im going to tweak the OSSCAL as you said, i was thinking in compensate the timer counter :S

Total votes: 0

Great tutorial, but one thing is not clear to me.

Let's assume you have a timer tick each 1 Âµs
I want to measure 1 s = 10^6 Âµs.
Too big for a 16-bit timer, so let's count the overflows and do some math:

2^16 = 65536

Case 1:
> Overflow at 2^16 ticks (Âµs)?
10^6 / 2^16 = 15,26... overflows.
after the 15th overflow, 0,26 * 2^16 has to be reached (16960 ticks)

Case 2:
> Overflow at 2^16 - 1 ticks (Âµs)?
10^6 / (2^16 - 1) = 15,26... overflows.
after the 15th overflow, 0,26 * (2^16 - 1) has to be reached (16975 ticks)

It's just a minor difference but wrong is wrong

Total votes: 0

Case 1 is correct, but 1000000 is not evenly divisible by 65536 so you would never get exactly one second. You can put the timer into CTC mode and use a TOP value that results in an exact value. If you use 62499 for TOP (which gives you 62500 ticks between compare matches), then it is exactly 16 compare matches in one second.

Regards,
Steve A.

The Board helps those that help themselves.

Total votes: 0

If you use a /64 prescale and CTC with OCR1A=0x3D08 then avrcalc says you should hit it without having to count overflows/matches.

Total votes: 0

hi all,

it's my first post in here I hope i'm doing things right.
I've some weird issues (don't know if a new topic is necessary) and in spite of this great tutorial I can't get the idea working.

```#include
#include

int t = 0;

void setup(){

TCCR1B |=   (1<<CS10);     // set timer 1 (16 bits) to full clock source
TCCR1B |=  (1<<WGM12); // CTC mode enabled
OCR1A = 15624; //value to compare against
TIMSK1 |= (1 << OCIE1A); // CTC interupts enabled
sei();

Serial.begin(9600);
}
void loop(){}

ISR(TIMER1_COMPA_vect)
{t++;
Serial.println(t);}
```

the issue is: t only goes to a certain number and stop .it's certainly an obvious mistake but I can't manage to find what's going on .
On the other hand , if I display TCNT1 in the main fonction it works fine. it has to do with the ISR and the compare match.
the code shown is a simple one (Iguess) but it doesn't work as expected, whatever the type of variable.

and even with an interrupt overflow the increment of the variable stops and doesn't count more than few value at the begining.

The project that I have (and for the purpose of using timers ) is to output a sinwave in a DAC in the Interupt via a look up table. The main loop will be used to display imformation on LCD as it doesn't need refresh all the time.

This is for a tinny signal generator and a LFO for musical electronic purposes.

Sorry for the Arduino code , I'm currently using it for convenience but I decided to follow my first idea and get to the AVR instead.

Is this issue a known thing ? a newbie trap ? i'm pretty stock actually.

thanks

Total votes: 0

I haven't delved that deeply into Arduino library code but I thought they used timer1 for Arduino's own purposes. If so your use of it may be messing with normal operation. This would be especially so if something inside the Serial class was using timer1 ticks for something like timeouts.

As the program is so simple why not implement it in plain C. The only "tricky" bit is the Serial.println() but if you just implement a UART_init() and a UART_putchar you can connect the putchar to the stdout stream and then printf() or whatever.

BWT just for future reference the threads in Tutorial are for presenting an article then subsequent feedback about it. As your post isn't really directly related to the tutorial as such this should be a separate thread in AVR Forum. I can split it if you like? I'd call it something like "Arduino timer counting problem" so you won't lose it.

Moderator.

Total votes: 0

Good tutorial, thanks :) as a complement to AVR130 application note for assembler.

AVR assembler sources at http://avr-asm.blogspot.com

Total votes: 0

clawson wrote:
I haven't delved that deeply into Arduino library code but I thought they used timer1 for Arduino's own purposes. If so your use of it may be messing with normal operation. This would be especially so if something inside the Serial class was using timer1 ticks for something like timeouts.

As the program is so simple why not implement it in plain C. The only "tricky" bit is the Serial.println() but if you just implement a UART_init() and a UART_putchar you can connect the putchar to the stdout stream and then printf() or whatever.

BWT just for future reference the threads in Tutorial are for presenting an article then subsequent feedback about it. As your post isn't really directly related to the tutorial as such this should be a separate thread in AVR Forum. I can split it if you like? I'd call it something like "Arduino timer counting problem" so you won't lose it.

Moderator.

Hi, sorry I didn't see that answers was posted :oops: . Sorry for the misplaced message.

actually I decided to leave arduino plateform (nice to start but too many things are hidden and don't help the understanding. Beside you can only use a specific chip)

The timer 0 or 1 is used for the millis() fonction and the compiler specifies an error if you use it for something else.

Anyway, I have some serious readings to do for starting with the proper AVR plateform. I'll post a proper topic with my issues regarding this LFO/frequency generator project in the future.

Total votes: 0

As a newbie, I found this tutorial informative and useful. Thank you very much!

Total votes: 0

Likewise, I found this tutorial very useful. I used it to turn my Dragon Rider LCD into a combination clock/calendar, complete with switches for setting the time and date and blinking tick-tock LED.

I found (as one might expect) that the crystal-based clock circuit on the Dragon Rider isn't 100% accurate, given that it lacks temperature compensation and the tolerance of the crystal isn't that tight. So I added a user interface to adjust the CTC timeout value up or down, depending on whether the clock needs to run a bit faster or a bit slower. This added one more constraint to calculating a timer prescaler and interrupt rate, which is that it is better to have as large a number as possible within in the limits of the 16-bit timer, as this allows finer adjustments to the rate at which the clock runs. In my case, the Dragon Rider came with a 7.3728 MHz crystal, so I use no prescaler and a 120Hz interrupt rate, giving me a period of 8 and 1/3 milliseconds and a nominal reset count of 61455. The purist will point out that this doesn't yield exactly 8 and 1/3 milliseconds. However, it is reasonably close, and allows for 4x finer adjustments than if, for example, I went for a rate of 100 Hz and was able to come up with an exact reset count of 9216 with a prescaler of 8.

Total votes: 0

hello,
I am a new learner,it's a good course to study,but I really want to know the for{} what is content inside
thanks

Total votes: 0

Which for{}? This thread is 24 pages long and contains a multitude of for{}s.

Regards,
Steve A.

The Board helps those that help themselves.

Total votes: 0

Can i ask for help? Im trying to run timers on my ATmega328P-PU

I want to use 8-bit Timer/Counter0 and i wrote my code using part 5 of this tutorial the last "Code" section. Unfortunately i cant get it to work. I want to simply test timer interrupt so this is what i want to achieve: Led is off on initialisation, on first interrupt it goes on (and stays on because there is no place in code where it would be toggled off/C5 set to low) so i know interrupts caused with timers are working.

Unfortunately its not working. After programming the led is off all the time. I checked connections for led (when i move that part from ISR interrupt to while() loop it works). Here is my code:

```#include
#include
#include
int main (void)
{
DDRC |= (1 << 5); // set C5 as output (initially low led off)

TCCR0A |= (1 << WGM01); // configure timer 0 for CTC mode

TCCR0B |= (1 << CS02);	// set prescaler to 1024
TCCR0B |= (1 << CS01);
TCCR0B |= (1 << CS00);

OCR0A = 179;  //interrupt every 10ms

TIMSK0 |= (1 << OCIE0A); // enable CTC interrupt

sei(); // enable global interrupt

while(1)
{

}
}

ISR(TIMER0_COMPA_vect)
{
PORTC |= (1 << 5); // set C5 high (led on)
}
```

What im missing? Im sure its something silly but i just cant get why its not working, i need another pair of eyes to have fresh look at it :/

Thank you in advance

Total votes: 0

Why do people insist on using "|=" to set registers, particularly when you want to set several bits in the same register? Do it in one line with "="

Regards,
Steve A.

The Board helps those that help themselves.

Total votes: 0

Yeah, i just wanted to break it apart to rule out any mistake in syntax, normally i do set multiple bits of same register in one line.
So yeah im still fighting with this problem

```#include
#include

int main (void)
{
DDRC |= (1 << 5); // Set LED as output
TCCR0A|=(1 << WGM01);
TCCR0B=(1 << CS02)|(1 << CS01)|(1 << CS00);
sei();
OCR0A=179;
TIMSK0|=(1 << OCIE0A);

while(1)
{
}
}

ISR(TIMER0_COMPA_vect)
{
PORTC |=(1 << 5);
}```

Its still not working. I tried using TIMER0 in overflow mode

```#include
#include

int main (void)
{
TIMSK0 |=(1<<TOIE0);
sei();
TCCR0B |= (1 << CS02);

while(1)
{
}
}

ISR(TIMER0_OVF_vect)
{
PORTC |=(1 << 5);
}```

and it worked... I just cant get that ATmega328P-PU to run the TIMER0 in CTC mode

--------------------------------------------

found it >< I shouldnt have set CS01 bit high.......... case closed

Total votes: 0

I tried this in the AS6 simulator and you are absolutely right - nothing happens - the clock does not tick. Then I noticed a drop-list saying that the clock was set to 0x07 and I wondered what that meant. So I dropped the list and this is what it said... (hopefully you see the issue!)

## Attachment(s):

Total votes: 0

Quote:
hopefully you see the issue!

Let's add some data sheet reading to that:

## Attachment(s):

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]

Total votes: 0

I have a quick question too. :)

timer1 16-bits

```	 TCCR1B = (1<<WGM12)|(1<<CS12); // enable CTS mode; 1HZ=62499 clocks=256 prescale
OCR1A = 62499;    //sets the desired count for displaying temp every one sec
TIMSK1 = (1<<OCIE1A); //Enable timer interrupt for "A" timer```

time0 8-bits

```	 TCCR0A |=(1<<WGM01);  //enable CTS mode;
TCCR0B |=(1<<CS00)|(1<<CS01);  //64 prescale
OCR0A = 249; //1000Hz or 1ms (0.001)
TIMSK0 = (1<<OCIE0A); // start timer0 "1"```

main.c

```ISR(TIMER0_COMPA_vect){
ms++;
}

ISR(TIMER1_COMPA_vect){
lcd_putint(rpm);
rpm=0;

}```

It prints ~600 for rpm value instead of 1000? Some assumptions ?

Total votes: 0

Your assumptions are based on what you think F_CPU is and hence the numeric OCR values.

Total votes: 0

I could assume the lcd code takes too long to execute. Where does rpm code from? Using ctc mode on timer1 when you should let it free run.

Total votes: 0

Quote:

It prints ~600 for rpm value instead of 1000?

So?

You've shown exactly one place (two lines) in code that references the rpm variable:

```      lcd_putint(rpm);
rpm=0;```

I.e. one line prints the current value, and the next sets it to zero. No other code shown that in any way changes the rpm variable.

How do you think anyone is going to do any fault-finding given only that?

Here is the standard advice: Post minimal but complete program that builds and runs and demostrates the problem. Report clearly what you would expect the program to do, and report just as clearly what it actually does.

If you just drop a half-arsed question here you will get half-decent answers.

Remember #1: YOU are responsible for supplying as good a question as possible - i.e. YOU should spend as much time as possible formulating the question so that we need to spend as little time as possible helping you.

Remember #2: You are in a competition for attendance here at AVRfreaks. The better, clearer, more interesting, workable or thrilling your question is - the better the chance of you getting help here. If you pose a bad question while others pose better questions, you will lose and others will get our attention.

Your call.

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]

Total votes: 0

Kartman wrote:
I could assume the lcd code takes too long to execute. Where does rpm code from? Using ctc mode on timer1 when you should let it free run.

rpm is just a variable which is being increased every 1ms (timer0) and timer1 prints its value every 1sec.
So it should print 1000 for rpm value.

The entire program is bigger, i just posted a piece of the code.

However my thoughts are why does it count the thicks for timer1 (it's real 1 sec, I used looong period of time and stopwatch to made myself sure) but it misses some thicks for timer0?

Total votes: 0

As i said, your lcd code probably takes too long. I wrote a tutorial on multi tasking. This might help you

Total votes: 0

Thanks. It seems that's what I have been looking for.

PS: Are you speaking for FreeRTOS?
Could I ask you to put a link?

Total votes: 0

Quote:
Could I ask you to put a link?

Just browse the listing for the Tutorials forum here at AVRfreaks. Locate a tutorial with 'Kartman' as author and the title containing "multitasking".

[Personally I am reluctant to supply a link since that will awaken the CAPTCHA beast.]

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]

Total votes: 0

Dean you quoted:
"Part Three - Long Timer Delays in Firmware

So far, we've learned how to use the timers in their most basic counting mode to delay a specified duration. However, we've also discovered a limitation of the timers - their maximum duration that their timer count registers can hold. We've managed to get a 1Hz delay out of a prescaled 16-bit timer with a prescale, but what if we want a delay of a minute? An hour? A week or year?"
- Dean first of all great tutorial written with passion
My question to you if you want a short delay or high frequency. Let say if my frequency target is 1MHz=1000000Hz and my Input frequency is 4MHz or 12MHz.

After applying the math i ended up with:
Time Resolution=(1/Input Freq)
=(1/1000000)=0.000001sec

Target Timer Count= [(1/Target Frequency)/(1/Timer Clock Frequency)] â€“ 1
=[(1/1000000)/(1/4000000)]-1
= [(0.000001)/(0.00000025)] â€“ 1
= [4] -1
=3

# include
int main ( void )
{
DDRB |= (1 << 0); // Set LED as output
TCCR1B |= (1 << CS10 ); // Set up timer
for (;;)
{
// Check timer value in if statement , true when count matches 1/20 of a second
//if ( TCNT1 >= 49999)
if ( TCNT1 >= 3)
{
PORTB ^= (1 << 0); // Toggle the LED
TCNT1 = 0; // Reset timer value
}
}
}

I used my digital oscilloscope and did not get frequency target only got some 23khz

Sorry if this sound stupid!

Thank

Total votes: 0

A tutorial thread is not the right place to be asking about this (it's only for adding to details of the tutorial). Anyway your question is basically:

Quote:

but what if we want a delay of a minute? An hour? A week or year?"

The answer is simply that you count compares/overflows.

Say you want to implement an RTC but you only have an 8 bit timer and at 20MHz you can't make it last longer than 13ms (20MHz/1024/256). Then what you do is put it in CTC mode and set the compare to interrupt every 10ms. Each time the interrupt occurs you increment a counter. When it reaches 100 a second has passed so you set that counter back to 0 and increment a seconds counter. When the increment of that counter takes it from 59 to 60 you set that one back to 0 and increment a minutes counter. When that one eraches the 59 to 60 increment you set that back to 0 and increment an hours counter. When that one reaches the 23 to 24 increment you set it back to 0 and increment a days counter. When that one reaches 365 to 366 you set it back to 0 and increment a year counter and so on.

Nothing stops a 10ms interrupt counting millenia.

Total votes: 0

clawson wrote:
A tutorial thread is not the right place to be asking about this (it's only for adding to details of the tutorial). Anyway your question is basically:

Quote:

but what if we want a delay of a minute? An hour? A week or year?"

The answer is simply that you count compares/overflows.

Say you want to implement an RTC but you only have an 8 bit timer and at 20MHz you can't make it last longer than 13ms (20MHz/1024/256). Then what you do is put it in CTC mode and set the compare to interrupt every 10ms. Each time the interrupt occurs you increment a counter. When it reaches 100 a second has passed so you set that counter back to 0 and increment a seconds counter. When the increment of that counter takes it from 59 to 60 you set that one back to 0 and increment a minutes counter. When that one eraches the 59 to 60 increment you set that back to 0 and increment an hours counter. When that one reaches the 23 to 24 increment you set it back to 0 and increment a days counter. When that one reaches 365 to 366 you set it back to 0 and increment a year counter and so on.

Nothing stops a 10ms interrupt counting millenia.

Hi clawson, I am sorry for asking a question in TUT. What should I do? Should start a new question?

For my question it is not about a long delay: a delay of a minute? An hour? A week or year?" but for short delay in order to generate a 1MHz at one of the pin of the MCU.

Thank

Total votes: 0

Hi clawson, I am sorry for asking a question in TUT. What should I do? Should start a new question?

For my question it is not about a long delay: a delay of a minute? An hour? A week or year?" but for short delay in order to generate a 1MHz at one of the pin of the MCU.

Thank

Total votes: 0

The way you do that is to set up a timer in CTC mode with a very low OCR value and have it toggle a pin on the compare event. I seem to remember it's possible to generate F_CPU/2 by doing that.

But really you should start a new thread in AVR Forum about all this.

Cliff (moderator).

Total votes: 0

toggle a led each 5 US if you have frequency 10MHZ using compare match mode how to calculate OCR0

Total votes: 1

Do NOT cross post - you just asked (and got answered) something almost totally identical here: https://www.avrfreaks.net/forum/...

(going to lock this)