The ATMega328 has 3 timers that can used in various ways including keeping time, triggering interrupts, PWM etc. Arduino uses up TIMER0 for functions such as millis
, micros
etc.
TIMER1 and TIMER2 are available. Below is a contrived example of building a custom timer based on TIMER2. The code is designed to run on a processor clocked at 16MHz and prints out some text at 1Hz. A prescaler of 1024 is combined with a counter to 251. This gives a counter up to: 16e6/(1024*251) = 62.25. Counting up to 62 gives a time very close to 1 sec.
See the Basic AVR page for details on the registers used.
volatile uint32_t counter = 0; // Interrupt based on Compare Match A vector ISR(TIMER2_COMPA_vect) { counter++; } long ms = 0; void setup() { Serial.begin(9600); Serial.println("Ready..."); // Reset, then setup for CTC TCCR2A = 0; TCCR2A |= _BV(WGM21); // Reset, then setup with prescaler: 1024 TCCR2B = 0; TCCR2B |= (_BV(CS22) | _BV(CS21) | _BV(CS20)); // Comparator A value that triggers interrupt OCR2A = 251; // Setup interrupt on Comparator Match A TIMSK2 |= _BV(OCIE2A); ms = millis(); } uint16_t secs = 0; void loop() { boolean print_time = false; // It's essential to suspend interrupts while manipulating counter uint8_t oldSREG = SREG; cli(); if (counter>=(62)) { print_time = true; counter = 0; } SREG = oldSREG; if (print_time) { Serial.print(secs++); Serial.print(" : "); Serial.println(millis()-ms,DEC); ms = millis(); } }