Hallo,
als so ein Problem habe ich auch noch nicht gehabt.
in kurzer Version:
main.c -> Zeile 153
Wenn ich die Funktion so Aufrufe,
erhalte ich eine Programmgröße von 2602 Bytes
_delay_ms(1);
Lade ich mir hingegen die Zeit aus einem Array heraus,
habe ich plötzlich eine Programmgröße von 6088 Bytes
_delay_ms(message_array[2]);
Also ist das gesamte Programm ca 2,3 mal so groß.
Könnte mich mal bitte jemand über die Ursache aufklären ?
( Bitte nicht lachen oder stöhnen, das Programm ist noch seeeeeeeeeehr
im Entwurfsstadium)
Jogibär
Die _delay_XX-Funktionen funktionieren nur dann korrekt, wenn sie (1)
konstante Parameter übergeben bekommen und (2) die Optimierung
eingeschaltet ist. Das sind inline-Assembler-Funktionen, die mit
double-Parametern arbeiten. Und das ist sehr aufwändig und klappt nur
dann, wenn die Berechnung nicht zur Programmlaufzeit durchgeführt werden
muss, sondern der Compiler das übernehmen kann. Wenn man nicht-konstante
Parameter übergibt, wird zudem die komplette float-lib eingebunden und
bläht den Code auf, auch wenn ansonsten überhaupt keine
Gleitkommageschichten im Programm verwendet werden. Steht aber auch in
der AVR-libc-Doku (Zitat):
"In order for these functions to work as intended, compiler
optimizations must be enabled, and the delay time must 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."
Das liegt daran, dass _delay_xx Funktionen mit Floating-Point Zahlen als
Parameter arbeiten. Wenn du also die Verzögerung zur Laufzeit berechnen
willst, muss sichergestellt sein, dass der Mikrocontroller während
seiner Laufzeit auch mit Floating-Point-Zahlen umgehen kann. Und genau
dies tut er, indem er die große und langsame float-lib mit hinzulinkt.
Wenn man _delay_xx Funktionen mit zur Kompilierzeit konstanten Werten
aufruft, ist es nicht nötig eine Floating-Point Implementierung
beizugeben, da der Compiler es im Voraus berechnen kann.
Was möchtest du denn genau machen? Hört sich für mich eher nach einer
Aufgabe für einen Timer an.
Hallo,
einfach nur ein wenig warten.
Das mit float habe ich schon fast vermutet,da
im Assemblercode auf einmal Funktionen aufgetaucht sind,
die float was weiß ich hießen.
Aber daß das gleich so einschlägt.
Dann muß wohl eine eigene Wartefunktion schreiben.
Die Wartezeiten werden mir per Protokoll übergeben.
Jogibär
Nein, du musst lernen dich mit den Timern auseinander zu setzen, da
diese vermutlich für genau deinen Zweck gemacht sind.
(längere) Warteschleifen sind Mist, da der Prozessor währenddessen
nichts anderes machen kann.
Michael Jogwich wrote:
> Aber daß das gleich so einschlägt.
Was meinst Du, was eine Festpunkt-CPU für Verrenkungen machen muss, um
Gleitkomma-Operationen durchführen zu können? Gerade aufgrund der
Laufzeit- und Code-Intensität dieser Operationen auf solchen Rechnern
versucht man doch krampfhaft, alles in Festpunkt zu erledigen (was auch
in >90% der Fälle problemlos machbar ist).
> Dann muß wohl eine eigene Wartefunktion schreiben.> Die Wartezeiten werden mir per Protokoll übergeben.
Die einfachste Methode (wenn es unbedingt mit den Busy-wait-Funktionen
sein soll, andernfalls siehe Simons zweites Posting in Sachen Timer)
ist, einfach z.B. ein _delay_ms(1) in einer Schleife aufzurufen (Bsp.
siehe yalus Posting). Dann kannste in ms-Schritten alle möglichen
Wartezeiten realisieren. Wenn allerdings ein Interrupt dazwischenhaut,
ist Essig mit Genauigkeit. Wie auch in der Doku steht: Die
_delay_XX-Funktionen sind nicht für den allgemeinen Bedarf v.a. an
längeren Wartezeiten gedacht.
Hallo,
klar das ist eine gute Idee.
Simon:
Ich weiß schon, wie ich Timer benutze.
Den hätte ich ja dann auch verwendet.
Dann lasse ich sowas immer im Hintergrund laufen.
Außerdem genügt eine Wartefunktion für diesen Zweck,
da die CPU sowiso nichts anderes tun muß.
Michael Jogwich wrote:
> Außerdem genügt eine Wartefunktion für diesen Zweck,> da die CPU sowiso nichts anderes tun muß.
Dann kannst du sie mit einem Timer schlafen legen und Strom sparen. ;-)
Du hast ansonsten immer noch die Basisfunktionen, die _delay_ms()
und _delay_us() zu Grunde liegen, die heißen _delay_loop_1() und
_delay_loop_2(). Diesen übergibst du nur die Anzahl der Durchläufe
der Schleifen, die Rechnung, wie lange es dauert, musst du dann zu
Fuß machen. Die _delay_*s-Funktionen sind ``convenience functions'',
die darauf aufsetzen und halt für die typischen Anwedungsfälle dem
Programmierer das Rechnen abnehmen und dieses in den Compiler
verlagern.