Das was ich da vor langer Zeit mal gecoded hatte funktioniert übrigens auch recht gut aufm AVR (ATMega-2560 @16MHz)

Test mit AVR-Simulator:
Aufruf: delayMilliSeconds(137);
Dauer: 138.950us = 138,95ms

macht knapp 2% Fehler

Ich vermute sehr stark, dass das einfach ein konstanter Faktor ist, den man mit einrechnen. Der Großteil wird wohl konstant innerhalb folgender Schleife verbraten:

Code:
	for (currentCycle=0; currentCycle < totalCycles; currentCycle++){
		_delay_ms(MAXIMUM_DELAY_MS);
	}
Lässt sich vermutlich recht einfach rausrechnen (3-4 Werte ins EXCEL-Sheet...)

Wers selber probieren will...

"myUtil.h"
Code:
#include "myUtil.c"

void delayMilliSeconds(long totalMs);
"myUtil.c"
Code:
/**
 * Converts an double value to an integer
 */
int doubleToInteger(double d);


/**
 * AVRs cannot sleep more than the following per _delay_ms()-Call
 * MAXIMUM_DELAY_MS = 262,2ms / F_CPU_in_MHz
 */
#ifdef F_CPU
	#define MAXIMUM_DELAY_MS (262 / (F_CPU / 1000000))
#endif


void delayMilliSeconds(long totalMs){
	long totalCycles; // Max-number of cycles
	long rest; // Rest of the flolowing integer-division

	// Calculate the total amount of cycles neccessary to reach the wanted delay
	totalCycles = doubleToInteger(totalMs / MAXIMUM_DELAY_MS);

	// Calculate the rest that has been lost due to integer-division
	rest = totalMs - (totalCycles * MAXIMUM_DELAY_MS);
	
	// Will hold the current Cycle
	int currentCycle;

	// Work out all full cycles
	for (currentCycle=0; currentCycle < totalCycles; currentCycle++){
		_delay_ms(MAXIMUM_DELAY_MS);
	}

	// Work out the rest if there is one
	if(rest != 0){
		_delay_ms(rest);
	}

}

int doubleToInteger(double d){
	return d;
}