did some rework and fine tuning of the delayMicroseconds code, see - bug in delayMicroseconds() when called with 0 · Issue #1121 · arduino/Arduino · GitHub -
Resulted in more accurate timing for values up to 100uSeconds (above not tested)
/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */
void delayMicroseconds(unsigned int us)
{
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
// delay_us(us);
#if F_CPU == 20000000L
// for the 20 MHz clock on rare Arduino boards
// handle 0 and 1
if (us == 0) return;
__asm__ __volatile__ (
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop");
if (us == 1) return;
// calc # iterations
us = (us<<2) + us; // x5 us
// account for the time taken in the preceeding commands.
us -= 7;
#elif F_CPU == 16000000L
// for the 16 MHz clock on most Arduino boards
// handle 0 and 1
if (us == 0) return;
if (us == 1) return;
// calc # iterations
us <<= 2;
// account for the time taken in the preceeding commands.
us -= 5;
#elif F_CPU == 8000000L
// for the 8 MHz internal clock on the ATmega168
// handle 0, 1;
if (us < 2) return;
// handle 2;
if (us == 2) return;
// calc # iterations
us <<= 1;
// account for the time taken in the preceeding commands.
us -= 5;
// quarter uSecond adjust
__asm__ __volatile__ (
"nop\n\t"
);
#elif F_CPU == 1000000L
// TODO 1 MHz
#error "delayMicroseconds: 1 MHz not supported yet"
# else
#error "delayMicroseconds: not supported clockspeed"
#endif
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
}
16MHz now gives the following output:
delayMicroseconds(0) => 0.81920 ==> inf
delayMicroseconds(1) => 1.01880 ==> 0.01880
delayMicroseconds(2) => 2.02280 ==> 0.01140
delayMicroseconds(3) => 3.02880 ==> 0.00960
delayMicroseconds(4) => 4.03520 ==> 0.00880
delayMicroseconds(5) => 5.04080 ==> 0.00816
delayMicroseconds(10) => 10.07080 ==> 0.00708
delayMicroseconds(20) => 20.13200 ==> 0.00660
delayMicroseconds(50) => 50.31200 ==> 0.00624
delayMicroseconds(100) => 100.61360 ==> 0.00614
Last column is the relative error (inf due to divide by zero) and it is decreasing which is good. The value for DMS(0) is as good as it gets.