4.3 Example 3 : Timer2 Asynchronous Operation

Timer2 can be used in synchronous mode like Timer0 and Timer1. In addition, an asynchronous mode can be used. See the description of the asynchronous clocking in section Clocking by Asynchronous Clock or the data sheet for details.

Example – Timer Output Compare Interrupt

This example shows how to use the timer output compare interrupt of Timer2. The timer will be configured so that the compare match event occurs every second. This feature could be used to implement a RTC. In this example, however, the port pins will be inverted with every compare match event so that PB5 will be blinking with a frequency of 0.5Hz.

Similar to the previous example, PB5 has to be connected to an LED. In addition, a 32.768kHz crystal has to be mounted on the pins TOSC1/PB6 and TOSC2/PB7 of Port B.

The timer settings can be calculated according to Equation 2. As Timer maximum value (MaxVal) the value of the OCR2 has to be used instead. The prescaler clock (PCKx) is in this case the clock signal of the watch crystal (fOSCCK). TOVCK is the overflow frequency which is specified by the application to 1 second. The mathematical description of this relation is shown by the following equation:

A prescaler value of 1024 is selected plus a corresponding OCR2 value of 32 to get the delay time of one second between two Timer compare match events.

The following initialization routine shows how to set up such a system:
init_Ex3:
	ldi r16, (1<<AS2)
	sts ASSR,r16 ; Enable asynchronous mode
				 ; Clear Timer on compare match. Toggle OC2A on Compare Match
	ldi r16, (1<<COM2A0) | (1<<WGM21)
	sts TCCR2A,r16	
				 ; Timer clock = 32768/1024
	ldi r16, (1<<CS22)|(1<<CS21)|(1<<CS20)
	sts TCCR2B,r16
	ldi r16,32
	sts OCR2A,r16 ; Set output compare value to 32
	sbi DDRB, PORTB3 ; Set OC2A pin as output
	lds r16, ASSR ; Refer ATmega328PB datasheet section
				  ;'Asynchronous Operation of Timer/Counter2'
	andi r16, ((1 << OCR2AUB) | (1 << OCR2BUB) | (1 << TCR2AUB) | (1 << TCR2BUB) | (1<< TCN2UB))
	brne PC-0x03
	ldi r16, (1 << TOV2) | (1 << OCF2A) | (1 << OCF2B)
	sts TIFR2,r16 ; Clear pending interrupts
	ldi r16,1<<OCIE2A
	sts TIMSK2,r16 ; Enable timer output compare interrupt
	ret 

The corresponding C code can be as follows:
void init_Ex3(void)
{
	/* Select clock source as crystal on TOSCn pins */
	ASSR |= 1 << AS2;
	/* Clear Timer on compare match. Toggle OC2A on Compare Match */
	TCCR2A = (1<<COM2A0) | (1<<WGM21);
	/* Timer Clock = 32768 Hz / 1024 */
	TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20);
	/* Set Output Compare Value to 32. Output pin will toggle every second */
	OCR2A  = 32;
	/* Wait till registers are ready
	 * Refer ATmega328PB datasheet section
	 * 'Asynchronous Operation of Timer/Counter2' */
	while ((ASSR & ((1 << OCR2AUB) | (1 << OCR2BUB) | (1 << TCR2AUB) 
		| (1 << TCR2BUB) | (1<< TCN2UB))));
	/* Clear pending interrupts */
	TIFR2  = (1 << TOV2) | (1 << OCF2A) | (1 << OCF2B);
	/* Enable Timer 2 Output Compare Match Interrupt */
	TIMSK2 = (1 << OCIE2A);
	/* Set OC2A pin as output */
	DDRB |= (1 << OC2A_PIN);
}

In the next step the interrupt service routine has to be implemented. This routine will be executed with every output compare event. The purpose in this example is to toggle an LED connected to PB5.
ISR_OCIE2A:
	push r16
	in r16,SREG
	call TOGGLEPIN
	out SREG,r16
	pop r16
	reti

The corresponding C code can be as follows:
ISR(TIMER2_COMPA_vect)
{
	/* Toggle a pin to indicate compare interrupt */
	PORTB  ^= (1 << USER_LED);
}