HY Leute!
Hab ein großes Problem!! Wenn ich eine us erzeugen will, nehme ich diese
delay_us(1) Funktion her und es funktioniert. Jedoch will ich flexibel
sein und alle möglichen zeiten einstellen können. Ich hab es zuerst mit
einer for Schleife probiert, in welcher die Funktion x mal aufgerufen
wird.
Beim Nachmessen bin ich draufgekommen, dass es die Zeit größer
ist(warscheinlich + Abarbeitungszeit). Dann hab ich probiert eine
Variable der delay_us(VAR) zu übergeben - ging auch nicht
Hat von euch irgendwer ne Idee, wie ich das in Griff bekomme?
Vielleicht die FUnktion delay_us(unsigned int n) irgendwie ändern???
Naja, _delay_us() lebt davon, dass das Argument vom Compiler zur
Compilezeit ausgewertet werden kann. Gerade bei kurzen
Verzögerungen (und dafür ist _delay_us() ja da) kommt bei einer
weiteren Schleife natürlich zusätzlicher Overhead hinzu.
Bei den längeren Schleifen, die _delay_ms() benutzt, ist der
Einfluss einer äußeren Schleife dann deutlich geringer. Was
daher brauchbar funktioniert ist sowas wie:
1
voiddelay_1s(void)
2
{
3
uint8_ti;
4
5
for(i=0;i<100;i++)
6
_delay_ms(10);
7
}
10 ms sind für alle derzeitigen AVRs (max. 20 MHz Takt) im sicheren
Bereich, der von _delay_ms() erfasst werden kann.
Ansonsten der übliche Hinweis: diese Funktionen sind für kurze
Wartezeiten gedacht, bei denen es sich nicht lohnt, erst einen
Timer anzuwerfen. Das Timing der gesamten Applikation sollte man
aber bitte denen überlassen, die darauf spezialisiert sind. Man
muss wohl nicht erst in den Gelben Seiten nachgucken um rauszufinden,
dass dafür die Timer da sind...
Jörg Wunsch wrote:
>> Wirklich genau geht es eigentlich nur in Assembler>> Was anderes machen die diversen _delay_XXX-Funktionen nicht.
Das ist schon klar, aber diese sind in diesem Fall nicht nutzbar,
zumindest nicht unverändert.
Man könnte aber die _delay_loop_2(uint16_t __count) Funktionen aus der
delay.h aufrufen.
Benedikt K. wrote:
> Das ist schon klar, aber diese sind in diesem Fall nicht nutzbar,> zumindest nicht unverändert.
Warum nicht?
Du hast halt den Overhead der äußeren Schleife, aber den hast du
bei einer Assemblerimplementierung ebenfalls, da du ja keine
Bruchteile von Befehlen abziehen kannst.
> Man könnte aber die _delay_loop_2(uint16_t __count) Funktionen aus der> delay.h aufrufen.
Genau das macht ja _delay_ms(), nur dass es den Compiler noch den
Wert __count berechnen lässt.
Das sage ich ja, man müsste die _delay_xs() neu schreiben, so dass der
Rechenaufwand von µs/ms in Takte kleiner wird und kompensiert wird, und
den berechneten Wert dann an die _delay_loop_2(uint16_t __count)
weitergeben.
Naja, viel sinnvoller ist es, dann doch lieber die Timer zu benutzen,
statt endlos Gehirnschmalz darüber zu verbraten, wie man die CPU
möglichst zyklengenau elektrische Energie in Wärme umwandeln lassen
kann...
Die delay-Funktionen (egal welche) sind sinnvoll für Dinge wie das
Timing eines HD44780-Zugriffs oder einer 1-wire-Routine einzustellen,
aber nicht dafür, dass man das Zeitraster der kompletten Applikation
damit zusammenbaut. Das können Timer viel effektiver.
Damit wären wir wieder bei dem was ich zuerst geschrieben habe: Timer
sind klar die bessere Wahl, vor allem wenn es genau sein soll.
Ich muss gestehen: Für viele Sachen nutze ich die _delay_ms() Makros
gerne auch, um einige 100ms oder gar mehrer Sekunden Pause einzufügen.
Wenn der µC sowiso auf den Benutzer warten muss, dann ist es egal ob
dieser in einer sinnlosen Warteschlange auf den Timer wartet, oder
solange Werte runterzählt.
Benedikt K. wrote:
> Damit wären wir wieder bei dem was ich zuerst geschrieben habe: ...
Ich auch. :-)
> Ich muss gestehen: Für viele Sachen nutze ich die _delay_ms() Makros> gerne auch, um einige 100ms oder gar mehrer Sekunden Pause einzufügen.
Für einen schnellen Prototypen nehme ich sie auch gern.
> Wenn der µC sowiso auf den Benutzer warten muss, dann ist es egal ob> dieser in einer sinnlosen Warteschlange auf den Timer wartet, oder> solange Werte runterzählt.
Naja, ich habe mir mittlerweile angewöhnt, am Ende der main loop
immer ein sleep_mode() mit einzubauen. Egal, wie viel Strom es
wirklich spart, schaden kann's nicht.
@ Benedikt K. (benedikt)
>Ich muss gestehen: Für viele Sachen nutze ich die _delay_ms() Makros>gerne auch, um einige 100ms oder gar mehrer Sekunden Pause einzufügen.>Wenn der µC sowiso auf den Benutzer warten muss, dann ist es egal ob>dieser in einer sinnlosen Warteschlange auf den Timer wartet, oder>solange Werte runterzählt.
Nöö, bei _delay_ms() verbrät er mit maximalem Takt Energie, beim Timer
kann man zumindest in den Idle Sleep Mode schalten. Ist in mobilen
Geräten sicher keine schlechte Idee.
MfG
Falk
Das ist klar, dann kann man sogar den Bedientaster an den INT Pin hängen
und den µC komplett abschalten.
Wenn das ganze aber sowiso an einem 5V 5A Netzteil hängt, dann sind die
paar mA sch... egal. Das Backlight des Displays (dessen Text der
Benutzer gerade liest) verbraucht da schon sehr viel mehr.
Ich versuche generell immer möglichst sparsam zu programmieren, aber man
muss es ja nicht übertreiben.
> Nöö, bei _delay_ms() verbrät er mit maximalem Takt Energie, beim Timer> kann man zumindest in den Idle Sleep Mode schalten. Ist in mobilen> Geräten sicher keine schlechte Idee.
Kommt halt immer auf das Einsatzgebiet an. Ich habe meistens keine so
eingeschränkte Stromversorgung, dafür aber manchmal recht enge Timings
einzuhalten. Die Reaktionszeit auf einen Interrupt aus dem Sleep-Mode
heraus ist aber höher als aus dem Normalbetrieb.