AVR Timer2 asynchronous mode

We have almost gone through main modes of AVR timers. It is impossible to review them all in more details as there are lots of special uses and cases. Anyway we will get back to them in future as lots of routines are usually based on timer operations.

We haven’t touched Timer/Counter2 which is actually another 8 bit timer of Atmega328. This is very similar to Timer0 with all pretty same features including CTC, fast PWM and correct phase PWM modes. If you can run these modes in Timer0 then this will be easy doing on Timer2. The only difference is the naming of registers. So lets leave this behind and get to something new and untouched. As I mentioned before each timer has something unique making them useful in special occasions. So this one isn’t exception. It has an special asynchronous timing mode which can be set to count events from external clock source or be clocked with 32.768kHz crystal.

Asynchronous is less predictable

When operating in asynchronous timer mode there are some dangers to get wrong results. As datasheet says counter, compare and control registers must be preserved when switching between synchronous mode and asynchronous in order to avoid corruption. Also there is an additional Asynchronous Status Register (ASSR) used, which allows selecting asynchronous modes and holds busy status bits of register indicating successful register update. Atmega328 doesn’t have dedicated pins for this – it uses TOSC1 and TOSC2 pins. So this leaves us without main crystal oscillator or other external clock source. So we can have two options – clock microcontroller with 32kHz crystal (or other external clock on TOSC1 pin) or use internal oscillator.

Clocking timer with 32kHz crystal

Probably you know what 32.768kHz crystals are mainly used for? In most cases it is used to clock real Time Clocks (RTC). Such frequency is chosen because it may be scaled down to 1Hz by dividing it by 2 fifteen times. Of course there are some historical issues and price. Making lower frequency crystals souls lead to higher prices and dimensions. So why bother changing things these already do great job and are available on every corner. This frequency is convenient for our 8 bit timer as it may be scaled down to 1Hz with prescaller 128. Dividing 32768 by 128 gives 256 – one full counter with overflow interrupt. So we are going to us this. Lets make a simple 1Hz LED flasher.

In our program microcontroller is clocked with internal 1MHz clock source while Timer2 is clocked by 32.768kHz crystal.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//Prepare LED pin
void PortInit(void)
{
	//Initlally LED OFF
	PORTD&=~(1<<PD0);
	//PD0 as output
	DDRD|=(1<<PD0);
}
//Timer2 init acording datasheet
void RTCInit(void)
{
	//Disable timer2 interrupts
	TIMSK2  = 0;
	//Enable asynchronous mode
	ASSR  = (1<<AS2);
	//set initial counter value
	TCNT2=0;
	//set prescaller 128
	TCCR2B |= (1<<CS22)|(1<<CS00);
	//wait for registers update
	while (ASSR & ((1<<TCN2UB)|(1<<TCR2BUB)));
	//clear interrupt flags
	TIFR2  = (1<<TOV2);
	//enable TOV2 interrupt
	TIMSK2  = (1<<TOIE2);
}
//Overflow ISR
ISR(TIMER2_OVF_vect)
{
	//Toggle pin PD0 every second
	PIND=(1<<PD0);
	asm volatile("nop"::);
	//_delay_us(10);
}
int main (void)
{
	SMCR|=(1<<SM1)|(1<<SM0);
	//Initialize port
	PortInit();
	//Initialise the timer2
	RTCInit();
	//Enable global interrupts
	sei();
	while(1)
	{
		SMCR|=(1<<SE);
		asm volatile("sleep"::);
		SMCR&=~(1<<SE);
		//Do nothing
		
	}
}

This program is almost good enough. But if wee need only to count time, why run core at 1MHz. Running MCU at high speeds consume more energy. For such simple application it is better to clock entire microcontroller from same 32.768kHz crystal. We only have to delete one line from above code:

ASSR = (1<<AS2);

This will make timer be clocked from system clock. Our problem now is to make system to be clocked from 32.768kHz crystal. It can be done by selecting right fuses. Just be careful with setting AVR to such low speed, because not all programmers (especially DIY) will support low baud rates for SPI. In all cases SPI programmer has to run four times slower than MCU clock. I find this web application useful when need to set AVR fuse bits.

If you need to make really efficient RTC of your Atmega328, then you need to use power management. One of options is to put AVR int-to Power-Safe sleep mode where Timer2 can run in asynchronous mode. We will get to sleep modes other time. Next time think twice if you need a separate RTC chip.

Bookmark the permalink.

16 Comments

  1. You can’t run Timer2 and the CPU from the same crystal. The CPU has to be at least 4x the Timer frequency. However, if using a 32.768kHz crystal as your system crystal, the CPU power consumption is very low anyway so just use a regular timer in conjunction with idle power saving mode.

    (p.s. your captcha is set way too sensitive!)

  2. If you set 32.768kHz as system clock – then actually timer will become synchronous. As I mentioned clearing line ASSR = (1<<AS2); will make it possible.

  3. I’m not sure I understand what you mean by “I/O ports are disabled while CPU is sleeping. LEDs won’t light up while sleep”. In sleep, the I/Os stay exactly where you leave them, so a lit LED will stay lit. Clearly, to change an IO while sleeping you’ll need to wake up for a short time.

  4. I made wrong conclusions according to some sources. Removed this part. Thanks.

  5. Pingback: Electronics-Lab.com Blog » Blog Archive » AVR Timer2 asynchronous mode

  6. Why 18 pF and 8 pF, are experimentaly discovered values? I can’t find something find in datastheets.

  7. CAP value should be 18pF. Missed that. Thanks.

  8. And accuracy? Min in Hour or min in day?

  9. If I understand correctly you want to know accuracy of such RTC? It depends on crystal accuracy. Crystals are characterized by frequency tolerance parameter in ppm (parts per million). Lets say 32.768kHz crystal is characterized by -50ppm then it may miss 50 seconds every million seconds. If year has 31536000 seconds then clock might miss 1577 seconds per year or ~26min/year. This means ~4 seconds per day.

  10. @Admin: I found cyrstal /-10ppm, with load capacitance=12,5pF. What’s mean? Can I use 2x18pF as described in schematic? Thanks for sharing.

  11. Correct code:
    //wait for registers update
    while (ASSR & ((1<<TCN2UB)|(1<<TCR2BUB)));

  12. Thank you AAA.
    The loop has to wait for bits to be cleared by hardware.
    Code has been fixed.

  13. you help me too much , too many thanks. I developed a project using a atmega328p with 32768Hz xtal for time, and only put to work correcty after read details of your project.

  14. Great code, been struggling for a while until i found this page. Awesome! Thank You!

  15. The way you toggle the LED is incorrect, it looks like you’re modifying the PIND register when you should be modifying the PORTD register.

  16. error-> TCCR2B |= (1<<CS22)|(1< TCCR2B |= (1<<CS22)|(1<<CS20);

Leave a Reply

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