Forum: Mikrocontroller und Digitale Elektronik AVR-Delay-Funktion!?


von Enrico. J. (ejoerns)


Lesenswert?

Moin, was haltet ihr von dieser Konstruktion einer Warte-Funktion?
Habe versucht mit c eine möglichst genaue und gleichzeitig für längere
Zeitintervalle brauchbare Zeitfunktion zu entwickeln.

Ich hoffe mal, dass ich dort keinen Denkfehler hab..


/** Wartet  genau für die angegebene Anzahl Takte
 *  @param  takte  16-Bit Variable für die Anzahl zu wartener Takte.
 *  @note   Bei 14.7456Mhz entsprich das etwa einer maximalen Wartedauer
 *          von 4,444ms
 *  @note   Die minimale Wartezeit liegt bei 17/F_CPU, also etwas über 
1us bei
 *          14,17456Mhz.
 *  @note   Mit avr-gcc-Flag '-s' compilieren!
 **/
void waitTakte(uint16_t takte){
// specifies how long the actions take (for calculating cycle numbers)
#define LOOP_CLOCKS 8
#define CALC_CLOCKS 17
  // takes 17 clock cycles
  takte /= LOOP_CLOCKS;
  // this loop takes 8 cylces with 16-bit var 'takte'!
  while (takte > (uint8_t) (CALC_CLOCKS/LOOP_CLOCKS)) {
    asm volatile("nop");
    takte--;
  }
}

Viele Grüße, Enrico

von STK500-Besitzer (Gast)


Lesenswert?

>was haltet ihr von dieser Konstruktion einer Warte-Funktion?
Ich persönlich gar nichts.

>Habe versucht mit c eine möglichst genaue und gleichzeitig für längere
>Zeitintervalle brauchbare Zeitfunktion zu entwickeln.
Dafür kann man auch Timer benutzen...

von Falk B. (falk)


Lesenswert?

@  Enrico J. (ejoerns)

>Moin, was haltet ihr von dieser Konstruktion einer Warte-Funktion?

Sie ist schlecht. Die bereits vorhandenen _delay_ms() und _delay_us() 
sind um Längen besser.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

>Habe versucht mit c eine möglichst genaue und gleichzeitig für längere
>Zeitintervalle brauchbare Zeitfunktion zu entwickeln.

Was mal vollkommen daneben gegangen ist. Besser so.

AVR - Die genaue Sekunde / RTC

MFG
Falk

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Wieso verwendest Du Defines innerhalb einer Funktion?

Sowas macht man in einer Header-Datei oder am Programmanfang (wenn es 
nur eine Datei ist), wenn die Konstanten einfach änderbar sein sollen. 
Ansonten kannst Du die Werte (vor allem, wenn sie nur einmal benutzt 
werden) auch direkt in die Funktion schreiben.

Übrigens:
CALC_CLOCKS/LOOP_CLOCKS = 2

von Enrico. J. (ejoerns)


Lesenswert?

@STK500-Besitzer: Und wenn ich die für was anderes brauche?

@Falk Brunner: Was genau ist daneben gegangen?
Die Funktionen aus delay.h haben doch schon ein sehr eingeschränkten 
Zeitbereich!

@Christian H.: Die Defines sind nur um (mir) klar zu machen wo die Werte 
herkommen ;)
Fühle mich sogar in der Lage 17/8 zu rechnen ;) Aber das tut der 
dortigen Schreibweise, bzw. dem Programmcode, der dabei rauskommt ja 
nicht sonderlich weh...
Des weiteren machts auch kein Sinn alle Defines in ne Header auszulagern 
;)

Danke schonmal für die Kommentare

von Gast (Gast)


Lesenswert?

Ich code nur ASM, deshalb sorry wenn die Fragen doof sind, aber woher 
weisst du wieviele Takte die while-Abfrage und das "takte--;" brauchen? 
Das kann man doch bei C nie eindeutig vorhersagen wenn ich recht 
informiert bin. Und damit waere das ganze eben nicht Taktgenau.

von Enrico. J. (ejoerns)


Lesenswert?

Ich gehe davon aus, dass zumindest für den Controller in der selben 
Optimierungsstufe der Code immer gleich rauskommt.
Hab mir das ganze im erzeugten Assembler angeschaut. Die Befehle die da 
verwendet werden sind soweit ich das überblicke auf den meisten AVR 
vorhanden und somit denke ich, dass er das auch immer gleich erzeugen 
sollte..

von Falk B. (falk)


Lesenswert?

@  Enrico J. (ejoerns)

>@Falk Brunner: Was genau ist daneben gegangen?

Vieles. Wenn man es genau machen will, muss man im WinAVR reine ASM 
Macros nehmen.

>Die Funktionen aus delay.h haben doch schon ein sehr eingeschränkten
>Zeitbereich!

???
6,5s sollten für eine blockierende Warteschleife mehr als reichen. Mal 
meinen Link gelesen?

MFG
Falk

von Enrico. J. (ejoerns)


Lesenswert?

@ Falk Brunner:

6.5 sec will ich garnicht haben, mir gehts um die genaue Auflösung 
(us-bereich). Und zwar für ein paar mehr µs als nur 50... Die ist bei 
den delay.h definitiv nicht gegeben!

Und wie steht es mit meiner annahme zur codeoptimierung? Überzeugen kann 
mich da bisher noch keine aussage...

von Falk B. (falk)


Lesenswert?

@  Enrico J. (ejoerns)

>6.5 sec will ich garnicht haben, mir gehts um die genaue Auflösung
>(us-bereich). Und zwar für ein paar mehr µs als nur 50... Die ist bei
>den delay.h definitiv nicht gegeben!

Aber sicher, schau dir mal die Schleifen an, die hinter den Makros 
stecken. delay_loop_2 etc. Steht alles in der Doku der libc.

MFG
Falk

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Enrico J. schrieb:
> Und wie steht es mit meiner annahme zur codeoptimierung? Überzeugen kann
> mich da bisher noch keine aussage...

Es gibt auch nur einen einzigen C-Compiler in einer Version. Daher 
machen auch alle immer genau das gleiche. Genauso gibt es nur eine 
einzige Optimierungsoption (naja, gibt es nicht, wenn sie die einzige 
ist).

Wer sagt Dir, dass mein Compiler nicht jedesmal CALC_CLOCKS/LOOP_CLOCKS 
neu ausrechnet?

Überzeugt?

Ach ja, ich verwende gerne 16MHz oder 20MHz Takt. Muss mir wohl doch 
eine eigene Version schreiben.

von Peter D. (peda)


Lesenswert?

Enrico J. schrieb:
> Moin, was haltet ihr von dieser Konstruktion einer Warte-Funktion?
> Habe versucht mit c eine möglichst genaue und gleichzeitig für längere
> Zeitintervalle brauchbare Zeitfunktion zu entwickeln.

Für Genauigkeit sind ja die Timer da.

Da keines meiner Programme ohne Interrupts auskommt, geb ich auf die 
Genauigkeit von Delays keinen Pfifferling.

Ich benutze sie zur Einhaltung von Minimalzeiten, z.B. bei LCD-Ausgaben.
Daß die Zeiten durch Interrupts größer werden, kann man nicht verhindern 
und darf daher nicht stören.


Peter

von gast (Gast)


Lesenswert?

delays nutz ich nur mein sachen wo sinnlos zeit vertrödelt werden kann
also LCD ausgane im neü und ma ne sek warten

ansonst ... garkeit delay
das ganze eben so bauen das man sowas ganrnicht erst brauch
LCDs laufen dank busyabfrage auch ganz ohne delays

die _delay_ms() sollten opimiert genug sein ..

von Peter D. (peda)


Lesenswert?

gast schrieb:
> LCDs laufen dank busyabfrage auch ganz ohne delays

Das ist Quatsch.
Du wartest dann auch, bloß die Zeitdauer ist etwas kürzer.
Ich denke nicht, daß die Zeitangaben im Datenblatt wesentlich über den 
Busy-Zeiten liegen.
D.h. die CPU-Last durch das LCD sinkt vielleicht von 1% auf 0,5%.
Da spare ich mir lieber den extra Pin für das Busy-Waiting.


Peter

von Enrico. J. (ejoerns)


Lesenswert?

So, jetzt bin ich auch mal wieder on board^^

Aaalso...

@Falk Brunner
>Aber sicher, schau dir mal die Schleifen an, die hinter den Makros
>stecken. delay_loop_2 etc. Steht alles in der Doku der libc.

War aus unerfindlichen Gründen davon ausgegangen, dass die Funktionen 
Integer übernehmen, was ja bedeuten würde, dass bei ner etwas längeren 
Wartezeit nur noch ne ms-auflösung bereitgestellt würde... ;)
Dafür sollte aber die für die Vorberechnung die Genauigkeit schon etwas 
drunter leiden (zumindest bei kurzen Wartezeiten die Relaitve), oder?

Aber die delay.h ist ja schon iwie fast was ich gemacht hab, mit dem 
Unterschied, dass bei meiner Version die direkte Anzahl Takte angegeben 
werden kann.

@Christian H.
>Es gibt auch nur einen einzigen C-Compiler in einer Version. Daher
>machen auch alle immer genau das gleiche. Genauso gibt es nur eine
>einzige Optimierungsoption (naja, gibt es nicht, wenn sie die einzige
>ist).

Exzessiver Gebrauch von Ironie ist selten förderlich, aber 
nichtsdestotrotz hab ich ja beschrieben, dass das ganze nur unter 
bestimmten Einschränkungen läuft (avr-gcc, -s). Und vorrangig soll sie 
erstmal für meine Zwecke funktionieren ;).

>Wer sagt Dir, dass mein Compiler nicht jedesmal CALC_CLOCKS/LOOP_CLOCKS
>neu ausrechnet?

Alles andere wäre doch seehr stupide...

@Peter Dannegger:
>Für Genauigkeit sind ja die Timer da.

Mal schaun, vllt. muss ich doch noch einen Timer opfern, den ich eig. 
nicht habe.. mal sehn ;)

von Falk B. (falk)


Lesenswert?

@  Enrico J. (ejoerns)

>Dafür sollte aber die für die Vorberechnung die Genauigkeit schon etwas
>drunter leiden (zumindest bei kurzen Wartezeiten die Relaitve), oder?

???
Keinesfalls.

>Unterschied, dass bei meiner Version die direkte Anzahl Takte angegeben
>werden kann.

Kann man auch in den delay Funktionen. Einfach _delay_loop_2 nehmen.

MFG
Falk

von Enrico. J. (ejoerns)


Lesenswert?

aus delay.h:

>Delay loop using a 16-bit counter __count, so up to 65536 iterations are
>possible. (The value 65536 would have to be passed as 0.) The loop
>executes four CPU cycles per iteration, not including the overhead the
>compiler requires to setup the counter register pair.

oder was verstehe ich da nicht?..

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Falls die Makros der avr-libc zu ungenau sind:

Es gibt auch
  Beitrag "Delay: Exakt n Ticks erzeugen (avr-gcc)"

Damit lassen sich Ticks im Bereich von 0 bis 2^18 exakt erzeugen, also 
ohne einen Tick mehr oder weniger als angefordert! Die Anzahl der Ticks 
muss dazu allerdings zur Compilezeit (bzw. Assemble-Zeit) bekannt sein.

Johann

von Enrico. J. (ejoerns)


Lesenswert?

Das schaut doch mal sehr brauchbar aus :) Danke!

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.