Timer and Counter Interrupts

From Nutwiki
Jump to: navigation, search

AVR - How to Configure a Timer Compare Interrupt

Macros to define a time period, feel free to change 1ms to e.g. 4 etc.

#define SAMPLE_PERIOD		1	//[ms]
#define TIMER1_DIVISOR		14745600/(1000/SAMPLE_PERIOD)	//NUT_CPU_FREQ/...

This routine is periodically called. Note: In case IRQSTACK_SIZE is not defined, you run within an unpredictable context.

void Timer1Process(void *arg)
{
	arg = arg;	//requires gcc compiler (when called from thread)
 			//NutRegisterIrqHandler callback fn has void* argument

	//your fn goes here
}

Following initialization (called only once) generates Timer1Process() interrupt calls every 1ms (0.999959 ms).

16 bit timer is used for accuracy. If timer2 (8bit) is used, you can reach 1,11111 ms (prescaler 128, OCR=128)

void Timer1Init(void)
{
#ifdef MCU_ATMEGA_2561
	NutIrqDisable(&sig_OUTPUT_COMPARE1A);
#endif
	
	//COM1A, B, C = 0 (Compare Output Mode) = normal (output pin disconnected)
	//WGM = 4 (CTC - Clear Timer on Compare match)
	//CS = 1 (prescaler = 1)

#ifdef MCU_ATMEGA_2561
	outb(TCCR1A, 0);
#endif
	outb(TCCR1B, BV(WGM12) | BV(CS10));	//0x09
#ifdef MCU_ATMEGA_2561
	cbi(TCCR1C, FOC1A);
#endif
	//assume timer is disabled after power up
	//outb(TCNT1H, 0);
	//outb(TCNT1L, 0);

	//divisor
	outb(OCR1AH, TIMER1_DIVISOR >> 8);	//0x39
	outb(OCR1AL, TIMER1_DIVISOR & 0xFF);	//0x99

	NutRegisterIrqHandler(&sig_OUTPUT_COMPARE1A, Timer1Process, 0);

#ifdef MCU_ATMEGA_2561
	NutIrqEnable(&sig_OUTPUT_COMPARE1A);
#elif defined MCU_ATMEGA_128
	sbi(TIMSK, OCIE1A);
#endif
}

See also