AVR Advanced Timer Interrupts

Now that you have timer interrupts working, lets get to work making them more useful.

STK500 Setup

For this example, make sure that you have your PORTA jumpered to LEDs, as was discussed in our Port Output guide.

You will also want to have the second serial port called RS232 SPARE connected to your computer, and a terminal program listening to that port. This example uses 19,200 baud.

Volatile Global Variables

If you are going to modify a global variable in your ISR or you are going to modify it in your main loop and then use it in your ISR, you need to declare that variable as volatile, to tell the compiler to not use the optimized value and assume that it hasn’t changed.

Main Loop

If you want to process code in the foreground, while letting timers do other processes in the background, then put your main code in your main loop. For instance, if you want to respond to SW0 connected to PORTB, you might have the following code in your main loop:

Lets look at this block of code really close.

if(bit_is_clear(PINB,PB0)) checks to see if the pushbutton connected to PB0, which is SW0 has been pressed. If it has not been presssed, code continues on. However, if it has been pressed, then the entire if block gets executed.

Inside the if block, we print Stop poking me! at the user, and then enter a while loop that does nothing { } and watches the same bit. As long as the user holds SW0 down, we will never leave that empty { } loop. That’s ok, because the timer can still interrupt us to do whatever it has to do, even though we are effectively looping forever.

When the user finally lets go of the button, our second while loops ends and we tell the user “That’s better.” After that, we jump back to the top of our never ending main loop.

Timer Interrupt Routines

The timer interrupt routines are going to be busy every once in a while doing randome tasks. In this program, we have them doing the following:

  • timer1 proudly prints “***** Timer1 Overflow ****” to the screen.
  • timer0 increments a global variable called lights and sends it out to PORTA for a nice light show
  • timer0 also tracks a value called timer0_ticks and at the correct time prints the number of seconds that have elapsed to the screen

Timers, Tracking Seconds, and printf

This is a large example of code that uses timers to keep track of how many seconds have elapased, and every second prints the current number of seconds to the USART usingprintf. It also responds to button inputs on SW0 and SW1 in the main loop.

You can download the complete source code here.

This program compiles to 2,300 bytes (thanks to printf). It generates the following output if left alone:

Ready to rock!
Its been 1 seconds.
Its been 2 seconds.
Its been 3 seconds.
Its been 4 seconds.
Its been 5 seconds.
Its been 6 seconds.
Its been 7 seconds.
Its been 8 seconds.
***** Timer1 Overflow *****
Its been 9 seconds.
Its been 10 seconds.

And if you press and hold SW0 for a second or 2, then release it, you’ll get this in your output:

Its been 11 seconds.
***** Stop poking me! *****
Its been 12 seconds.
Its been 13 seconds.
Its been 14 seconds.
***** That’s better. *****
Its been 15 seconds.

Meanwhile, the LEDs connected to PORTA are constantly lighting up in a binary counting pattern.

Our next guide is not yet written…

Head back to our index of AVR Guides here.

5 comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.