Why is micros() so much slower than millis()?

Like an external clock

like an RTC ?

Yeh

The ones I know don't give microsecond information...

if your loop content is only a few hundred nano-seconds, you need something that has better granularity than what you measure and is fast to access.

➜ so the question is what do you expect the loop to do and how long (ballpark) that would take?

It really depends but interrupts could be used, right?

Ideally you want a counter (timer) which does not need any interruption otherwise you start impacting what you are trying to measure

Yeah. I don't actually need any code to run that fast at this point, but its probably good practice to try to make it as fast as possible

It just needs to be fast enough for the requirements :wink:
(Over engineering a solution might be costly)

1 Like

No. Reading a 32bit microsecond count over a pin would typically be MUCH slower than the current micros() function...

Look, your test code demonstrates that micros() is much slower than millis(), but that's been explained: millis() is a very simple function that doesn't do much, so it is VERY fast. micros() does more work - it combines two separate counters (millisecond interrupts and individual timer ticks) with some moderate math. Easily several times more complicated, and millis() may get in-lined as well.

But that doesn't mean that micros() is actually SLOW! Here's the object code generated for micros() on an Uno:

unsigned long micros() {
        unsigned long m;
        uint8_t oldSREG = SREG, t;
     3da:       3f b7           in      r19, 0x3f       ; 63
        
        cli();
     3dc:       f8 94           cli
        m = timer0_overflow_count;
     3de:       80 91 ad 01     lds     r24, 0x01AD
     3e2:       90 91 ae 01     lds     r25, 0x01AE
     3e6:       a0 91 af 01     lds     r26, 0x01AF
     3ea:       b0 91 b0 01     lds     r27, 0x01B0     ;timer0_overflow_count
        t = TCNT0;
     3ee:       26 b5           in      r18, 0x26       ; 38
        if ((TIFR0 & _BV(TOV0)) && (t < 255))
     3f0:       a8 9b           sbis    0x15, 0 ; 21
     3f2:       05 c0           rjmp    .+10            ; 0x3fe <micros+0x24>
     3f4:       2f 3f           cpi     r18, 0xFF       ; 255
     3f6:       19 f0           breq    .+6             ; 0x3fe <micros+0x24>
                m++;
     3f8:       01 96           adiw    r24, 0x01       ; 1
     3fa:       a1 1d           adc     r26, r1
     3fc:       b1 1d           adc     r27, r1
        SREG = oldSREG;
     3fe:       3f bf           out     0x3f, r19       ; 63
        
        return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
     400:       ba 2f           mov     r27, r26
     402:       a9 2f           mov     r26, r25
     404:       98 2f           mov     r25, r24
     406:       88 27           eor     r24, r24
     408:       bc 01           movw    r22, r24
     40a:       cd 01           movw    r24, r26
     40c:       62 0f           add     r22, r18
     40e:       71 1d           adc     r23, r1
     410:       81 1d           adc     r24, r1
     412:       91 1d           adc     r25, r1
     414:       42 e0           ldi     r20, 0x02       ; 2
     416:       66 0f           add     r22, r22
     418:       77 1f           adc     r23, r23
     41a:       88 1f           adc     r24, r24
     41c:       99 1f           adc     r25, r25
     41e:       4a 95           dec     r20
     420:       d1 f7           brne    .-12
}
     422:       08 95           ret

(and yes, if you're going to be this nit-picky about the speed of code, you DO need to learn how to interpret the object code!)

I count about 50 cycles for the whole thing; about 3 microseconds execution time. Reading 32bits via a pin would take at least 128 cycles (read a bit, merge into count, loop, times 32...), and that doesn't include clocking or waiting for a slower serial protocol (I2C, used by many clocks, runs at ~400kHz, so that would be 80 microseconds (1280 cycles) just waiting for the bits to arrive.)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.