Forum: Compiler & IDEs AVR: timing mit _delay_us()


von Empage (Gast)


Lesenswert?

Guten Abend,
ich habe ein Problem bezüglich der Funktion _delay_us() mit einem 
ATMega32.
Mit dem folgenden Code steuere ich einen Lautsprecher (Port A0) an und 
möchte einen konstanten Ton ausgeben:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main(void) {
5
  uint32_t udelay = 360UL;
6
  uint32_t i;
7
  DDRA = 0xFF;
8
  PORTA = 0;
9
  
10
  while(1) {
11
    PORTA ^= 0b00000001;
12
    
13
    for (i = 0UL; i < udelay; i++) {
14
      _delay_us(1);
15
    }
16
    
17
    //_delay_us(1000UL);
18
  }
19
  return 0;
20
}

Mit der auskommentierten delay-Funktion klappt das so auch ganz gut und 
der Ton ist sauber und liegt wohl auch ungefähr bei 1kHz. Wenn ich 
jedoch die Funktion mit der for-Schleife benutze, wie ich sie hier im 
Forum gefunden habe, um eine variable Zeit abzuwarten, geht das 
irgendwie schief. Bei udelay < 350 funktioniert das auch noch, bis auf 
das der Ton nicht bei (1000000 / 350) Hz liegt, sondern etwas tiefer 
ist. Sobald ich jedoch für udelay einen Wert von 360 oder höher 
eintrage, krisselt der Lautsprecher total und hat keinen guten 
konstanten Ton mehr, obwohl das ja eigentlich bis 1 kHz kein Problem 
darstellen sollte.

Woran kann das liegen? Ist die for-Schleife soviel langsamer als ein 
einfaches delay? Aber dann müsste ich ja mit einem anderen Wert ein 
Äquivalent zur einfachen delay-Funktion schaffen, das ist aber nicht 
möglich.

Gruß,
Empage

von Karl H. (kbuchegg)


Lesenswert?

Empage schrieb:

> Woran kann das liegen? Ist die for-Schleife soviel langsamer als ein
> einfaches delay?

32 Bit Arithmetik ist für einen 8-Bit µC nun mal ziemlich aufwändig.

> Aber dann müsste ich ja mit einem anderen Wert ein
> Äquivalent zur einfachen delay-Funktion schaffen, das ist aber nicht
> möglich.

Ich denke mal, dass der Optimizer da bei kleinen Werten zugeschlagen hat 
und die for-Schleife soweit beschleunigt hat, dass es noch einigermassen 
hinkommt. Bei größeren Werten schägt dann der 32 Bit Overhead gnadenlos 
zu.


Solche Dinge macht man mit Timern.

von Rolf Magnus (Gast)


Lesenswert?

Welchen Takt hat der Prozessor denn? _delay_us(1) sind ja bei 8 MHz nur 
8 Taktzyklen.  Da ist der Overhead für die for-Schleife pro Durchlauf 
mindestens genauso groß. Bei niedrigeren Prozessortakten überwiegt der 
Overhead deutlich gegenüber dem delay.

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.