Timers avr

Timers avr DEFAULT

AVR Timers – TIMER0

AVR SeriesHello friends! Welcome back to the second part of the AVR Timers Series. In the previous post, we have discussed the basic concepts of AVR Timers. Let me summarize it:

  • We have seen how timers are made up of registers, whose value automatically increases/decreases. Thus, the terms timer/counter are used interchangeably.
  • In AVR, there are three types of timers – TIMER0, TIMER1 and TIMER2. Of these, TIMER1 is a 16-bit timer whereas others are 8-bit timers.
  • We have seen how prescalers are used to trade duration with resolution.
  • We have also discussed how to choose an appropriate value of a prescaler.
  • And then, to finish off, we learnt about interrupts.

So, I will move towards its implementation directly. I have assumed that you have understood the concepts discussed above.

In this tutorial, we will learn to use TIMER0. Since timer is a peripheral, it can be activated by setting some bits in some registers. Instead of discussing all the registers at once, we will be discussing them as and when necessary. For those who are new to the term ‘register’, they can read about it from this page. To have an idea about AVR Peripherals, view this page (you need to scroll down a bit).

Let’s define a problem statement for us. The simplest one being the LED flasher. Let’s say, we need to flash an LED every 6 ms and we are have a CPU clock frequency of 32 kHz.

Well, I know that an LED flashing at every 6 ms will be always visible as on by our eye, but I could not find any simpler example which does not include prescalers. Take this as a demonstration.

Now, as per the following formula, with a clock frequency of 32 kHz and 8-bit counter, the maximum delay possible is of 8 ms. This is quite low (for us, but not for the MCU). Hence for a delay of 6 ms, we need a timer count of 191. This can easily be achieved with an 8-bit counter (MAX = 255).

Timer CountThus, what we need to do is quite simple. We need to keep a track of the counter value. As soon as it reaches 191, we toggle the LED value and reset the counter. For this, we need the help of the following registers.

TCNT0 Register

The Timer/Counter Register – TCNT0 is as follows:

TCNT0 Register

TCNT0 Register

This is where the uint 8-bit counter of the timer resides. The value of the counter is stored here and increases/decreases automatically. Data can be both read/written from this register.

Now we know where the counter value lies. But this register won’t be activated unless we activate the timer! Thus we need to set the timer up. How? Read on…

TCCR0 Register

The Timer/Counter Control Register – TCCR0 is as follows:

TCCR0 Register

TCCR0 Register

Right now, we will concentrate on the highlighted bits. The other bits will be discussed as and when necessary. By selecting these three Clock Select Bits, CS02:00, we set the timer up by choosing proper prescaler. The possible combinations are shown below.

Clock Select Bit Description

Clock Select Bit Description

For this problem statement, we choose No Prescaling. Ignore the bits highlighted in grey. We will be using it later in this tutorial. Thus, we initialize the counter as:

TCCR0 |= (1 << CS00);

Please note that if you do not initialize this register, all the bits will remain as zero and the timer/counter will remain stopped.

Thus now we are ready to write a code for this. To learn about I/O port operations in AVR, view this. To know about bit manipulations, view this.

 Code

#include <avr/io.h> void timer0_init() { // set up timer with no prescaling TCCR0 |= (1 << CS00); // initialize counter TCNT0 = 0; } int main(void) { // connect led to pin PC0 DDRC |= (1 << 0); // initialize timer timer0_init(); // loop forever while(1) { // check if the timer count reaches 191 if (TCNT0 >= 191) { PORTC ^= (1 << 0); // toggles the led TCNT0 = 0; // reset counter } } }

I guess the code is pretty simple and straightforward. It doesn’t need any explanation. Or maybe one thing needs explanation. In the if statement, I have used

if (TCNT0 >= 191)

instead of

if (TCNT0 == 191)

This is because sometimes due to missed compares or unexpected increment, this condition may never be true. Thus to remain on the safer side, we use ‘>=’ instead of ‘==’.

Now let’s change the above problem statement to the following. We need to flash an LED every 8 ms and we have an XTAL of 16 MHz. Well, 8 ms is still low, but it’s good enough for the following illustration.

Methodology – Using Prescalers

Now since the CPU clock frequency is 16 MHz, the maximum time delay that it can measure is 16 μs! But 8 ms (which is quite a small duration for us) is way much larger. So what do we do? Yes, you guessed right (I hope so ;))! We use a prescaler in order to trade duration with resolution. Now the following table summarizes the results of using different prescalers 8, 64, 256 and 1024. See previous tutorial for details.

Prescaler Selection

Prescaler Selection

From the values of the counter, we can easily rule out the top three prescalers as they are above the maximum limit of an 8-bit counter (which is 255). Thus we use a prescaler of 1024. Now refer to the descriptions of clock select bits as shown in the TCCR0 register. Have a look at the selection highlighted in grey. This implements a prescaler of 1024. The rest remains the same. Moving to the coding part, we simply change the initialize function and the compare value. The rest remains the same.

Code

#include <avr/io.h> void timer0_init() { // set up timer with prescaler = 1024 TCCR0 |= (1 << CS02)|(1 << CS00); // initialize counter TCNT0 = 0; } int main(void) { // connect led to pin PC0 DDRC |= (1 << 0); // initialize timer timer0_init(); // loop forever while(1) { // check if the timer count reaches 124 if (TCNT0 >= 124) { PORTC ^= (1 << 0); // toggles the led TCNT0 = 0; // reset counter } } }

Now let’s change the problem statement to something you can actually see! Let’s flash an LED every 50 ms (you can surely see the LED flashing this time ;)). We have an XTAL of 16 MHz.

Methodology – Using Interrupts

So now, we have to flash the LED every 50 ms. With CPU frequency 16 MHz, even a maximum delay of 16.384 ms can be achieved using a 1024 prescaler. So what do we do now? Well, we use interrupts.

The concept here is that the hardware generates an interrupt every time the timer overflows. Since the required delay is greater than the maximum possible delay, obviously the timer will overflow. And whenever the timer overflows, an interrupt is fired. Now the question is how many times should the interrupt be fired?

For this, let’s do some calculation. Let’s choose a prescaler, say 256. Thus, as per the calculations, it should take 4.096 ms for the timer to overflow. Now as soon as the timer overflows, an interrupt is fired and an Interrupt Service Routine (ISR) is executed. Now,

50 ms ÷ 4.096 ms = 12.207

Thus, in simple terms, by the time the timer has overflown 12 times, 49.152 ms would have passed. After that, when the timer undergoes 13th iteration, it would achieve a delay of 50 ms. Thus, in the 13th iteration, we need a delay of 50 – 49.152 = 0.848 ms. At a frequency of 62.5 kHz (prescaler = 256), each tick takes 0.016 ms. Thus to achieve a delay of 0.848 ms, it would require 53 ticks. Thus, in the 13th iteration, we only allow the timer to count up to 53, and then reset it. All this can be achieved in the ISR as follows:

// global variable to count the number of overflows volatile uint8_t tot_overflow; // TIMER0 overflow interrupt service routine // called whenever TCNT0 overflows ISR(TIMER0_OVF_vect) { // keep a track of number of overflows tot_overflow++; } int main(void) { // connect led to pin PC0 DDRC |= (1 << 0); // initialize timer timer0_init(); // loop forever while(1) { // check if no. of overflows = 12 if (tot_overflow >= 12) // NOTE: '>=' is used { // check if the timer count reaches 53 if (TCNT0 >= 53) { PORTC ^= (1 << 0); // toggles the led TCNT0 = 0; // reset counter tot_overflow = 0; // reset overflow counter } } } }

Please note that the code is not yet ready. Not until you learn how to enable the interrupt feature. For this, you should be aware of the following registers.

TIMSK Register

The Timer/Counter Interrupt Mask – TIMSK Register is as follows. It is a common register for all the three timers. For TIMER0, bits 1 and 0 are allotted. Right now, we are interested in the 0th bit TOIE0. Setting this bit to ‘1’ enables the TIMER0 overflow interrupt.

TIMSK Register

TIMSK Register

TIFR Register

The Timer/Counter Interrupt Flag Register– TIFR is as follows. Even though we are not using it in our code, you should be aware of it.

TIFR Register

TIFR Register

This is also a register shared by all the timers. Even here, bits 1 and 0 are allotted for TIMER0. At present we are interested in the 0th bit TOV0 bit. This bit is set (one) whenever TIMER0 overflows. This bit is reset (zero) whenever the Interrupt Service Routine (ISR) is executed. If there is no ISR to execute, we can clear it manually by writing one to it.

In this example, since we are using ISR, we need not care about this bit (thus this register as a whole).

Enabling Global Interrupts

In the AVRs, there’s only one single bit which handles all the interrupts. Thus, to enable it, we need to enable the global interrupts. This is done by calling a function named sei(). Don’t worry much about it, we simply need to call it once, that’s all.

Final Code

#include <avr/io.h> #include <avr/interrupt.h> // global variable to count the number of overflows volatile uint8_t tot_overflow; // initialize timer, interrupt and variable void timer0_init() { // set up timer with prescaler = 256 TCCR0 |= (1 << CS02); // initialize counter TCNT0 = 0; // enable overflow interrupt TIMSK |= (1 << TOIE0); // enable global interrupts sei(); // initialize overflow counter variable tot_overflow = 0; } // TIMER0 overflow interrupt service routine // called whenever TCNT0 overflows ISR(TIMER0_OVF_vect) { // keep a track of number of overflows tot_overflow++; } int main(void) { // connect led to pin PC0 DDRC |= (1 << 0); // initialize timer timer0_init(); // loop forever while(1) { // check if no. of overflows = 12 if (tot_overflow >= 12) // NOTE: '>=' is used { // check if the timer count reaches 53 if (TCNT0 >= 53) { PORTC ^= (1 << 0); // toggles the led TCNT0 = 0; // reset counter tot_overflow = 0; // reset overflow counter } } } }

So friends, we are done with the basics of TIMER0. What remains to be discussed in it are CTC Mode and PWM Mode. We will be discussing them in upcoming posts. In the next post, we will discuss how to apply the same concepts to use TIMER1, and then to TIMER2.

Till then, enjoy flashing LEDs at different intervals! ;)

And please comment below to encourage me to keep on updating interesting stuffs! :) Also you can grab the RSS Feeds or subscribe to my blog to stay updated!

Thank You!

Like this:

LikeLoading...

Related

Sours: https://maxembedded.com/2011/06/avr-timers-timer0/

For an updated version of this tutorial in PDF format, please see this page of my website.

Newbie's Guide to AVR Timers
(C) Dean Camera, 2007

At last! Yet another tutorial, this one covering a topic which is the main source of frustration to those new with AVRs; timers. What are they, and what can they do for us?

Introduction - The AVR Timer

The timer systems on the AVR series of Microcontrollers are complex beasts. They have a myriad of uses ranging from simple delay intervals right up to complex PWM (more on this later) generation. However, despite the surface complexity, the function of the timer subsystem can be condensed into one obvious function: to time.

We use timers every day - the most simple one can be found on your wrist. A simple clock will time the seconds, minutes and hours elapsed in a given day - or in the case of a twelve hour clock, since the last half-day. AVR timers do a similar job, measuring a given time interval.

The AVR timers are very useful as they can run asynchronous to the main AVR core. This is a fancy way of saying that the timers are separate circuits on the AVR chip which can run independent of the main program, interacting via the control and count registers, and the timer interrupts. Timers can be configured to produce outputs directly to pre-determined pins, reducing the processing load on the AVR core.

One thing that trips those new to the AVR timer is the clock source. Like all digital systems, the timer requires a clock in order to function. As each clock pulse increments the timer's counter by one, the timer measures intervals in periods of one on the input frequency:

Timer Resolution = (1 / Input Frequency)

This means the smallest amount of time the timer can measure is one period of the incoming clock signal. For instance, if we supply a 100Hz signal to a timer, our period becomes:

Timer Resolution = (1 / Input Frequency) Timer Resolution = (1 / 100) Timer Resolution = .01 seconds

For the above example, our period becomes .01 seconds - so our timer will measure in multiples of this. If we measure a delay to be 45 timer periods, then our total delay will be 45 times .01 seconds, or .45 seconds.

For this tutorial, I will assume the target to be a MEGA16, running at at 1MHz clock. This is a nicely featured AVR containing certain timer functionality we'll need later on. As modern AVRs come running off their internal ~1MHz RC oscillator by default, you can use this without a problem (although do keep in mind the resultant timing measurements will be slightly incorrect due to the RC frequency tolerance).

In the sections dealing with toggling a LED, it is assumed to be connected to PORTB, bit 0 of your chosen AVR (pin 1 of DIP AVRMEGA16).

To start off, we will deal with basic timer functionality and move on from there.

Part One - Timers running at Fcpu

We'll start with a simple example. We'll create a simple program to flash a LED at about 20Hz. Simple, right?

First, let's look at the pseudo-code required to drive this example:

Set up LED hardware Set up timer WHILE forever IF timer value IS EQUAL TO OR MORE THAN 1/20 sec THEN Reset counter Toggle LED END IF END WHILE

Very simple. We're just starting out, so we'll use the polled method of determining the elapsed time - we'll put in an IF statement in our code to check the current timer value, and act on it once it reaches (or exceeds) a certain value. Before we start on the timer stuff, let's create the skeleton of our project:

#include

Extremely simple. I'm going to assume you are familiar with the basics of setting up AVR ports as well as bit manipulation (if you're uncertain about the latter, refer to this excellent tutorial). With that in mind, I'll add in the LED-related code and add in the IF statement:

#include

Now we need to start dealing with the timer. We want to do nothing more than start it at 1MHz, then check its value later on to see how much time has elapsed. We need to deviate for a second and learn a little about how the timer works in its most basic mode.

The AVR timer circuits come in two different widths, 8 and 16 bit. While the capabilities of the two timer types differ, at the most basic level (simple counting), the only difference is the maximum amount of time the timer can count to before overflowing and resetting back to zero. Those familiar with C will know that an unsigned eight bit value can store a value from 0 to (2^8 - 1), or 255, before running out of bits to use and becoming zero again. Similarly, an unsigned 16 bit value may store a value from 0 to (2^16 - 1), or 65535 before doing the same.

As the name suggests, an 8 bit timer stores its value as an eight bit value in its count register, while the 16 bit timer stores its current count value in a pair of eight bit registers. Each advancement of the counter register for any AVR timer indicates that one timer period has elapsed.

Our project needs a fairly long delay, of 1/20 of a second. That's quite short to us humans, but to a microcontroller capable of millions of instructions per second it's a long time indeed!

Our timer will be running at the same clock speed as the AVR core to start with, so we know that the frequency is 1MHz. One Megahertz is 1/1000000 of a second, so for each clock of the timer only one millionth of a second has elapsed! Our target is 1/20 of a second, so let's calculate the number of timer periods needed to reach this delay:

Target Timer Count = (1 / Target Frequency) / (1 / Timer Clock Frequency) - 1 = (1 / 20) / (1 / 1000000) - 1 = .05 / 0.000001 - 1 = 50000 - 1 = 49999

So running at 1MHz, our timer needs to count to 49999 before 1/20th of a second has elapsed - the normal calculated value is decremented by one, as the 0th count of the timer still takes one tick. That's a very large value - too large for an 8 bit value! We'll need to use the 16 bit timer 1 instead.

Firstly, we need to start the timer at the top of our main routine, so that it will start counting. To do this, we need to supply the timer with a clock; as soon as it is clocked it will begin counting in parallel with the AVR's CPU core (this is called synchronous operation). To supply a clock of Fcpu to the timer 1 circuits we need to set the CS10 bit (which selects a Fcpu prescale of 1 - more on that later) in the TCCR1B, the Timer 1 Control Register B.

#include

Now, with only one line of code, we've started the hardware timer 1 counting at 1MHz - the same speed as our AVR. It will now happily continue counting independently of our AVR. However, at the moment it isn't very useful, we still need to do something with it!

We want to check the timer's counter value to see if it reaches 1/20 of a second, or a value of 49999 at 1MHz as we previously calculated. The current timer value for timer 1 is available in the special 16-bit register, TCNT1. In actual fact, the value is in two 8-bit pair registers TCNT1H (for the high byte) and TCNT1L (for the low byte), however the C library implementation we're using helpfully hides this fact from us.

Let's now add in our check to our code - it's as simple as testing the value of TCNT1 and comparing against our wanted value, 49999. To prevent against missed compares (where the timer updates twice between checks so our code never sees the correct value), we use the equal to or more than operator, ">=".

#include

Great! We've only got one more line of code to write, to reset the timer value. We already know the current value is accessed via the TCNT1 register for Timer 1, and since this is a read/write register, we can just write the value 0 to it once our required value is reached to rest it.

#include

And there we have it! We've just created a very basic program that will toggle our LED every 1/20 of a second at a 1MHz clock. Testing it out on physical hardware should show the LED being dimmer than normal (due to it being pulsed quickly). Good eyesight might reveal the LED's very fast flickering.

Next, we'll learn about the prescaler so we can try to slow things down a bit.

Part Two - Prescaled Timers

In part one of this tutorial we learned how to set up our 16-bit timer 1 for a 1/20 second delay. This short (to us humans) delay is actually quite long to our AVR - 50,000 cycles in fact at 1MHz. Notice that Timer 1 can only hold a value of 0-65535 - and we've almost reached that! What do we do if we want a longer delay?

One of the easiest things we can do is to use the timer's prescaler, to trade resolution for duration. The timer prescaler is a piece of timer circuitry which allows us to divide up the incoming clock signal by a power of 2, reducing the resolution (as we can only count in 2^n cycle blocks) but giving us a longer timer range.

Let's try to prescale down our Fcpu clock so we can reduce the timer value and reduce our delay down to a nice 1Hz. The Timer 1 prescaler on the MEGA16 has divide values of 1, 8, 64, 256 and 1024 - so let's re-do our calculations and see if we can find an exact value.

Our calculations for our new timer value are exactly the same as before, except we now have a new prescaler term. We'll look at our minimum resolution for each first:

Timer Resolution = (1 / (Input Frequency / Prescale)) = (Prescale / Input Frequency)

For a 1MHz clock, we can construct a table of resolutions using the available prescaler values and a Fcpu of 1MHz.

Prescaler Value | Resolution @ 1MHz 1 | 1uS 8 | 8uS 64 | 64uS 256 | 256uS 1024 | 1024uS

If you recall our equation for calculating the timer value for a particular delay in part 1 of this tutorial, you'll remember it is the following:

Target Timer Count = (1 / Target Frequency) / (1 / Timer Clock Frequency) - 1

However, as we've just altered the prescaler term, the latter half is now different. Substituting in our new resolution equation from above we get:

Target Timer Count = (1 / Target Frequency) / (Prescale / Input Frequency) - 1

Or rearranged:

Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1

Now, we want to see if there is a prescaler value which will give an *exact* delay of 1Hz. One Hertz is equal to one cycle per second, so we want our compare value to be one second long, or 1000000uS. Let's divide that by each of our resolutions and put the results in a different table:

Prescaler Value | Target Timer Count 1 | 999999 8 | 125000 64 | 15624 256 | 3905.25 1024 | 975.5625

The results are interesting. Of the available prescaler values, we can immediately discount 256 and 1024 - they do not evenly divide into our wanted delay period. They are of course usable, but due to the rounding of the timer count value the resultant delay will be slightly over or under our needed delay. That leaves us with three possible prescales; 1, 8 and 64.

Our next task is to remove the values that aren't possible. On an 8-bit timer, that means discounting values of more than (( 2 ^ 8 ) - 1), or 255, as the value won't fit into the timer's 8-bit count register. For our 16-bit timer, we have a larger range of 0 to ((2 ^ 16) - 1), or 65535. Only one of our prescaler values satisfies this requirement - a prescale of 64 - as the other two possibilities require a timer count value of more bits than our largest 16-bit timer is capable of storing.

Let's go back to our original timer program and modify it to compare against our new value of 15624, which we've found to be 1 second at a prescale of 64 and a Fcpu of 1MHz:

#include

Note I've removed the timer setup line, as it is no longer valid. We want to set up our timer to run at Fcpu/64 now. To do this, we need to look at the datasheet of the MEGA16 to see which bits need to be set in which control registers.

Checking indicates that we need to set both the CS10 and CS11 prescaler bits in TCCR1B, so let's add that to our program:

#include

Compile it, and we're done! Remembering that our timer runs as soon as it gets a clock source, our program will now work, flashing the LED at a frequency of 1Hz.

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?

The answer is to create a sort of prescaler of our own in software. By making the hardware timer count to a known delay - say the 1Hz we created earlier - we can increment a variable each time that period is reached, and only act after the counter is reached a certain value. Let's pseudocode this so we can get a better understanding of what we want to do:

Set up LED hardware Set up timer Initialise counter to 0 WHILE forever IF timer value IS EQUAL TO 1 sec THEN Increment counter Reset timer IF counter value IS EQUAL TO 60 seconds THEN Toggle LED END IF END IF END WHILE

The above pseudocode will build on our last experiment - a timer with a one second count - to produce a long delay of one minute (60 seconds). It's very simple to implement - all we need extra to our last example is an extra IF statement, and a few variable-related lines. First off, we'll re-cap with our complete code as it stands at the moment:

#include

We need some code to create and initialise a new counter variable to 0, then increment it when the counter reaches one second as our pseudocode states. We also need to add in a test to see if our new variable reaches the value of 60, indicating that one minute has elapsed.

#include

Now that we have our new program's structure, replacing the TODOs becomes very simple. We want a target count of 60, which is well within the range of an unsigned integer variable, so we'll make our counter variable of type unsigned integer. The rest of the code is extremely simple, so I'll add it all in at once:

#include

Compile and run, and the LED should toggle once per minute. By extending this technique, we can produce delays of an arbitrary duration. One point of interest is to note that any timing errors compound - so if the timer input frequency is 1.1MHz rather than 1.0MHz our one minute timer will be sixty times that small error out in duration. For this reason it is important to ensure that the timer's clock is as accurate as possible, to reduce long-term errors as much as possible.

Part Four - The CTC Timer Mode

Up until now, we've been dealing with the timers in a very basic way - starting them counting, then comparing in our main routine against a wanted value. This is rather inefficient - we waste cycles checking the timer's value every time the loop runs, and slightly inaccurate (as the timer may pass our wanted compare value slightly while processing the loop). What if there was a better way?

Well, there is. The AVR timers usually incorporate a special function mode called "Clear on Timer Compare", or CTC for short. The CTC operating mode does in hardware what we've previously experimented in software; it compares in hardware the current timer value against the wanted value, and when the wanted value is reached a flag in a status register is set and the timer's value reset.

This is extremely handy; because the comparing is done in hardware, all we have to worry about is checking the flag to determine when to execute our LED toggling - much faster than comparing bytes or (in the case of the 16-bit timer) several bytes.

CTC mode is very straightforward. Before we look into the implementation, let's pseudocode what we want to do.

Set up LED hardware Set up timer in CTC mode Set timer compare value to one second WHILE forever IF CTC flag IS EQUAL TO 1 THEN Toggle LED Clear CTC flag END IF END WHILE

Very short, and very simple. Note that the name of the mode is Clear on timer compare - the timer's value will automatically reset each time the compare value is reached, so we only need to clear the flag when the delay is reached. This set-and-forget system is very handy, as once the timer is configured and started we don't need to do anything other than check and clear its status registers.

Now then, we'll grab our previous example, modifying it to fit with our new pseudocode:

#include

Now, we need to flesh out the skeleton code we have. First up we need to configure our timer for CTC mode. As you might be able to guess, we want to configure our timer, thus the bits we want will be located in the timer's Control registers. The table to look for is the one titled "Waveform Generation Mode Bit Description", and is located in timer Control register descriptions for each timer. This table indicates all the possible timer modes, the bits required to set the timer to use those modes, and the conditions each mode reacts to.

You should note that our previous examples have ignored this table altogether, allowing it to use its default value of all mode bits set to zero. Looking at the table we can see that this setup corresponds to the "Normal" timer mode. We want to use the CTC mode of the timer, so let's look for a combination of control bits that will give us this mode.

Interestingly, it seems that two different combinations in Timer 1 of the MEGA16 will give us the same CTC behaviour we desire. Looking to the right of the table, we can see that the "Top" value (that is, the maximum timer value for the mode, which corresponds to the compare value in CTC mode) uses different registers for each. Both modes behave in the same manner for our purposes and differ only by the register used to store the compare value, so we'll go with the first.

The table says that for this mode, only bit WGM12 needs to be set. It also says that the register used for the compare value is named OCR1A.

Looking at the timer control registers (TCCR1A and TCCR1B) you should notice that the WGM1x bits - used to configure the timer's mode - are spread out over both registers. This is a small pain as you need to find out which bits are in which register, but once found setting up the timer becomes very easy. In fact, as we only have one bit to set - WGM12 - our task is even easier. The MEGA16's datasheet says that WGM12 is located in the TCCR1B register, so we need to set that.

#include

The second task for this experiment is to set the compare value - the value that will reset the timer and set the CTC flag when reached by the timer. We know from the datasheet that the register for this is OCR1A for the MEGA16 in the first CTC timer mode, so all we need is a compare value. From our previous experiment we calculated that 1Hz at 1MHz with a prescaler of 64 needs a compare value of 15624, so let's go with that.

#include

There, almost done already! Last thing we need is a way of checking to see if the compare has occurred, and a way to clear the flag once its been set. The place to look for the compare flags is in the timer's Interrupt Flag register - an odd place it seems, but the reason will become clear in the next section dealing with timer interrupts. The MEGA16's Timer 1 interrupt flags are located in the combined register TIFR, and the flag we are interested in is the "Output Compare A Match" flag, OCF1A. Note the "A" on the end; Timer 1 on the MEGA16 has two CTC channels (named channel A and channel B), which can work independently. We're only using channel A for this experiment.

Checking for a CTC event involves checking the OCF1A flag in this register. That's easy - but what about clearing it? The datasheet includes an interesting note on the subject:

Quote:

...OCF1A can be cleared by writing a logic 1 to its bit location

Very strange indeed! In order to clear the CTC flag, we actually need to set it - even though it's already set. Due to some magic circuitry inside the AVR, writing a 1 to the flag when its set will actually cause it to clear itself. This is an interesting behaviour, and is the same across all the interrupt bits.

Despite that, we can now add in our last lines of code to get a working example:

#include

Note that when clearing the OCF1A flag, we assign its value to the TIFR register. This is because it will assign a logic one to the flag's position (clearing it) but also because as writing zeros to the other flags won't affect them, we can go ahead and use the smaller (codesize-wise) direct assignment, rather than ORing the register to form a read/modify/write sequence. This is also beneficial because it prevents the compiler from writing logic one to the other flags if they were already set via the read/modify/write, which would clear unwanted flags.

And there we have it, a working 1Hz LED flasher using the CTC timer mode!

Part Five - CTC Mode using Interrupts

Important: The interface for defining and working with Interrupts has changed in the more recent versions of WinAVR - please make sure you've updated your installation to the latest version if you encounter errors relating to the unknown macro "ISR".

For all our previous experiments, we've been using a looped test in our main code to determine when to execute the timer action code. That's fine - but what if we want to shift the responsibility of choosing when to execute the timer code to the AVR hardware instead? To do this, we need to look at the timer interrupts.

Interrupts are events that when enabled, cause the AVR to execute a special routine (called an Interrupt Service Routine, or ISR for short) when the interrupt conditions are met. These interrupts can happen at any time and when executing the main routine is paused while the ISR executes, the main routine continues until the next interrupt. This is useful for us, as it means we can eliminate the need to keep checking the timer value and just respond to its interrupt events instead.

The AVR timers can have several different Interrupts - typically Overflow, Compare and Capture. Overflow occurs when the timer's value rolls past it's maximum and back to zero (for an 8 bit timer, that's when it counts past 11111111 in binary and resets back to 00000000). However, for this section we'll deal with the Compare interrupt, which occurs in CTC mode when the compare value is reached.

Again, we'll pseudocode this to start with:

Set up LED hardware Set up timer in CTC mode Enable CTC interrupt Enable global interrupts Set timer compare value to one second WHILE forever END WHILE ISR Timer Compare Toggle LED END ISR

We can start off this by working with our skeleton main code, used in previous examples. I'll skip the details on the parts already discussed in previous sections.

#include

Note how it's a modified version of the non-interrupt driven CTC example covered in the last section. All we need to do is tell the timer to run the compare ISR we define when it counts up to our compare value, rather then us polling the compare match flag in our main routine loop.

We'll start with creating the ISR first, as that's quite simple. In AVR-GCC - specifically, the avr-libc Standard C Library that comes with it - the header file for dealing with interrupts is called (unsurprisingly) "interrupt.h" and is located in the "avr" subdirectory. We need to include this at the top of our program underneath our include to the IO header file. The top of our code should look like this:

#include

This gives us access to the API for dealing with interrupts. We want to create an ISR for the Timer 1 Compare Match event. The syntax for defining an ISR body in AVRGCC is:

ISR(VectorName_vect) { // Code to execute on ISR fire here }

Where "VectorName" is the name of the ISR vector which our defined ISR handles. The place to go to find this name is the "Interrupt" section of the datasheet, which lists the symbolic names for all the ISR vectors that the chosen AVR supports. When writing the vector name into GCC, replace all spaces with underscores, and append "_vect" to the end of the vector's name.

Like in part four we are still dealing with Channel A Compare of Timer 1, so we want the vector named "TIMER1 COMPA". In GCC this is called "TIMER1_COMPA_vect", after performing the transformations outlined in the last paragraph. Once the ISR is defined, we can go ahead and write out it's body, adding the LED toggling code.

#include

Notice how we don't clear the CTC event flag like in part four - this is automatically cleared by the AVR hardware once the ISR fires. Neat, isn't it!

Running the code so far won't yield any results. This is because although we have our ISR all ready to handle the CTC event, we haven't enabled it! We need to do two things; enable the "TIMER1 COMPA" interrupt specifically, and turn on interrupt handling on our AVR.

The way to turn on our specific interrupt is to look into the second interrupt-related register for our timer, TIMSK. This is the Timer Interrupt Mask register, which turns on and off ISRs to handle specific timer events. Note that on the MEGA16 this single register contains the enable bits for all the timer interrupts for all the available timers. We're only interested in the Timer 1 Compare A Match interrupt enable bit, which we can see listed as being called OCIE1A (Output Compare Interrupt Enable, channel A).

By setting that bit we instruct the timer to execute our ISR upon compare match with our specified compare value. Let's put that line into our program's code and see how it all looks.

#include

Only one more thing to do - enable global interrupts. The AVR microcontrollers have a single control bit which turns on and off interrupt handling functionality. This is used in pieces of code where interrupt handling is not desired, or to disable interrupts while an ISR is already being executed. The latter is done automatically for us, so all we need to do is turn on the bit at the start of our code, and our compare interrupt will start to work.

The command to do this is called "sei" in the avr-libc library that ships with WinAVR, and is named to correspond with the assembly instruction which does the same for AVRs (the SEI instruction). That's irrelevant however, as we just need to call the command in our code.

#include

And our example is finished! Running this will give a nice 1Hz LED flashing, using the timer's event interrupts. The nice thing is that the timer operation is now completely handled for us in hardware - once set up, we just need to react to the events we've configured. Notice that our main loop is now empty; if this is the case you may put sleep commands inside the main loop to save power between compares.

Part Six - Pure Hardware CTC

You probably think by now that we've improved our example as much as possible - after all, what more improvements are there to make? Well, it's time to finish of the CTC topic by looking at the hardware outputs.

All AVRs' pins have alternative hardware functions. These functions (currently non re-routable) when activated interface the IO pins directly to the AVR's internal hardware - for instance the Tx/Rx alternative functions which are the direct interface to the AVR's USART subsystem. Alternative pin functions can be very useful; as they can be internally connected straight to a hardware subsystem, the maximum possible performance can be achieved.

In this section, we'll be looking at the Compare Output settings of the AVR timer.

Looking at the timer 1 control registers, we can see a few pairs of bits we've previously ignored, called (for timer 1) COM1A1/COM1A0 and COM1B1/COM1B0. Bonus points to anyone who's linked the "A" and "B" parts of the bit names to the timer compare channels - you're spot on.

These bits allow us to control the hardware behaviour when a compare occurs. Instead of firing an interrupt, the hardware can be configured to set, clear or toggle the OCxy (where "x" is the timer number, "y" is the channel letter for timers with more than one channel) hardware pins when a compare occurs. We can use the toggle function with our LED flasher, so that the hardware toggles the LED's state for us automatically, making it a true set-and-forget operation.

Before we do anything else, let's work out which pins of our MEGA16 are linked to the Compare Output hardware - we want the pins with alternative functions starting with "OC". On our PDIP package version, that maps to:

Quote:

PB3 = OC0
PD4 = OC1B
PD5 = OC1A

So timer 0 has one Compare Output channel, while timer 1 has two (channels A and B) as we've already discovered. As always we'll just deal with Channel A in our example.

Now we have a problem. All the previous chapters have assumed the LED is attached to PORTB, bit 0 - but we'll have to move it for this chapter. As stated above the alternative functions cannot be moved to another pin, so we must move moses...I mean, our LED, to the pin with the required alternative function.

Timer 1 Channel A's Compare Output is located on PD5, so move the LED there for the rest of this example. Now, let's psudocode:

Set up LED hardware Set up timer in CTC mode Enable timer 1 Compare Output channel A in toggle mode Set timer compare value to one second WHILE forever END WHILE

Amazing how simple it is, isn't it! Well, we can already fill in almost all of this:

#include

All we need is to configure the timer so that it'll toggle our channel A output each time the timer value is equal to our compare value. The datasheet has several descriptions for the functionality of the COM1Ax and COM1Bx bits, so we need to find the table corresponding to the mode we're using the timer in.

CTC mode isn't listed - instead the appropriate table is listed as "Compare Output mode, Non PWM". PWM stands for "Pulse Width Modulation", and will be covered later on in this tutorial. For now, it is sufficient to know that the CTC mode is not a form of PWM and thus the non-PWM bit description table is the one we're looking for.

To make the channel A Compare Output pin toggle on each compare, the datasheet says we need to set bit COM1A0 in TCCR1A. That's our missing line - let's add it in!

#include

Simple, isn't it! We've now created the simplest (code-wise) LED flasher possible using pure hardware functionality. Running this will cause the LED to flash at 1Hz, without any code other than the timer initialization!

Part Seven - The Overflow Event

Well, now that we've had fun creating a LED flasher via a variety of software and hardware CTC methods, we'll move on to one last LED flashing program. This time we'll be using a different Timer event to manage the toggling of the LED - the overflow.

As previously stated, timers store their values into internal 8 or 16 bit registers, depending on the size of the timer being used. These registers can only store a finite number of values, resulting in the need to manage the timer (via prescaling, software extention, etc) so that the interval to be measured fits within the range of the chosen timer.

However, what has not been discussed yet is what happens when the range of the timer is exceeded. Does the AVR explode? Does the application crash? Does the timer automatically stop?

The answer is simple, if rather boring. In the event of the timer register exceeding its capacity, it will automatically roll around back to zero and keep counting. When this occurs, we say that the timer has "overflowed".

When an overflow occurs, a bit is set in one of the timer status registers to indicate to the main application that the event has occured. Just like with the CTC hardware, there is also a corresponding bit which can enable an interrupt to be fired each time the timer resets back to zero.

So why would we need the overflow interrupt? Well, I leave that as an excersize to the reader. However, we can demonstrate it here in this tutorial - via another LED flasher, of course.

Calculating the frequency of the flashing is a little different to our previous examples, as now we have to calculate in reverse (to find the frequency from the timer count and timer resolution rather than the timer count from a known frequency and timer resolution). We'll still be working with our 16-bit timer 1 for this example, to be consistent with previous chapters.

Let's go back to our one of the timer equations we used back in chapter 2:

Target Timer Count = (1 / Target Frequency) / (Prescale / Input Frequency) - 1

We want to determine the Target Frequency from the other two variables, so let's rearrange:

(Target Timer Count + 1) * (Prescale / Input Frequency) = (1 / Target Frequency)

And swap the left and right hand sides to get it into a conventional form:

(1 / Target Frequency) = (Target Timer Count + 1) * (Prescale / Input Frequency)

Since we know that for the overflow equation, the "Target Timer Count" becomes the maximum value that can be held by the timer's count register, plus one (as the overflow occurs after the count rolls over from the maximum back to zero). The formula for the maximum value that can be held in a number of bits is:

Max Value = (2 ^ Bits) - 1

But we want one more than that to get the number of timer counts until an overflow occurs:

Counts Until Overflow = (2 ^ Bits)

Change "Max Value" to the more appropriate "Target Timer Count" in the first timer equation:

(1 / Target Frequency) = Counts Until Overflow * (Prescale / Input Frequency)

And substitute in the formula for the counts until overflow to get the timer period equation. Since frequency is just the inverse of period, we can also work out the frequencies of each duration as well:

Target Period = (1 / Target Frequency)
Target Period = ((2 ^ Bits) * (Prescale / Input Frequency)

Which is a bit complex, but such is life. Now's the fun part - we can now work out the overflow frequencies and periods for our 16-bit Timer 1 running at different prescales of our AVR's 1MHz system clock:

Target Period = ((2 ^ 16) * (Prescale / 1000000)
Prescaler Value | Overflow Frequency | Overflow period 1 | 15.259 Hz | 65.5 ms 8 | 1.907 Hz | 0.524 s 64 | .2384 Hz | 4.195 s 256 | .0596 Hz | 16.78 s 1024 | .0149 Hz | 67.11 s

Note how our frequency decreases (and period increases) as our prescaler increases, as it should. Because we have a reasonably slow main system clock, and a large timer count register, we end up with frequencies that are easy to see with the naked eye (with the exception of the case where no prescaler is used). Unlike the CTC method however, we are limited to the frequencies above and cannot change them short of using a smaller timer, different prescaler or different system clock speed - we lose the precision control that the CTC modes give us.

For this example, we'll use a prescaler of 8, to give a 1.8Hz flashing frequency, and a period of about half a second.

Almost time to get into the code implementation. But first, pseudocode! I'm going to extrapolate on the preceding chapters and jump straight into the ISR-powered example, rather than begin with a polled example. It works in the same manner as previous polled experiments, except for the testing of the overflow bit rather than the CTC bit.

Set up LED hardware Set up timer overflow ISR Start timer with a prescale of 8 WHILE forever END WHILE ISR Timer Overflow Toggle LED END ISR

Let's get started. As always, we'll begin with the skeleton program:

#include

Let's begin with filling in the bits we can already do. The ISR code is easy - we can use the same ISR as part five, except we'll be changing the compare vector to the overflow vector of timer 1.

Looking in the MEGA16 datasheet, the overflow interrupt for timer 1 is obvious - it's listed as "TIMER1 OVF" in the Interrupts chapter. Just like in part five, we need to replace the spaces in the vector name with underscores, and add the "_vect" suffix to the end.

We can also fill in the "Enable global interrupts" line, as that is identical to previous chapters and is just the "sei()" command from the

#include

Next, we need to figure out how to enable the overflow vector, so that our ISR is run each timer the overflow occurs. The datasheet's 16-bit Timer/Counter section comes to our rescue again, indicating that it is the bit named "TOIE1" located in the Timer 1 Interrupt Mask register, TIMSK:

#include

The last thing we need to do, is start the timer with a prescaler of 8. This should be easy for you to do - if not, refer back to chapter 2.

The MEGA16 Datasheet, Timer 1 section tells us that for a timer running with a prescaler of 8, we need to start it with the bit CS11 set in the control register TCCR1B. Adding that to our code finishes our simple program:

#include

All done! This simple program will cause the LED to toggle each time the overflow occurs and serves as a practical use of the overflow interrupt.

Part Eight - Overflow as CTC

One neat application of the overflow event is for creating a CTC timer on AVRs which don't support true hardware CTC. It's not as neat as the pure hardware CTC discussed in part six, but faster than the pure software CTC discussed in part two.

CTC works by having a fixed BOTTOM value - that's the timer's minimum value - of zero, and a variable TOP value, the value at which resets the timer and fires the event. However, with the overflow event we seemingly have a fixed BOTTOM of again zero, and a fixed TOP of the maximum timer's value. Not so - with a small trick we can adjust the BOTTOM value to give us the equivelent of a CTC implementation standing on it's head.

This tecnique is called timer reloading. When configured, we preload the timer's count register (which is both readable and writeable) with a value above zero. This shortens the time interval before the next overflow event, although only for a single overflow. We can get around that by again reloading the timer's value to our non-zero value inside the overflow event for a hybrid software/hardware CTC.

Psuedocode time!

Set up LED hardware Set up timer overflow ISR Load timer count register with a precalculated value Start timer with a prescale of 8 WHILE forever END WHILE ISR Timer Overflow Toggle LED Reload timer count register with same precalculated value END ISR

Let's examine the maths again. From part two, we know that the formula for determining the number of timer clock cycles needed for a given delay is:

Target Timer Count = (Input Frequency / Prescale) / Target Frequency

Which works for a fixed BOTTOM of zero, and a variable TOP. We've got the "upside-down" implementation of a fixed top of ((2 ^ Bits) - 1) and a variable BOTTOM. Our BOTTOM value becomes the TOP minus the number of clock cycles needed for the equivelent CTC value, so the formula becomes:

Reload Timer Value = ((2 ^ Bits) - 1) - ((Input Frequency / Prescale) / Target Frequency)

Let's go with the previous example in part two: a 1Hz flasher, using a 1MHz clock and a prescale of 64. We found the timer count to be 15625 for those conditions. Plugging it into the above Reload Timer Value formula gives:

Reload Timer Value = ((2 ^ Bits) - 1) - 15624 = ((2 ^ 16) - 1) - 15624 = 65535 - 15624 = 49911

So we need to preload and reload our overflow timer on each overflow with the value 49911 to get our desired 1Hz delay. Since we've already gone over the code for an interrupt-driven overflow example in part seven, we'll build upon that.

#include

Both the reloading and preloading of the timer takes identical code - we just need to set the timer's count register to the precalculated value. The timer's current count value is avaliable in the TCNTx register, where "x" is the timer's number. We're using the 16-bit timer 1, so the count value is located in TCNT1.

We'll now finish of the example, replacing the unfinished segments:

#include

And done! This is less preferable to the pure hardware CTC mode, as it requires a tiny bit more work on both the programmer and the AVR to function. However, it will work just fine for AVRs lacking the complete CTC timer functionality.

Due to forum software length limits, the PWM section of this tutorial is continued HERE

For an updated version of this tutorial in PDF format, please see this page of my website.

- Dean :twisted:

Sours: https://www.avrfreaks.net/forum/tut-c-newbies-guide-avr-timers?page=all
  1. Walmart custom frames
  2. Flo rida itunes
  3. Yrc freight hawaii

A Timer is actually a counter that is increased every time when an instruction is executed. There are one to six timers in AVR Microcontrollers depending upon their family architecture.The AVR timers are of 8 bits and 16 bits. The 8-bit timers are termed as TCNTn while the 16 bit timers are termed as two 8 bit registers (TCNTnH, TCNTnL).Generally AVR like ATmega32 consists of three timers Timer0, Timer1 and Timer2 respectively. The timer0 and timer2 are 8 bit registers whereas the timer1 is a 16 bit register.   Every timer has its own TCCR (Timer/Counter Control Register) register that is responsible to choose different operational modes.

Timers of AVR microcontroller

Timers can be used to generate time delays or as a counter to count events.If we want to use timer as counter then we can join the external source to the clock pin of counter register. The content of the counter is incremented when an event is occurred. This increment shows that how many times an event has occurred. Now if we want to generate time delays then we can connect the oscillator to the clock pin of counter register. This results an increment in the content of the counter when an oscillator ticks. This shows that how many ticks have been occurred when cleared the counter. We can easily calculate the tick period as the speed of oscillator is known and we will recognize how much time has been over and done from the content of the register.

There is also a flag for each counter in the microcontrollers. When the counter overflows the flag is set. The other technique to generate time delays is to load the counter register and wait for the time when the overflow of the counter takes place and flag is set. For example, in a microcontroller with a frequency of 1MHZ using 8-bit counter register, if we need a time delay of 2 seconds we just have to load the counter register with $FE and wait until the flag is set. In this case, after the first tick the content of the clock register increases to $FF and after the second tick it overflows. In other words, the content of the register becomes $00 and the flag is set. This expression is illustrated in the following diagram.

how to user timers of avr microcontroller

Basic registers of timers

There is a TCNTn called timer/Counter Register for each of the timers in AVR. For example, In Atmega32 we have TCNT0, TCNT1 and TCNT2.  The TCNTn is basically a counter. It counts up with each pulse. It contains zero when reset. We can read or load any value in the TCNTn register.Each of the timer has TOV called Time Overflow. The TOVn flag is set when the timer overflows, where ‘n’ is the any number of a timer.

These timers have also Timer/Counter Control Register. It is denoted as TCCRn. It is used for setting up the modes of the timer.Another register of the timer is OCRn which is named as “Output Compare register”. It is used as Compare match register. Here the contents of OCRn are compared with the contents of TCNTn.

Modes of operation of timers

There are two modes of AVR Timers.

  1. Normal Mode
  2. CTC mode

In normal mode, the content of the timer or counter is increased with each clock. It keeps on counting until it reaches its maximum value of 0xFF. When it turns from 0xFF to 0x00, a flag bit is set up and overflow occurs.

While in CTC mode, compare match occurs. In other words, the content of the timer increases with each clock. This increment goes on until a stage comes when the contents of the TCNTn register become equal to the contents of OCRn. Then the timer is cleared and the OCFn flag is set when the next clock occurs. Here ‘n’ is the number of the timer like TCNT0, TCNT1 etc. and OCFn is called the output compare flag of any timer/counter.

Timer1 Programming

Timer1 is 16 bit timer which is shown below:

       TCNT1H                                                                                                        TCNT1L

D15D14D13D12D11D10D9D8D7D6D5D4D3D2D1D0

As Timer1 is 16 bit registers, it is split up into two bytes. They are termed as TCNT1L and TCNT1H. TCNT1L is lower byte whereas TCNT1H is higher byte. In above case, the register vales from D0 to D7 are called TCNT1L and the register values ranging from D8 to D15 are called TCNT1H.

Timer1 has also two timer/counter control registers termed as TCCR1A & TCCR1B. Similarly timer overflow registers are TOV1 & TOV2 respectively. Whereas there are two output compare registers are OCR1A and OCR1B. There are two separate flags for each of the OCR registers which are independent of each other. When TCNT1 is equal to OCR1A, OCF1 flag will be set on the next timer clock. Similarly when TCNT2 is equal to the OCR1B, the OCF2 flag will be set on the next timer clock.

Timer1 operation modes

Normal mode

In this mode, the timer counts up until it reaches to its maximum value $FFFF. Then it moves from $FFFF to $0000. As a result TOV1 flag is set as high.

CTC Mode

In this mode, the timer keeps on counting until the contents of TCNT1 become equal to those of OCR1A. Then the timer will be cleared after the next clock and the OCF1 flag will be set as a result of compare match case.The size of time delay depends upon the two factors “the crystal frequency” and “the timer’s 16-bit register”. If we want to increase the delay time then we can use the prescalar option by reducing the period. This option of TCCR1b facilitates to divide the instruction clock by a factor of 8 to 1024.

Programming Timers in C

As it is clear that the general purpose registers of the AVR are under the control of the C Compiler. They are not directly accessed by the C statements. However, all of the special function registers (SFR) are directly accessed by the C statements.In other words, we can say that in ‘C’ we can access timer registers such as TCNT0, OCR0 and TCCR0 directly using their names.

timer0 of avr microcontroller

Let’s see an example showing this phenomenon.Following example will toggle all the bits of PORTB with some delay.  LED are connected with PORTB of avr microcontroller to check results. Timer is used to generate delay.

#include “avr/io.h”

Void T0 Delay ( ); int main ( ) {             DRB = 0xFF;                          // PORTB output port while ( 1) {             PORTB = 0x55;          // repeat forever             T0 Delay ( );                // delay size unknown             PORTB = 0xAA;        // repeat forever             T0 Delay ( ); } } Void T0 Delay ( ) {             TCNT0 = 0x20;                       // load TCNT0             TCCR0 = 0x01;                      // Timer0, Normal mode, no prescaler             While ((TIFR&0x1) ==0);      // wait for TF0 to roll over             TCCR0 = 0;             TIFR = 0x1;                            // clear TF0 }

In the above example, we toggled all the bits with the use PORTB. We generated time delay using normal mode in which the timer reaches to its   maximum value $FFF. Then it moves from $FFF to $000 and as a result TOV1 flag bit is set as high.

Categories AVR microcontroller tutorials and projectsSours: https://microcontrollerslab.com/timers-avr-microcontroller/
Atmel Programming Tutorial 6 - Timers and Counters

Basics

Timers come in handy when you want to set some time interval like your alarm. This can be very precise to a few microseconds.

Timer/Counter Unit

Timers/Counters are essential part of any modern MCU. Remember it is the same hardware unit inside the MCU that is used either as Timers or Counter. Timers/counters are an independent unit inside a micro-controller. They basically run independently of what task CPU is performing. Hence they come in very handy, and are primarily used for the following:

  • Internal Timer: As an internal timer the unit, ticks on the oscillator frequency. The oscillator frequency can be directly feed to the timer or it can be pre-scaled. In this mode it used generate precise delays. Or as precise time counting machine.
  • External Counter: In this mode the unit is used to count events on a specific external pin on a MCU.
  • Pulse width Modulation(PWM) Generator: PWM is used in speed control of motors and various other applications.

Atmega32 has 3 timer units, timer 0, timer 1 and timer 2 respectively. Let us start our exploration with timer 0.

Timer 0.png0 Timer.gif Timer 0 is a 8 bit timer. It basically means it can count from 0 to 2^8 255. The operation of timer 0 is straight forward. The TCNT0 register hold the timer Count and it is incremented on every timer "tick". If the timer is turned on it ticks from 0 to 255 and overflows. If it does so, a Timer OverFlow Flag(TOV) is set.

You can as well load a count value in TCNT0 and start the timer from a specific count. Another interesting feature is that a value can be set in the Output Compare Register (OCR0), and whenever TCNT0 reaches that value, the Output Compare Flag (OCF0) flag is Set.

TCNT0 D7D6D5D4D3D2D1D0

The configuration of the Timer can be set using the TCCR0 register shown below. With this you can basically select two things:

  1. The Frequency of the Clock Source with CS02, CS01, CS00 bits.
  2. The mode of the timer. For the first example we will use it in normal mode where it ticks from zero to the highest value(255)
TCCR0 D7D6D5D4D3D2D1D0
FOC0WGM00COM01COM00WGM01CS02CS01CS00
D2D1D0Clock Source
CS02CS01CS00Freq
000 No Clock (Stopped)
001Clk
010Clk/8
011Clk/64
100Clk/256
101Clk/1024
110Clk/T0-Falling edge
111Clk/T0-Rising Edge
D6D3PWM
WGM00WGM01Mode
00Normal
01CTC (Clear timer on compare match)
10PWM (Phase correct)
11Fast PWM

The Timer/counter Interrupt Flag Register(TIFR) holds the two basic flags we need the TOV and OVF. Other bits correspond to the timer interrupts, which we will look at in another tutorial.

TIFR D7D6D5D4D3D2D1D0
OCF2TOV2ICF1OCF1AOCF1BTOV1OCF0TOV0

Toggle LED connected to PD4 every 100msec using Timer Zero with 1024 pre-scalar in normal mode.

What is the Max delay Timer 0 overflow generates? Okay, lets calculate. The Explore Ultra AVR dev board comes with a 16MHz on board crystal and the fuse bits are set appropriately. If we use the highest pre-scalar of 1024, calculation shows it can generate a delay of 16milli seconds every time timer zero overflows.

$$Ftimer = CPU Frequency/Prescalar $$ $$Ftimer = 16MHz/1024 = 15.625KHz $$ $$Ttick = 1/ 15.625K = 64 \mu seconds$$ $$Ttotal = 64\mu s X 255 = 16ms$$

Of-course 16ms is not enough, so the next obvious question is:
How many times should the timer overflow to generate a delay of approximately 100msec?

$$ OverFlowCount = 100ms/16ms = 6.25 ≈ 6 $$

Now let's write a simple program which will toggle a port pin (PD4) after the timer 0 overflows 6 times.

  1. Load TCNT0 with 0x00
  2. Set CS00 and CS02 bits in TCCR0 register. This will start the timeWe will calculate the tick time in just a moment.r at Clk/1024 speed.
  3. Monitor the TOV0 flag in the TIFR0 register to check if the timer has over-flowed, keep a timerOverFlowCount.
  4. If timerOverFlowCount >= 6, toggle the led on PD4 and reset the count

Code

The Timer 1 is 16 bit, that means it can count from 0 to $$2^{16} = 65536$$. Hence the Timer/Counter 1 is a 16 bit registered formed out of TCNT1H and TCNT1L as shown below.

TCNT1H TCNT1L
D15D14D13D12D11D10D9D8D7D6D5D4D3D2D1D0

Timer 3 also has 2 control registers which allow us to configure it and use it in any mode you wish.

TCCR1A D7D6D5D4D3D2 D1D0
COM1A1COM1A0COM1B1COM1B0FOC1AFOC1BWGM11WGM10
TCCR1B D7D6D5D4D3D2 D1D0
ICNC1ICES1-WGM13WGM12CS12CS11CS10
D2D1D0Clock Source
CS12CS11CS10Freq
000 No Clock (Stopped)
001Clk
010Clk/8
011Clk/64
100Clk/256
101Clk/1024
110Clk/T1-Falling edge
111Clk/T1-Rising Edge

Yes, and indeed we have a Flag register which will tell us the status of Timer 1 as shown below.

TIFR D7D6D5D4D3D2D1D0
OCF2TOV2ICF1OCF1AOCF1BTOV1OCF0TOV0

Let us repeat the example of Timer 0 of toggling PD4 every 100ms. This time since it is a 16 bit timer, let's see what is the max delay it generates with a pre-scalar of 1024.

$$Ftimer = CPU Frequency/Prescalar $$ $$Ftimer = 16MHz/1024 = 15.625KHz $$ $$Ttick = 1/ 15.625K = 64 \mu seconds$$ $$Ttotal = 64\mu s X 65536 = 4 seconds$$

So that is 4 secs! We just need 100 msec so, $$100ms/64\mu s = 1562 = 0x061A$$

This time, instead of using the overflow flag, it's use Output Compare Register (OCR) and the related flag.

So the with the following steps we should be able to generate the required delay.

  1. Load OCR1H with 0x3d and OCR1L with 0x09
  2. Run the timer with pre-scalar of 1024 by setting CS12 and CS10 bits.
  3. Monitor OCF flag and if it is set, toggle the led
  4. Reset the TCNT1L and TCNT1H values to zero and repeat steps 1 to 3.

Code

Well, timer 2 is pretty similar to the timers covered above. Give it a shot, should you've any questions do comment below.

Timers are independent units from the CPU. Hence if we use timers with Interrupts it can make the CPU free from polling the flags every-time. This is the way they are used normally. Check AVR Timer Interrupts tutorial where we will cover all of that.

Download the complete project folder from the below link: https://github.com/ExploreEmbedded/ATmega32_ExploreUltraAvrDevKit/archive/master.zip

Have a opinion, suggestion , question or feedback about the article let it out here!

Sours: https://exploreembedded.com/wiki/AVR_Timer_programming

Avr timers

[8-bit] [16-bit] [Register Overview] [Modes] [Examples]

The AVR has different Timer types. Not all AVRs have all Timers, so look at the datasheet of your AVR before trying to use a timer it doesn't have...This description is based on the AT90S2313.

I will only describe the "simple" timer modes all timers have. Some AVRs have special timers which support many more modes than the ones described here, but they are also a bit more difficult to handle, and as this is a beginners' site, I will not explain them here.

The timers basically only count clock cycles. The timer clock can be equal to the system clock (from the crystal or whatever clocking option is used) or it can be slowed down by the prescaler first. When using the prescaler you can achieve greater timer values, while precision goes down.

The prescaler can be set to 8, 64, 256 or 1024 compared to the system clock. An AVR at 8 MHz and a timer prescaler can count (when using a 16-bit timer) (0xFFFF + 1) * 1024 clock cycles = 67108864 clock cycles which is 8.388608 seconds. As the prescaler increments the timer every 1024 clock cycles, the resolution is 1024 clock cycles as well: 1024 clock cycles = 0.000128 seconds compared to 0.125µs resolution and a range of 0.008192 seconds without prescaler. It's also possible to use an external pin for the timer clock or stop the timer via the prescaler.

The timers are realized as up-counters. Here's a diagram of the basic timer hardware. Don't panic, I'll explain the registers below.

The 8-bit Timer:

The 8-bit timer is pretty simple: The timer clock (from System Clock, prescaled System Clock or External Pin T0) counts up the Timer/Counter Register (TCNT0). When it rolls over (0xFF -> 0x00) the Overflow Flag is set and the Timer/Counter 1 Overflow Interrupt Flag is set. If the corresponding bit in TIMSK (Timer Interrupt Mask Register) is set (in this case the bit is named "TOIE0") and global Interrupts are enabled, the micro will jump to the corresponding interrupt vector (in the 2313 this is vector number 7).

The 16-bit Timer

is a little more complex, as it has more modes of operation:

Register Overview:

[TCNT1] [TCCR1A / TCCR1B] [OCR1A] [ICR1] [TIMSK and TIFR]

The register names vary from timer to timer and from AVR to AVR! Have a look at the datasheet of the AVR you're using first.

Important note: All 16-bit registers have can only be accessed one byte at a time. To ensure precise timing, a 16-bit temporary register is used when accessing the timer registers.

Write:
When writing the high byte (e.g. TCNT1H), the data is placed in the TEMP register. When the low byte is written, the data is transferred to the actual registers simultaneously. So the high byte must be written first to perform a true 16-bit write.

Read:
When reading the low byte, the high byte is read from TCNT1 simultaneously and can be read afterwards. So when reading, access the low byte first for a true 16-bit read.

TCNT

Most important is the Timer/Counter Register (TCNT1) itself. This is what all timer modes base on. It counts System Clock ticks, prescaled system clock or from the external pin.

TCCR

The Timer/Counter Control register is used to set the timer mode, prescaler and other options.

TCCR1A:

Bit 7

           

Bit 0

COM1A1

COM1A0

---

---

---

---

PWM11

PWM10

Here's what the individual bits do:

COM1A1/COM1A0: Compare Output Mode bits 1/0; These bits control if and how the Compare Output pin is connected to Timer1.

COM1A1COM1A0Compare Output Mode

0

0

Disconnect Pin OC1 from Timer/Counter 1

0

1

Toggle OC1 on compare match

1

0

Clear OC1 on compare match

1

1

Set OC1 on compare match

With these bit you can connect the OC1 Pin to the Timer and generate pulses based on the timer. It's further described below.

PWM11/PWM10: Pulse Width Modulator select bits; These bits select if Timer1 is a PWM and it's resolution from 8 to 10 bits:

PWM11PWM10PWM Mode

0

0

PWM operation disabled

0

1

Timer/Counter 1 is an 8-bit PWM

1

0

Timer/Counter 1 is a 9-bit PWM

1

1

Timer/Counter 1 is a 10-bit PWM

The PWM mode of Timer1 is dsecribed below.

TCCR1B:

Bit 7

           

Bit 0

ICNC1

ICES1

---

---

CTC1

CS12

CS11

CS10

ICNC1: Input Capture Noise Canceler; If set, the Noise Canceler on the ICP pin is activated. It will trigger the input capture after 4 equal samples. The edge to be triggered on is selected by the ICES1 bit.

ICES1: Input Capture Edge Select;

When cleared, the contents of TCNT1 are transferred to ICR (Input Capture Register) on the falling edge of the ICP pin.

If set, the contents of TCNT1 are transferred on the rising edge of the ICP pin.

CTC1: Clear Timer/Counter 1 on Compare Match; If set, the TCNT1 register is cleared on compare match. Use this bit to create repeated Interrupts after a certain time, e.g. to handle button debouncing or other frequently occuring events. Timer 1 is also used in normal mode, remember to clear this bit when leaving compare match mode if it was set. Otherwise the timer will never overflow and the timing is corrupted.

CS12..10: Clock Select bits; These three bits control the prescaler of timer/counter 1 and the connection to an external clock on Pin T1.

CS12CS11CS10Mode Description

0

0

0

Stop Timer/Counter 1

0

0

1

No Prescaler (Timer Clock = System Clock)

0

1

0

divide clock by 8

0

1

1

divide clock by 64

1

0

0

divide clock by 256

1

0

1

divide clock by 1024

1

1

0

increment timer 1 on T1 Pin falling edge

1

1

1

increment timer 1 on T1 Pin rising edge

OCR1

The Output Compare register can be used to generate an Interrupt after the number of clock ticks written to it. It is permanently compared to TCNT1. When both match, the compare match interrupt is triggered. If the time between interrupts is supposed to be equal every time, the CTC bit has to be set (TCCR1B). It is a 16-bit register (see note at the beginning of the register section).

ICR1

The Input Capture register can be used to measure the time between pulses on the external ICP pin (Input Capture Pin). How this pin is connected to ICR is set with the ICNC and ICES bits in TCCR1A. When the edge selected is detected on the ICP, the contents of TCNT1 are transferred to the ICR and an interrupt is triggered.

TIMSK and TIFR

The Timer Interrupt Mask Register (TIMSK) and Timer Interrupt Flag (TIFR) Register are used to control which interrupts are "valid" by setting their bits in TIMSK and to determine which interrupts are currently pending (TIFR).

Bit 7

           

Bit 0

TOIE1

OCIE1A

---

---

TICIE1

---

TOIE0

---

TOIE1: Timer Overflow Interrupt Enable (Timer 1); If this bit is set and if global interrupts are enabled, the micro will jump to the Timer Overflow 1 interrupt vector upon Timer 1 Overflow.

OCIE1A: Output Compare Interrupt Enable 1 A; If set and if global Interrupts are enabled, the micro will jump to the Output Compare A Interrupt vetor upon compare match.

TICIE1: Timer 1 Input Capture Interrupt Enable; If set and if global Interrupts are enabled, the micro will jump to the Input Capture Interrupt vector upon an Input Capture event.

TOIE0: Timer Overflow Interrupt Enable (Timer 0); Same as TOIE1, but for the 8-bit Timer 0.

TIFR is not really necessary for controlling and using the timers. It holds the Timer Interrupt Flags corresponding to their enable bits in TIMSK. If an Interrupt is not enabled your code can check TIFR to deternime whether an interrupt has occured and clear the interrupt flags. Clearing the interrupt flags is usually done by writing a logical 1 to them (see datasheet).

Timer Modes

[Normal Mode] [Output Compare Mode] [Input Capture Mode] [PWM Mode]

Normal Mode:

In normal mode, TCNT1 counts up and triggers the Timer/Counter 1 Overflow interrupt when it rolls over from 0xFFFF to 0x0000. Quite often, beginners assume that they can just load the desired number of clock ticks into TCNT1 and wait for the interrupt (that's what I did...). This would be true if the timer counted downwards, but as it counts upwards, you have to load 0x0000 - (timer value) into TCNT1. Assuming a system clock of 8 MHz and a desired timer of 1 second, you need 8 Million System clock cycles. As this is too big for the 16-bit range of the timer, set the prescaler to 1024 (256 is possible as well).

8,000,000/1024 = 7812.5 ~ 7813
0x0000 - 7813 = 57723 <- Value for TCNT1 which will result in an overflow after 1 second (1.000064 seconds as we rounded up before)

So we now know the value we have to write to the TCNT1 register. So? What else? This is not enough to trigger the interrupt after one second. We also have to enable the corresponding interrupt and the global interrupt enable bit. Here's a flow chart of what happens:

The only steps you have to do are:

- set prescaler to 1024 (set bits CS12 and CS10 in TCCR1B)
- write 57723 to TCNT1
- enable TOIE1 in TIMSK
- enable global interrupt bit in SREG
- wait. Or do anything else. All the counting and checking flags is done in hardware.

Output Compare Mode

The Output Compare mode is used to perform repeated timing. The value in TCNT1 (which is counting up if not stopped by the prescaler select bits) is permanently compared to the value in OCR1A. When these values are equal to each other, the Output Compare Interrupt Flag (OCF in TIFR) is set and an ISR can be called. By setting the CTC1 bit in TCCR1B, the timer can be automatically cleared upon compare match.

The flow chart should show an arrow from CTC1 set? "Yes" to set OCF instead of a line, but somehow the Flow Charting Program didn't think that was a good idea. Bad luck.

Let's discuss a small example:We want the Timer to fire an int every 10ms. At 8 MHz that's 80,000 clock cycles, so we need a prescaler (out of 16-bit range).

In this case, 8 is enough. Don't use more, as that would just pull down accuracy. With a prescaler of 8, we need to count up to 10,000.As the value of TCNT1 is permanently compared to OCR1 and TCNT1 is up-counting, the value we need to write to OCR is acutally 10,000 and not 0x0000-10,000, as it would be when using the timer in normal mode.

Also, we need to set CTC1: If we didn't, the timer would keep on counting after reaching 10,000, roll over and then fire the next int when reaching 10,000, which would then occur after 0xFFFF*8 clock cycles. That's after 0.065536 seconds. Not after 10ms. If CTC1 is set, TCNT1 is cleared after compare match, so it will count from 0 to 10,000 again with out rolling over first.

What is to be done when those 10ms Interrupts occur? That depends on the application. If code is to be executed, the corresponding interrupt enable bit has to be set, in this case it is OCIE1A in TIMSK. Also check that global interrupts are enabled.

If the OC1 (Output Compare 1) pin is to be used, specify the mode in TCCR1A. You can set, clear or toggle the pin. If you decide that you want to toggle it, think about your timing twice: If you want a normal pulse which occurs every 10ms, the timer cycle must be 5ms: 5ms -> toggle on -> 5ms -> toggle off. With the 10ms example above and OC1 set up to be toggled, the pulse would have a cycle time of 20ms.

Input Capture Mode

The Input Capture Mode can be used to measure the time between two edges on the ICP pin (Input Capture Pin). Some external circuits make pulses which can be used in just that way. Or you can measure the rpm of a motor with it. You can either set it up to measure time between rising or falling edges on the pin. So if you change this setting within the ISR you can measure the length of a pulse. Combine these two methods and you have completely analysed a pulse. How it works?

Here's a flow chart of its basic functionality:

You see that it's actually pretty simple. I left out the low level stuff such as Interrupt validation (enabled/global enable), as you should understand that by now. The contents of TCNT1 are transferred to ICR1 when the selected edge occurs on the Input Capture Pin and an ISR can be called in order to clear TCNT1 or set it to a specific value. The ISR can also change the egde which is used to generate the next interrupt.

You can measure the length of a pulse if you change the edge select bit from within the ISR. This can be done the following way:

Set the ICES (Input Capture Edge Select) bit to 1 (detect rising edge)

When the ISR occurs, set TCNT1 to zero and set ICES to 1 to detect negative egde

When the next ISR is called, the pin changed from high to low. The ICR1 now contains the number of (prescaled) cycles the pin was high. If the ISR again sets the edge to be detected to rising (ICES=1), the low pulse time is measured. Now we have the high time AND the low time: We can calculate the total cycle time and the duty cycle.

It's also possible to connect the Analog Comparator to the input capture trigger line. That means that you can use the Analog Comparator output to measure analog signal frequencys or other data sources which need an analog comparator for timing analysis. See the Analog Comparator page for more.

PWM Mode

The Pulse Width Modulator (PWM) Mode of the 16-bit timer is the most complex one of the timer modes available. That's why it's down here.

The PWM can be set up to have a resolution of either 8, 9 or 10 bits. The resolution has a direct effect on the PWM frequency (The time between two PWM cycles) and is selected via the PWM11 and PWM10 bits in TCCR1A. Here's a table showing how the resolution select bits act. Right now the TOP value might disturb you but you'll see what it's there for. The PWM frequency show the PWM frequency in relation to the timer clock (which can be prescaled) and NOT the system clock.

PWM11PWM10ResolutionTOP-valuePWM Frequency
00PWM function disabled
018 bits$00FFfclock/510
109 bits$01FFfclock/1022
1110 bits$03FFfclock/2046

To understand the next possible PWM settings, I should explain how the PWM mode works. The PWM is an enhanced Output Compare Mode. In this mode, the timer can also count down, as opposed to the other modes which only use an up-counting timer. In PWM mode, the timer counts up until it reaches the TOP value (which is also the resolution of the timer and has effect on the frequency).

When the TCNT1 contents are equal to the OCR1 value, the corresponding output pin is set or cleared, depending on the selected PWM mode: You can select a normal and an inverted PWM. This is selected with the COM1A1 and COM1A0 bits (TCCR1A register). The possible settings are:

COM1A1COM1A0Effect:
00PWM disabled
01PWM disabled
10Non-inverting PWM
11inverting PWM

Non-inverted PWM means that the Output Compare Pin is CLEARED when the timer is up-counting and reaches the OCR1 value. When the timer reaches the TOP value, it switches to down-counting and the Output Compare Pin is SET when the timer value matches the OCR1 value.

Inverted PWM is, of course, the opposite: The Output Compare Pin is set upon an up-counting match and cleared when the down-couting timer matches the OCR1 value. Here are two diagrams showing what this looks like:

The reason why you can select between inverting and non-inverting pwm is that some external hardware might need an active-low pwm signal. Having the option to invert the PWM signal in hardware saves code space and processing time.

The PWM is also glitch-free. A glitch can occur when the OCR1 value is changed: Imagine the PWM counting down to 0. After the pin was set, the OCR1 value is changed to some other value. The next pulse has an undefined length because only the second half of the pulse had the specified new length. That's why the PWM automatically writes the new value of OCR1 upon reaching the TOP value and therefore prevents glitches.

Typical applications for the PWM are motor speed controlling, driving LEDs at variable brightness and so on. Make sure you have appropriate drivers and protection circuitry if you're using motors!

Some Examples...

Some simple examples can also be found here...

- Setting up a timer

- Flashing LED using the Timer Overflow Interrupt and the Output compare mode

- Pulse Width Modulated LED demo with two timers

Sours: http://www.avrbeginners.net/architecture/timers/timers.html
AVR Atmega 32 Timer 0 Prescaler 1024 Delay 10ms

When Pasha went ashore, Sveta seemed to be sitting on his head. Apparently Sveta did not feel this, and did not see what giant was standing at the entrance to her bosom. She turned to me, and with undisguised resentment began: "It's you. A-a-ah," Sveta screamed.

It was Pasha who interrupted her, lowering her even lower and pushing his head between her lips.

You will also be interested:

Angela covered her face with her hands, in a second she wanted to fall through the ground. She didn't want to believe it. Yes.



652 653 654 655 656