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:
Lässt sich vermutlich recht einfach rausrechnen (3-4 Werte ins EXCEL-Sheet...)Code:for (currentCycle=0; currentCycle < totalCycles; currentCycle++){ _delay_ms(MAXIMUM_DELAY_MS); }
Wers selber probieren will...
"myUtil.h"
"myUtil.c"Code:#include "myUtil.c" void delayMilliSeconds(long totalMs);
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; }







Zitieren

Lesezeichen