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.
Ersetze mal
1 | _delay_ms(message_array[2]); |
durch
1 | for(i=message_array[2]; i; i--) |
2 | _delay_ms(1); |
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.
yalu wrote: > Ersetze mal >
1 | > _delay_ms(message_array[2]); |
2 | >
|
> durch >
1 | > for(i=message_array[2]; i; i--) |
2 | > _delay_ms(1); |
3 | >
|
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.