Forum: Compiler & IDEs delay_us()


von Mike (Gast)


Lesenswert?

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???

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
void delay_1s(void)
2
{
3
  uint8_t i;
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...

von Benedikt K. (benedikt)


Lesenswert?

Wirklich genau geht es eigentlich nur in Assembler und/oder mit einem 
Timer.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Wirklich genau geht es eigentlich nur in Assembler

Was anderes machen die diversen _delay_XXX-Funktionen nicht.

von Benedikt K. (benedikt)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Benedikt K. (benedikt)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Benedikt K. (benedikt)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Falk (Gast)


Lesenswert?

@ 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


von Benedikt K. (benedikt)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

> 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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.