Zeitverzögerung in C

OP #2299687
Lesenswert?

Hallo.

Ich würde gerne wissen, wie viel Speicherplatz eine delay_ms_(__); 
verbraucht...
Ich habe mal ein Programm mit vielen solcher geschrieben, aber beim 
ATmega16 war irgendwann der Speicher alle...
Da ich für mein Programm warscheinlich ein paar (mehr) Verzögerungen 
brauche, habe ich Befürchtungen, dass nicht alle delays reinpassen.
Gibts sonst noch vergleichbare kleinere Zeitverzögerungen???
Wie viel Speicher verbraucht eine delay-funktion?
#2299704
Lesenswert?

Probiers einfach aus.
Mach ein Programm, compilier es. Im AVR Studio wird dir danach der 
Speicherverbrauch angezeigt.
Dann machst du einen _delay_ms rein und compilierst wieder. Aus dem 
Vergleich der Zahlen von jetzt und vorher kannst du ermitteln wieviele 
Bytes durch den _delay_ms verbraucht wurden.

Aber ein einzelnder _delay_ms wird nicht viel Speicher verbrauchen. Aus 
dem Bauch heraus: vielleicht 10 Bytes Flash, +- ein paar Zerquetschte.
#2299705
Lesenswert?

naja teste es doch aus :) mach ein neues programm nur mit einem delay 
und schau um wie viel es größer ist als ein leeres programm. du kannst 
das delay ja auch in eine funktion packen, die du immer wieder aufrufst, 
oder du realisierst es mit nem timer. das dürfte dann fast gar keinen 
platz verbrauchen
Gast #2299713
Lesenswert?

Oftmals ist/war(?) auch der Fehler eine Variable für die Delay-Funktion 
zu benutzen. Das darf/durfte(?) man nicht...das führte auch immer dazu 
dass der Code unheimlich groß wurde.

Grüße
Gast #2313461
Lesenswert?

> \note In order for these functions to work as intended, compiler
>     optimizations <em>must</em> be enabled, and the delay time
>     <em>must</em> be an expression that is a known constant at
>     compile-time.  If these requirements are not met, the resulting
>     delay will be much longer (and basically unpredictable), and
>     applications that otherwise do not use floating-point calculations
>     will experience severe code bloat by the floating-point library
>     routines linked into the application.

Und daher keine variablen _delay_* :)
Gast #2313467
Lesenswert?

Weil es reinpasst und ich mir die Frage schon länger stelle: Warum hat 
man nicht die eigentliche Delayfunktion in einer Hilfsfunktion mit 
for-Schleife gekapselt um die Verwendung von Variablen zu ermöglichen?

Also statt der aktuellen Funktion (bzw. dem Makro, kompliziertes Zeug) 
sowas
1
#define _internal_delay_ms (...irgendwas...) //don't use this directly. delay must be a constant
2

3
void delay_ms (int delay) //use this in your program
4
{
5
for(;int;int--)
6
  _internal_delay_ms(1);
7
}

Eventuell noch attribute always_inline um den Overhead vom Aufruf zu 
vermeiden.
Gast #2313471
Lesenswert?

Daher gibt's nur eins: Vergesst das leidige delay.
Ihr könnte in dem Programm zu der Zeit sowieso nichts anderes machen, 
lange Delays sind also sowieso ein Problem.

Der vernünftige Weg ist es, an bestimmten Stellen (eigentlich an einer, 
in der Hauptscheife des Programms (alternativ: In einer 
Interrupt-Routine die von eben so einem Timer regelmässig aufgerufen 
wird)) den Timer abzufragen, und zu prüfen, ob es "schon Zeit ist".

Dadurch kann man Programmieren ohne Instruktionen zählen zu müssen, es 
gibt eine Hardwarezeitbasis nach der man sich richten kann, und es 
entsteht ein reaktives Programm, weil es eben nicht an einer Stelle 
hängt, sondern "wenn noch nicht Zeit ist" sich um alles andere kümmern 
kann.

Der Vorteil ist, daß man sich nicht um Unzerbrechungen im Codedurchlauf 
Gedanken machen muß (wenn man nicht anderswo Interrupts verwendet).
#2313522
Lesenswert?

Skript Kiddy schrieb:
> Thomas Eckmann schrieb:
>> Die _delay_ms kann nicht mit einer Variablen aufgerufen werden.
> Versuchs mal. Und du wirst merken, dass es nämlich doch geht. Allerdings
> zu dem Preis, dass die Codegröße ins Unermessliche anwächst.

Nun ja. Das wär noch gar nicht mal so schlimm.
Das eigentliche Problem ist allerdings: Die Zeiten stimmen hinten und 
vorne nicht. Und dieses Problem ist schwerwiegend: Denn das 'Setup' 
welches berechnet, wieviele Durchgänge durch die Verzögerungsschleife 
notwendig ist, braucht selber Zeit die leider nicht konstant ist. D.h. 
man hat eine relativ hohe Untergrenze, unter die man prinzipiell bei der 
Verzögerung nicht kommen kann und der Jitter in der tatsächlichen 
Wartezeit ist hoch.

_delay_ms bzw _delay_us funktionieren nun mal nur dann 
zufriedenstellend, wenn der Compiler schon während des Übersetzens 
ausrechnen kann, wieviele Wiederholungen der zentralen Warteschleife 
notwenig sind und dieses Ergebnis dann auch direkt in Code umsetzt.
#2313523
Lesenswert?

a no nym schrieb:
> Weil es reinpasst und ich mir die Frage schon länger stelle: Warum hat
> man nicht die eigentliche Delayfunktion in einer Hilfsfunktion mit
> for-Schleife gekapselt um die Verwendung von Variablen zu ermöglichen?

Weil dein präsentierter Code impliziert, dass du niemals bei _delay_ms 
eine feinere Auflösung als 1 Millisekunde brauchst.

Den Zeitbedarf, den das Schleifenkonstrukt selber verbraucht hätte man 
noch berücksichtigen können. Allerdings impliziert diese nicht-0-Zeit 
auch, dass es eine Untergrenze gibt, unter die du dann zb mit _delay_ms 
nicht mehr kommen kannst, während _delay_ms(0.9) absolut legal ist und 
auch sinnvollen Code produziert.
#2313603
Lesenswert?

Die Genauigkeit von _delay_ms() kann man aber sowieso nicht unbedingt 
ernst nehmen, weil sie mehr oder weniger geschickt eine bestimmte Anzahl 
an Takten verbrät.

Das kann einer gewünschten Zeit entsprechen, muß aber nicht.
Und zwar aus dem Grund, daß die Funktion nicht merkt, wenn sie 
unterbrochen wird.
Sie ist so kalibriert, daß es ohne Interrupts passt. Hat man aber 
Interrupts, die (beispielsweise und meist hoffentlich übertrieben) 50% 
Last erzeugen, dauert ein _delay_ms(1) auch mal 2 Millisekunden.
Bei 90% Last in den ISR dann entsprechend 10 Millisekunden...
Gast #2313612
Lesenswert?

MaWin schrieb:
> Der vernünftige Weg ist es, an bestimmten Stellen (eigentlich an einer,
> in der Hauptscheife des Programms (alternativ: In einer
> Interrupt-Routine die von eben so einem Timer regelmässig aufgerufen
> wird)) den Timer abzufragen, und zu prüfen, ob es "schon Zeit ist".
Jain. Wenn man bzw. der µP sowieso nichts anderes zu tun hat (das soll 
bei einfachen Programmen vorkommen) kann man auch delay verwenden. Ich 
hatte mal einen Prof der auch krampfhaft (oder krankhaft?) auf die 
Verwendung von Timern bestand, macht einfache Programme nur unnötig 
kompliziert und ist sinnloser Aufwand. Bei komplexeren Sachen ist ein 
Timer natürlich notwendig.

Karl Heinz Buchegger schrieb:
> a no nym schrieb:
>> Weil es reinpasst und ich mir die Frage schon länger stelle: Warum hat
>> man nicht die eigentliche Delayfunktion in einer Hilfsfunktion mit
>> for-Schleife gekapselt um die Verwendung von Variablen zu ermöglichen?
>
> Weil dein präsentierter Code impliziert, dass du niemals bei _delay_ms
> eine feinere Auflösung als 1 Millisekunde brauchst.
>
> Den Zeitbedarf, den das Schleifenkonstrukt selber verbraucht hätte man
> noch berücksichtigen können. Allerdings impliziert diese nicht-0-Zeit
> auch, dass es eine Untergrenze gibt, unter die du dann zb mit _delay_ms
> nicht mehr kommen kannst, während _delay_ms(0.9) absolut legal ist und
> auch sinnvollen Code produziert.

Gut, ich hatte jetzt vergessen bzw. war mir nicht im klaren dass 
_delay_ms mit float zurechtkommt. Für feinere Auflösungen gibt es doch 
aber _delay_µs oder? Demnach könnte man für einfache Zwecke die 
(vielleicht nicht ganz genaue) Funktion delay verwenden welche auch 
Variablen akzeptiert und für genauere Auflösung/Genauigkeit wie bisher 
auf die Makros zurückgreifen welche nur mit Konstanten funktionieren.

Eigentlich ist die Diskussion ja überflüssig (eine for-Schleife kann man 
sich bei Bedarf selber einbauen), aber wenn ich sehe wie oft diese 
Frage hier kommt...

Klaus Wachtler schrieb:
> (Interruptproblem bei delay)
Das ist wohl wahr.
Gast #2313646
Lesenswert?

a no nym schrieb:
> Wenn man bzw. der µP sowieso nichts anderes zu tun hat (das soll
> bei einfachen Programmen vorkommen) kann man auch delay verwenden.

Sofern eben die Genauigkeit keine so große Rolle spielt.

> Ich hatte mal einen Prof der auch krampfhaft (oder krankhaft?) auf die
> Verwendung von Timern bestand, macht einfache Programme nur unnötig
> kompliziert und ist sinnloser Aufwand. Bei komplexeren Sachen ist ein
> Timer natürlich notwendig.

Naja, eine Timer-ISR, die ein Flag setzt, ist ja nun auch nicht gerade 
schwarze Magie.
Gast #2313692
Lesenswert?

Dominik Honnef schrieb:
> Und daher keine variablen _delay_* :)

Dann lies mal genauer. Bei variablem Delay wird die Floatingpoint 
Bibliothek eingebunden und die Vorlaufzeit durch die Berechnung der 
Float Variablen, d.h. bevor die eigentliche Delay-Schleife läuft, wird 
nicht kompensiert. Das führt zu einem Delay entsprechend der Rechenzeit.
Man kann sogar die Rechenzeit bestimmen und beim Aufruf die im Parameter 
angegeben Delayzeit entsprechend korrigieren ;-)

Pauschalaussagen wie "geht nicht" sind einfach Unfug.
Gast #2315713
Lesenswert?

Rolf Magnus schrieb:
> a no nym schrieb:
>> Wenn man bzw. der µP sowieso nichts anderes zu tun hat (das soll
>> bei einfachen Programmen vorkommen) kann man auch delay verwenden.
>
> Sofern eben die Genauigkeit keine so große Rolle spielt.
Wieso? Man kann delays durchaus auf einen Takt genau berechnen bzw. 
programmieren (Interruptproblematik mal außer acht gelassen, simples 
Programm ohne Interrupts z.B.), ob die C-Bibliotheken das können ist 
dann eine andere Frage.
>
>> Ich hatte mal einen Prof der auch krampfhaft (oder krankhaft?) auf die
>> Verwendung von Timern bestand, macht einfache Programme nur unnötig
>> kompliziert und ist sinnloser Aufwand. Bei komplexeren Sachen ist ein
>> Timer natürlich notwendig.
>
> Naja, eine Timer-ISR, die ein Flag setzt, ist ja nun auch nicht gerade
> schwarze Magie.
Nun, für Programmier- und "µC-Anfänger" wie man sie z.B. an der Uni 
findet ist anfänglich alles was mit/in/ um einen µC passiert schwarze 
Magie, da sind Timer für den Anfang nur unnötig kompliziert.
Gast #2315750
Lesenswert?

a no nym schrieb:
> Rolf Magnus schrieb:
>> a no nym schrieb:
>>> Wenn man bzw. der µP sowieso nichts anderes zu tun hat (das soll
>>> bei einfachen Programmen vorkommen) kann man auch delay verwenden.
>>
>> Sofern eben die Genauigkeit keine so große Rolle spielt.
> Wieso? Man kann delays durchaus auf einen Takt genau berechnen bzw.
> programmieren (Interruptproblematik mal außer acht gelassen, simples
> Programm ohne Interrupts z.B.), ob die C-Bibliotheken das können ist
> dann eine andere Frage.

Ich dachte da mehr an periodische Vorgänge. Da zum Delay immer auch noch 
die Zeit für den eigentlichen Algorithmus dazugerechnet werden muß, paßt 
es da nie. Denk z.B. mal an eine Uhr.

>>> Ich hatte mal einen Prof der auch krampfhaft (oder krankhaft?) auf die
>>> Verwendung von Timern bestand, macht einfache Programme nur unnötig
>>> kompliziert und ist sinnloser Aufwand. Bei komplexeren Sachen ist ein
>>> Timer natürlich notwendig.
>>
>> Naja, eine Timer-ISR, die ein Flag setzt, ist ja nun auch nicht gerade
>> schwarze Magie.
> Nun, für Programmier- und "µC-Anfänger" wie man sie z.B. an der Uni
> findet ist anfänglich alles was mit/in/ um einen µC passiert schwarze
> Magie, da sind Timer für den Anfang nur unnötig kompliziert.

Klar, für den blutigen Anfänger. Aber wenn der mal ein paar Ports 
getoggelt und den ADC eingelesent hat, dann ist es bald auch Zeit, sich 
mal mit Interrupts zu beschäftigen.
Persönliche Seite #2315759
Lesenswert?

a no nym schrieb:
> Nun, für Programmier- und "µC-Anfänger" wie man sie z.B. an der Uni
> findet ist anfänglich alles was mit/in/ um einen µC passiert schwarze
> Magie, da sind Timer für den Anfang nur unnötig kompliziert.

Lies mal die Quellen und das Kleingedruckte von _delay_*.
Ist das Einfach?

Und seit wann ist "an der Uni" sein eine Ausrede vor komplizierten 
Dingen???
Gast #2315761
Lesenswert?

Rolf Magnus schrieb:
> Ich dachte da mehr an periodische Vorgänge. Da zum Delay immer auch noch
> die Zeit für den eigentlichen Algorithmus dazugerechnet werden muß, paßt
> es da nie. Denk z.B. mal an eine Uhr.
Ach ok, so war das gemeint. Da hast du wohl recht. Wobei wohl kaum 
jemand eine Uhr mit delays (und ohne Timer) basteln würde...


> Klar, für den blutigen Anfänger. Aber wenn der mal ein paar Ports
> getoggelt und den ADC eingelesent hat, dann ist es bald auch Zeit, sich
> mal mit Interrupts zu beschäftigen.
Stimmt. Trotzdem, für irgendwelches "Kleinzeug". z.B. einen tiny der 
eine Fernbedienung simuliert bei der immer die gleichen Tasten gedrückt 
werden (anschalten, Quellenauswahl, ...) kann man imho beruhigt delays 
nehmen. Was natürlich kein Vorwand ist sich nicht mit Timern zu 
befassen!
Gast #2315769
Lesenswert?

Johann L. schrieb:
> a no nym schrieb:
>> Nun, für Programmier- und "µC-Anfänger" wie man sie z.B. an der Uni
>> findet ist anfänglich alles was mit/in/ um einen µC passiert schwarze
>> Magie, da sind Timer für den Anfang nur unnötig kompliziert.
>
> Lies mal die Quellen und das Kleingedruckte von _delay_*.
> Ist das Einfach?
Es sollte es imho sein... ;-)

> Und seit wann ist "an der Uni" sein eine Ausrede vor komplizierten
> Dingen???
Natürlich muss man sich auch mit Timern befassen, aber vielleicht nicht 
sofort. Für das erste "Hallo Welt" = blinkende LED tut es auch ein 
delay, ggf. mit Hinweis(en) vom Prof was man da beachten muss, denn da 
hat man schon genug mit DDR und PORT und Bit setzen usw. zu tun. Später 
kommen natürlich Timer usw.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren