How to implement a System Clock for AVR microcontroller

Microcontroller Topics
Post Reply
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

How to implement a System Clock for AVR microcontroller

Post by Neo » Thu Feb 11, 2010 11:01 pm

Handy system clock for AVR 8-bit microcontrollers suitable for measuring elapsed time or for use with timers. This provides a monotonic time since system startup (like the POSIX CLOCK_MONOTONIC).

The system clock is based around a 32kHz clock crystal and one of the 8-bit timers provided by the AVR, it is possible to use the CPU frequency as a timer base as long as it’s a nice, dividable, frequency. To be able to provide a stable 1 Hz clock but still have sub-second precision we divide 1 second into an arbitrary number of system ticks. To minimize CPU usage the tick counter should be increased at each interrupt, this means that the number of ticks per second we we choose determines our interrupt frequency and timer resolution. How to choose number of ticks? It all depends on your required resolution, if you only want a 1 second resolution a tick and a second becomes equal.

The AVR timer is a 8-bit register that simply counts at the rate of its clock source. The clock source can be either the CPU clock or an external oscillator, the clock source is also subject to a prescaler to further decrease the frequency. The timer then generates an interrupt on overflow and/or when it hits a pre-configured value. Since its a 8-bit timer, we have a maximum of 256 cycles before an interrupt is generated, a smaller interval can be achieved by using the comparator match to generate an interrupt at a specific value.

This example is creating a 1/32 second resolution timer (32 ticks per second) using an external 32768 Hz watch crystal.
comp is the comparator value, to avoid re-arming it with different values it should be limited to 128 or 256, otherwise it has to be changed at each interrupt.
1.png
1.png (635 Bytes) Viewed 3160 times
2.png
2.png (495 Bytes) Viewed 3160 times
The following to equations can be used to calculate either comp or the prescale value.
prescale is limited by the target device, but common values are powers of 2 (8,32,64,128,256,1024).
3.png
3.png (978 Bytes) Viewed 3160 times
4.png
4.png (1.06 KiB) Viewed 3160 times
Using 128 as the comp value and inserting the other values into equation 2 yields the following prescaler
5.png
5.png (677 Bytes) Viewed 3160 times
So, a prescaler of 8 gives us two interrupts per 256 cycles, one at 128 and one at 256 (overflow). Using 256 as comp would yield a perscaler of 4 but the target device I used didn’t have a TS/4 prescaler.

Complete source code for a 1/32 (or 31.25ms) second resolution timer for the ATmegaxx4 using Timer 2 and a 32kHz watch crystal connected to the pins TOSC1 and TOSC2.
Requires AVR libc.

Code: Select all

#include <avr/io.h>
#include <avr/interrupt.h>
 
typedef uint32_t clock_time_t;
static clock_time_t global_system_ticks = 0;
 
/* ISR for the timer overflow */
ISR(TIMER2_OVF_vect)
{
    global_system_ticks++;
}
 
/* ISR for the comparator */
ISR(TIMER2_COMPA_vect)
{
    global_system_ticks++;
}
 
/* Return number of elapsed ticks */
clock_time_t clock_time()
{
    return (global_system_ticks);
}
 
/* Return number of elapsed seconds */
unsigned long clock_seconds(void)
{
    uint32_t tmp;
 
    TIMSK2 &= ~(1 << OCIE2A) | (1 << TOIE2);
    tmp = global_system_ticks / 32;
    TIMSK2 |= (1 << OCIE2A) | (1 << TOIE2);
    return (tmp);
}
 
void clock_init()
{
 
    /* Enable external oscillator (32 kHz crystal) connected to TOSC{1,2} */
    ASSR |= (1 << AS2);
 
    /* Reset timer */
    TCNT2 = 0;
 
    /* Set TS/8 prescaler, results in a 4096Hz clock */
    TCCR2B |= (1 << CS21);
 
    /* Compare at half counter value */
    OCR2A = 128;
 
    /*
     * Enable overflow and compare interrupt.
     * Triggers each 1/32 secs
     */
    TIMSK2 |= (1 << OCIE2A) | (1 << TOIE2);
}
Post Reply

Return to “Microcontrollers”