Beepfunktion bläht hex um ~4kb auf

Gast #858317
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?
Gast #858325
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
#858337
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).
#858347
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
#858412
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.
Gast #858485
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. ;-))

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