Datum: 03.05.2008 13:46
Die Beep funktion
int i_beep; int rep_beep; void beep(int hz, int sec) { i_beep = 0; DDRB |= (1<<PB7); rep_beep = sec*hz; while (i_beep < rep_beep) { PORTB ^= (1<<PB7); _delay_ms(1000/hz*2); i_beep++; } } |
bläht die Hexdatei bei eingeschalteter Optimierung um ~4kb auf. Woran liegt das?
Datum: 03.05.2008 13:49
Das liegt daran, dass das Argument von
_delay_ms(1000/hz*2); |
ein double ist und somit die gesamte Fließkommabibliothek eingebunden wird.
Datum: 03.05.2008 13:51
@ 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-Tu... MFG Falk
Datum: 03.05.2008 13:54
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__...
Datum: 03.05.2008 13:54
Muss ich infolgedessen nun auf einen Timer ausweichen?
Datum: 03.05.2008 14:10
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:uint8_t i; 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).
Datum: 03.05.2008 14:22
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
Datum: 03.05.2008 16:22
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.
Datum: 03.05.2008 18:26
> 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
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel