Examination of the Arduino micros() Function

us clock


To fully understand the micros() function, you first need to understand the Timer #0 overflow interrupt handler which was covered in this post.

Recall the typical Ardiuno runs on a 16MHz oscillator. Both the millis() and micros() functions base their calculations on the Arduino Timer #0, which is running with a prescale of 64. This results in the timer ticking at 64*1/16,000,000th of a second (which is 0.000004 seconds or evey 4 µs). Its important to take note of this because the resolution of micros() is therefore 4 µs.

Also recall that since the Timer #0 counter (TCNT0) is 8-bit, it “rolls over” or “overflows” after every 256 ticks. This means an overflow occurs every 1/16,000,000(oscillator) * 64(prescale) * 256(roll over) = 0.001024 seconds, or 1.024 ms, or 1024 µs.

Expand a Macro

Now, let’s do some additional math so we can substitute a number in the place of the following macro (this macro is embedded inside an Arduino hardware file):

#define clockCyclesPerMicrosecond () ( F_CPU / 1000000L )

F_CPU is the oscillator frequency, and is defined during compilation. We already know this is 16,000,000, which makes:

clockCyclesPerMicrosecond = 16,000,000/1,000,000 = 16

micros() Simplified

I’ve removed some housekeeping steps which check for the potential rare instance of an interrupt occurring during the micros() function call and substituted the expanded macro from above. What is left is simply the meat of the function, which calculates the elapsed microseconds:

unsigned long micros() {
  return((timer0_overflow_count << 8) + TCNT0)*(64/16);

Knowing all this boils the micros() calculation down to:

micros = (Timer #0 counter + (number of times timer #0 has overflowed * 256)) * 4

Actual Arduino micros() Function:

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;
	m = timer0_overflow_count;
#if defined(TCNT0)
	t = TCNT0;
#elif defined(TCNT0L)
	t = TCNT0L;
	#error TIMER 0 not defined

#ifdef TIFR0
	if ((TIFR0 & _BV(TOV0)) && (t & 255))
	if ((TIFR & _BV(TOV0)) && (t & 255))

	SREG = oldSREG;
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());

Do you wish you could read and write inline assembly code for the Arduino? Check out the book with greatly expanded coverage!

[click on the image]

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , , , . Bookmark the permalink.

7 Responses to Examination of the Arduino micros() Function

  1. So the ‘micros()’ function itself already spoils the accuracy of the measurement? What’s the point then? (see my other post on FIXED POINT issue)

  2. Teo says:

    Hi. Is there any way I can modify this code to generate the number of nanoseconds since the arduino has started? Like an “nanos()” function…

    • Control says:

      Since a clock cycle will take 1/16.000.000 = 63 nanoseconds , the accuracy of your nanos function would be just 63 nanoseconds. I recommend to code your own functions with Timer0.

  3. Homayon says:

    How can I build micros for timer1?

    • Jim Eli says:

      First consider, Timer 1 is used by the servo library. Using it would invalidate the library. Second, I haven’t looked through the datasheet to see if the functionality of Timer 0 could be duplicated with Timer 1 (for example, Timer 0 is 8-bit and Timer 1 is 16-bit). Otherwise, simply transfer the setup to the Timer 1 registers.

      This is a great place to start.

  4. Memo says:

    how to get timer0_overflow_count because I tried this function with another name and it didn’t work

    • Jim Eli says:

      timer0_overflow_count is defined inside the wiring.c file as,

      volatile unsigned long timer0_overflow_count = 0;

      You should be able to access this variable by placing the following definition inside your code:

      extern volatile unsigned long timer0_overflow_count;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s