AVR: timing mit _delay_us()

Gast #2371208
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
#2371217
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.
Gast #2372205
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.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.