20161202T21:30 Timer with AVR assembly - OrCarin/CET-3510-1KB-Contest GitHub Wiki

Timer with AVR assembly

After work with the LED cycling part of the project, its became quite understandable for why the author decided against a blink program as the first program in the tutorial. With pure AVR assembly, a simple delay function is much more involved.

The ATmega 328P micro controller comes three timers, appropriately named TIMER0, TIMER1 and TIMER2. They can trigger interrupts at memory locations 0x0020 to 0x000E (see page 62 of ATmega328P Datasheet). This means that code at that location can be executed depending on the value of Timer/Counter, such as when it matches a certain value or when it overflows. Interrupts must first be enabled with the TIMSK0 Timer/Counter Interrupt Mask Register (page 109 of Datasheet).

As a 8bit system, the Timer/Counter may store values between 0 to 256 To control the rate of which this increments, it may be set to be increment at a rate of 1/1, 1/8, 1/64, 1/256 or 1/1024 (page 108 of Datasheet) of the clock speed 20MHz. Even at 1/1024 of 20MHz (19.53kHz), this is still too fast to blink an LED visibly. Therefore, a separate register is used to count Timer/Counter overflow interrupts. This overflow counter will increment every 13.11ms (76.29Hz). Since this counter is also 8 bit, it can be used for delays up to 3.356 seconds, slow enough to be visible!

The delay function first resets the overflow counter. It then compares the value stored in the r16 register with the overflow interrupt counter, looping until it exceeds the value in r16. For example, to delay for 1 second, r16 needs to be set to 76 (since 1000ms/13.11ms = 76). This delay function can called in the main loop to blink an LED.

TL:DR

The Arduino has an 20MHz clock, too fast to be visible. Timer can be set to trigger interrupts at 1/1024 of that rate, or around 20kHz (still too fast). A separate counter is used to count the number of interrupts at 1/256 of 20kHz, around 76.29Hz. This is slow enough for delays between 0.013 seconds and 3.356 seconds.