mikrocontroller.net

Forum: Compiler & IDEs _delay_ms () -> indirekte Zeitübergabe > Programm riesig


Autor: Michael J. (jogibaer)
Datum:
Angehängte Dateien:

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

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Michael J. (jogibaer)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ersetze mal
_delay_ms(message_array[2]);
durch
for(i=message_array[2]; i; i--)
  _delay_ms(1);

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Michael J. (jogibaer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:
> Ersetze mal
>
> _delay_ms(message_array[2]);
> 
> durch
>
> for(i=message_array[2]; i; i--)
>   _delay_ms(1);
> 

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

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

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

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.