COUNTERS ON THE ATmega8


INTRODUCTION:

This chapter describes the operation of the hardware counters of the ATmega8. While software counters are fairly simple they can easily miss fast signals in long complex programs. Hardware counters are always looking for inputs and if configured correctly will not miss even fast signals.

The ATmega8 has 3 counters, 2 8bit counters and 1 16bit counter. Since all 3 counters have unique registers and special functions I will break this chapter subsections by counter instead of my usual hardware, theory and software format.

ATmega8 - COUNTERS

Figure 1: ATmega8 - Counter Pins


COUNTER0 (8 Bit):

Theory of Operation:

Counter0 - ATmega8

Figure 2: Counter0

Counter0 is the most basic Counter on the AVR. It gets its input from the T0 pin(as always T0 has the same restrictions as any INPUT or OUTPUT), passes the signals into the Edge Detection, which when triggered sends a pulse to the Control Logic. The Control Logic receives the signal and increments the TCNT0 register. When the TCNT0 register passes the TOP value (0xFF or 255) it simply overflows (or overruns) back to 0, at the same time the TOV0 flag is set. Note that the prescaler is part not of the Counter.

An interrupt can be set to trigger when Counter0 overflows, however since the value at which the overflow occurs is set in stone to (0xFF or 255) we need to use a bit of programming if we want to count to a given number that is bigger then 255 and not an increment of 256.

The only other thing that you I could say about Counter0 is that if it is enabled, it will count events on the T0 pin regardless of if it is set as an input or an output.

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCCR0 - - - - - CS02 CS01 CS00

Timer/Counter Control Register 0

CS02 CS01 CS00 DESCRIPTION
0 0 0 Timer/Counter0 Disabled
x x x Prescaler settings (omited in this tutorial)
1 1 0 External clock source on T0 pin, Clock on Falling edge
1 1 1 External clock source on T0 pin, Clock on rising edge

CS bits Settings

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 - TOIE0

Timer/Counter Interrupt Mask Register

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIFR OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 - TOV0

Timer/Counter Interrupt Flag Register

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCNT0

Timer/Counter Register (stores the counter value)

Software:

You want simple, you got it. When it comes to a Counter all you have to do is activate it for clock on falling edge or clock on rising edge using the CS0n bits within the TCCR0 register, then decide if you want to use the overflow interrupt or not using the TOIEn bit within the TIMSK register. Brilliantly simple.

ATmega8 Code:

    // this code sets up counter0 and with no interrupts

    #include <avr/io.h>

    int main(void)
    {
        DDRD &= ~(1 << DDD4);     // Clear the PD4 pin
        // PD4 is now an input

        PORTD |= (1 << PORTD4);   // turn On the Pull-up
        // PD4 is now an input with pull-up enabled

        TCCR0 |= (1 << CS02) | (1 << CS01) | (1 << CS00);
        // Turn on the counter, Clock on Rise

        while (1)
        {
            // we can read the value of TCNT0 hurray !!
        }
    }

ATmega8 Code:

    // this code sets up counter0 and with interrupts enabled

    #include <avr/io.h>
    #include <avr/interrupt.h>

    int main(void)
    {
        DDRD &= ~(1 << DDD4);     // Clear the PD4 pin
        // PD0 is now an input

        PORTD |= (1 << PORTD4);   // turn On the Pull-up
        // PD4 is now an input with pull-up enabled

        TIMSK |= (1 << TOIE0);    // enable timer interrupt

        TCCR0 |= (1 << CS02) | (1 << CS01) | (1 << CS00);
        // Turn on the counter, Clock on Rise

        sei();

        while (1)
        {
            // we can read the value of TCNT0 hurray !!
        }
    }

    ISR (TIMER0_OVF_vect)
    {
        // interrupt just fired
    }

COUNTER1 (16 Bit):

Theory of Operation:

Counter1 - ATmega8

Figure 3: Counter1

As you could see counter1 is a bit more fancy then Counter0 but, all the theory is still the same. The T1 pin(as always T0 has the same restrictions as any INPUT or OUTPUT), passes the signals into the Edge Detection, which when triggered sends a pulse to the Control Logic. The Control Logic updates the TCNT1 register which is a 16 bit register. The biggest between Counter0 and Counter1 (aside from being 16bit) is that the Control Logic unit in counter1 has the ability to increment, decrement or clear(reset) the TCNT1 register. There are 16 different modes of operation that govern the Control Logic, however, most of them are only useful for PWM operations.

For counting external inputs only 2 modes really apply. the Normal Mode, and the CTC (Clear Timer On Comparer).

In Normal Mode the counter will count untill it reaches the TOP value. When the TCNT1 register passes the TOP value (0xFFFF or 65535) it simply overflows (or overruns) back to 0, at the same time the TOV1 flag is set. In CTC (Clear Timer on Compare) mode the counter will count until it hits the value specified in the OCR1 register. When the TCNT1 passes the TOP value (Specified by the OCR1) it resets to 0 and at the same time sets the TOV1 flag.

An interrupt can be configured to trigger when the TOV1 flag is set.

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCCR1A COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10

Timer/Counter Control Register 1 A

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCCR1B ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10

Timer/Counter Control Register 1 B

CS12 CS11 CS10 DESCRIPTION
0 0 0 Timer/Counter1 Disabled
x x x Prescaler settings (omited in this tutorial)
1 1 0 External clock source on T1 pin, Clock on Falling edge
1 1 1 External clock source on T1 pin, Clock on rising edge

CS bits Settings

WGM13 WGM12 WGM11 WGM10 MODE TOP TOV1
0 0 0 0 Normal 0xFFFF MAX
0 1 0 0 CTC OCR1A MAX

Counter Modes (Abbreviated Version)

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 - TOIE0

Timer/Counter Interrupt Mask Register

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIFR OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 - TOV0

Timer/Counter Interrupt Flag Register

7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCNT1H
TCNT1L

Timer/Counter Register (stores the counter value, 16 bit) Can be accessed as TCNT1

Software:

Counter1 isn't any different then Counter0. If we don't change the values of the WGMnx registers it will function the same way as Counter0 (well aside from being 16 bit instead of 8 bit that is). So first we set our mode using the WGM1n bits within the TCCR1A and TCCR1B register. Then we choose if we want to clock on the falling edge or the rising edge using CS1n within the TCCR1B register. And finally decide if we want to enable the interrupt using the TOIE1 within the TIMSK register.

ATmega8 Code:

    // this code sets up counter1 and with no interrupts in normal mode

    #include <avr/io.h>

    int main(void)
    {
        DDRD &= ~(1 << DDD5);     // Clear the PD5 pin
        // PD5 is now an input

        PORTD |= (1 << PORTD5);   // turn On the Pull-up
        // PD5 is now an input with pull-up enabled

        TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);
        // Turn on the counter, Clock on Rise

        while (1)
        {
            // we can read the value of TCNT1 hurray !!
        }
    }

ATmega8 Code:

    // this code sets up counter1 and with interrupts enabled

    #include <avr/io.h>
    #include <avr/interrupt.h>

    int main(void)
    {
        DDRD &= ~(1 << DDD5);     // Clear the PD4 pin
        // PD5 is now an input

        PORTD |= (1 << PORTD5);   // turn On the Pull-up
        // PD5 is now an input with pull-up enabled

        TIMSK |= (1 << TOIE1);    // enable timer interrupt

        TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);
        // Turn on the counter,

        sei();

        while (1)
        {
            // we can read the value of TCNT1 hurray !!
        }
    }

    ISR (TIMER1_OVF_vect)
    {
        // interrupt just fired
    }

COUNTER2 (8 Bit):

Theory of Operation:

Counter2 - ATmega8

Figure 4: Counter 2

Counter2 is designed to be used with an external Crystal Oscillatory. In fact, it is optimized for a 32.768 kHz XTAL, this will provide you with a very accurate Real Time Clock. Because this is a lot closer to being a Timer then a counter I will cover this topic in the Timer tutorial.

Lastly, the datasheet states that hooking up a input to TOSC1 is not recommended. I have never done it so I can say what it will do.


Woot, another one bites the dust!


Cheers
Q