Forum: Compiler & IDEs Beepfunktion bläht hex um ~4kb auf


von Alan (Gast)


Lesenswert?

Die Beep funktion
1
int i_beep;
2
int rep_beep;
3
void beep(int hz, int sec) {
4
  i_beep = 0;
5
  DDRB |= (1<<PB7);
6
  rep_beep = sec*hz;
7
  while (i_beep < rep_beep) {
8
    PORTB ^= (1<<PB7);
9
    _delay_ms(1000/hz*2);
10
    i_beep++;
11
  }
12
}

bläht die Hexdatei bei eingeschalteter Optimierung um ~4kb auf. Woran 
liegt das?

von Simon K. (simon) Benutzerseite


Lesenswert?

Das liegt daran, dass das Argument von
1
_delay_ms(1000/hz*2);
ein double ist und somit die gesamte Fließkommabibliothek eingebunden 
wird.

von Alan (Gast)


Lesenswert?

Wie ließe sich dies umgehen?

von Falk B. (falk)


Lesenswert?

@ Alan (Gast)

>    _delay_ms(1000/hz*2);

Böse, böse.

>bläht die Hexdatei bei eingeschalteter Optimierung um ~4kb auf. Woran
>liegt das?

_delay_ms() braucht KONSTANTE Parameter OHHE Berechnung.

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


MFG
Falk

von Sebastian G. (Gast)


Lesenswert?

Nein, ein double wird bei der Division nicht erzeugt, das ist einfache 
ganzzahlige Integer-Divison. Die Code-Groesze kommt wohl vielmehr daher, 
dass _delay_ms ueberhaupt mit nicht (zur Compile-Zeit bereits bekanntem) 
konstanten Parameter aufgerufen wird. Vergleiche den Auszug aus der 
avr-libc Dokumentation:

"Note: 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."

Quelle: 
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

von Alan (Gast)


Lesenswert?

Muss ich infolgedessen nun auf einen Timer ausweichen?

von Philipp B. (philipp_burch)


Lesenswert?

Alan wrote:
> Muss ich infolgedessen nun auf einen Timer ausweichen?

Bei Verwendung eines Output-Compare-Ausgangs wäre das die beste Lösung. 
Sollte kein Timer zur Verfügung stehen, musst du die Delays halt selbst 
bauen:
1
uint8_t i;
2
for (i = 0; i < delay; ++i) _delay_us(10);
Damit wird ungefähr 'delay' * 10 Mikrosekunden gewartet (Durch den 
Overhead der Schleife etwas länger).

von Peter D. (peda)


Lesenswert?

Alan wrote:
> Muss ich infolgedessen nun auf einen Timer ausweichen?

Was sollte sich denn damit ändern?

Du mußt Deine Herangehensweise ändern.

In der Regel ruft man die Funktionen mit konstanten Parametern auf und 
dann kann man ganz leicht die Konstantenberechnung vor den Aufruf 
ziehen.
Schau mal in die Delayfunktionen, da gibt es welche, denen man die 
Zykluszahl übergeben kann.

Timer ist aber keine schlechte Idee, besonders, wenn man die 
Compareausgänge benutzt. Dann gibt es keine Störungen durch Interrupts 
und der Ton klingt bedeutend sauberer.

Auch sind unsigned Rechnungen in der Regel einfacher. Da Du keine 
negativen Töne mit negativer Dauer erzeugen kannst, nimm für die 
Parameter besser unsigned.
1..65000 Sekunden als Dauer ist nicht so der Brüller, ich würde zu 10ms 
Raster raten, bis 2,5s reicht dann ein unsigned char völlig aus.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Sebastian G. wrote:
> Nein, ein double wird bei der Division nicht erzeugt, das ist einfache
> ganzzahlige Integer-Divison.

Bei der Division die du siehst nicht.
Aber in _delay_ms stecken ja auch noch ein paar Berechnungen.
Und die sind in floating point und fallen nur dann weg, wenn der
Compiler das Argument als Konstante sieht.

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

Da stehts sogar: Die Float Lib kommt mit rein.

von Sebastian G. (Gast)


Lesenswert?

> Bei der Division die du siehst nicht.
> Aber in _delay_ms stecken ja auch noch ein paar Berechnungen.
> Und die sind in floating point und fallen nur dann weg, wenn der
> Compiler das Argument als Konstante sieht.

Danke fuer den Hinweis, da habe ich nicht aufgepasst. Insofern ist, was 
ich geschrieben habe ("ein double wird bei der Division nicht erzeugt") 
auch ziemlich unsauber: die Divison selbst erzeugt zwar keinen double, 
aber natuerlich der implizite Cast in den Parametertyp von _delay_ms.

(Ich sollte das naechste Mal nochmal genau lesen, was ich geschrieben 
habe, und alles auf eventuelle Missverstaendlichkeiten abklopfen. ;-))

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.