www.mikrocontroller.net

Forum: Compiler & IDEs delay_us()


Autor: Mike (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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???

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
void delay_1s(void)
{
  uint8_t i;

  for (i = 0; i < 100; i++)
    _delay_ms(10);
}

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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wirklich genau geht es eigentlich nur in Assembler und/oder mit einem 
Timer.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wirklich genau geht es eigentlich nur in Assembler

Was anderes machen die diversen _delay_XXX-Funktionen nicht.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.