mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wartefunktion aus delay.h funktioniert nicht (ATMega16)


Autor: Jan Masak (gallig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und erstmal Danke für dieses hilfreiche Forum, hat mir schon oft 
weitergeholfen. :)

Ich habe nun folgendes Problem, ich möchte die Wartefunktion aus der 
delay.h nutzen jedoch wartet diese Funktion nicht wirklich. Egal welchen 
Wert ich übergebe. Meine Wartefunktion sieht folgendermaßen aus:
#define F_CPU 3686400UL

#include <util/delay.h>

void wait_ms(int miliSec){
   _delay_loop_2( ((F_CPU/250)* miliSec));
}

Die Optimierungen sind aktiviert und ich nutze AVR-Studio mit WinAVR für 
einen ATMega16.

Also bei einem vorigen Programm hatte die Funktion funktioniert, jedoch 
habe ich dort noch einen ATMega8 genutzt. Vielleicht sollte ich noch 
erwähnen das ich in dem Programm noch die TWI-Bibliothek von P.Fleury 
nutze falls das Probleme machen könnte.

Ich bin für jeden Hinweis dankbar und hoffe das ich alle nötigen 
Informationen erwähnt habe.

MfG
Jan

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast Du es schon mal mit dem Code vom Tutorial versucht?
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht liegt es ja daran, daß deine Berechnung nicht stimmt. 
Versuch's mal mit:
_delay_loop_2( ((F_CPU/4000)* miliSec));

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Rolf Magnus (Gast)

>_delay_loop_2( ((F_CPU/4000)* miliSec));

Und was soll der Unsinn? Schon mal _delay_ms() benutzt?

MfG
Falk

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und was soll der Unsinn?

Was blökst du mich deswegen an? Ich habe das vom Ursprungsposter 
übernommen und nur den fehlerhaften Faktor korrigiert.

> Schon mal _delay_ms() benutzt?

Schon mal _delay_ms() mit einem Parameter benutzt, der nicht zur 
Compilezeit bekannt ist?

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:

> Schon mal _delay_ms() mit einem Parameter benutzt, der nicht zur
> Compilezeit bekannt ist?

Welcher Parameter soll das sein? F_CPU? Der sollte eigentlich gerade in 
der Compilezeit gesetzt sein. Oder vestehe ich was falsch?

Zu beachten ist bei _delay_ms(), daß abhängig von der CPU-Frequenz die 
maximale Verzögerungszeit begrenzt ist. Beispielsweise waren es bei 8Mhz 
knapp 30ms. Das Ganze ist in der avr-libc dokumentiert.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Rolf Magnus (Gast)

>Was blökst du mich deswegen an?

Im locker bleiben, das war nicht so gemeint.

>Schon mal _delay_ms() mit einem Parameter benutzt, der nicht zur
>Compilezeit bekannt ist?

Ja, z.B. so
void long_delay(uint16_t ms) {
   for(; ms>0; ms--) _delay_ms(1);
}

MFG
Falk

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Schon mal _delay_ms() mit einem Parameter benutzt, der nicht zur
>> Compilezeit bekannt ist?
>
> Welcher Parameter soll das sein?

Na der eine Parameter, der an die Funktion übergeben wird. Die 
Wartezeit. Wenn der bei _delay_ms keine Compilezeitkonstante ist, wird 
die Wartezeit deutlich länger und der Code ein paar Kilobytes größer, 
weil zur Laufzeit Fließkomma-Berechnungen nötig sind.

>> Was blökst du mich deswegen an?
>
> Im locker bleiben, das war nicht so gemeint.

Wie man in den Wald hineinruft... ;-)

> void long_delay(uint16_t ms) {
>   for(; ms>0; ms--) _delay_ms(1);
> }

Ja, das ist die häufiger anzutreffende Variante. Die hat auch den 
Vorteil, daß man länger damit warten kann und daß sie vermutlich einen 
Tick genauer ist. Aber Jans Version solle ja eigentlich auch 
funktioneren.

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:

>> void long_delay(uint16_t ms) {
>>   for(; ms>0; ms--) _delay_ms(1);
>> }
>
> Ja, das ist die häufiger anzutreffende Variante. Die hat auch den
> Vorteil, daß man länger damit warten kann und daß sie vermutlich einen
> Tick genauer ist. Aber Jans Version solle ja eigentlich auch
> funktioneren.

Glaub ich nicht, es sei denn, ein uint16_t kann negativ werden....was 
ich aber stark bezweifele.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe im Moment nicht, worauf du hinaus willst. Was glaubst du 
nicht?

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaube nicht, das das so funktioniert. ms ist als uint16_t definiert 
und die Bedingung in der for-schleife lautet "ms>0", d.h. er kann erst 
false werden, wenn ms negativ wird.

uint16_t ist IMO ein unsigned type (also vorzeichenlos). ms kann nicht 
negativ werden. Das oben aufgeführte Konstrukt ist meiner Meinung nach 
eine Endlosschleife.

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>er kann erst false werden, wenn ms negativ wird.
Und was ist mit ms == 0 ? ist das negativ?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ansonsten: Standardantwort.  Nimm einen Timer.  Die werden dafür
bezahlt, sich mit Zeiten auszukennen...

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick wrote:

> Und was ist mit ms == 0 ? ist das negativ?

ich glaube nicht schäm

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ms>=0 wäre eine Endlosschleife.

Autor: Jan Masak (gallig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal viel dank für die vielen Antworten.
Die Funktion delay_ms(int) habe ich auch schon ausprobiert, bei den 
genutzten 3,6MHz komme ich mit Int auf eine max. Wartezeit von ca. 70ms 
daher hatte ich die Funktion ähnlich wie oben beschrieben in einer 
for-Schleife mehrmals aufgerufen aber leider ohne Erfolg.

Im Debugger von AVR-Studio habe ich die ganze Sache mal simuliert und es 
funktionierte Problemlos (musste nur die TWI-Funktionen auskommentieren 
da das Programm sonst auf Antworten wartet, welche es nicht bekommen 
kann) aber auf dem µC selber scheint es so als würde die Wartefunktion 
komplett übersprungen.

Inzwischen habe ich aber alle Pausen per Timer realisiert, da ich den 
Timer0 sowieso zum auswerten von Tastatureigaben nutze und jetzt einfach 
einen Zähler inkrementieren lasse. Habe das Problem also einfach 
umgangen, dennoch wundert es mich das diese Funktion nicht 
erwartungsgemäß arbeitet.

MfG
Jan

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jan Masak wrote:

> einen Zähler inkrementieren lasse. Habe das Problem also einfach
> umgangen, dennoch wundert es mich das diese Funktion nicht
> erwartungsgemäß arbeitet.

Wenn die delay Funktionen nicht erwartungsgemäss funktionieren,
dann gibt es dafür 4 Gründe
* die angegebene Zeit ist zu gross und fällt ueber das vorgebenen
  Limit
* die tatsächliche Taktfrequenz des µC stimmt nicht mit der im
  Pgm angegebenen überein. Häufiger Fehler: Der µC läuft immer
  noch auf internem Oszillator und nicht auf externem Quarz.
  Das Stichwort dazu lautet: Fusebits
* Der Optimizer im Compiler ist nicht eingeschaltet.
* die _delay_xx Funktionen werden durch Fehler in der Programm-
  logik nicht aufgerufen

Wenn diese 4 Fehlerquellen ausgeschlossen werden, dann funktionieren
die Aufrufe einwandfrei

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jan Masak wrote:

> daher hatte ich die Funktion ähnlich wie oben beschrieben in einer
> for-Schleife mehrmals aufgerufen aber leider ohne Erfolg.

Dann musst du schon den Code posten, der nicht geht.  Ich habe auf
jeden Fall auf so'ne Weise schon LED-Blinker zum Ausprobieren
gehackt.

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jan Masak wrote:

> Erstmal viel dank für die vielen Antworten.
> Die Funktion delay_ms(int) habe ich auch schon ausprobiert, bei den

Auf die Gefahr hin, noch einen unnötigen Kommentar abzugeben: wir 
sprachen von "_delay_ms()", nicht "delay_ms()".

Ich habe diese Funktion bereits auf verschiedenen Plattformen (atm8, 
atm128, atm64) bei verschiedenen Taktfrequenzen bisher problemlos 
einsetzen können. In der avr-libc ist diese Funktion nichts weiter als 
ein Makro, die zwei verschachtelte Schleifen (auf basis von 
_delay_loop_2()) implementiert. Das einzige, was hier schiefgehen kann, 
ist entweder daß die maximale Verzögerung überschritten wird, oder der 
optimizer im compiler erkennt, daß es sich hier um scheinbar unnötige 
Schleifen handelt, in denen nichts passiert und optimiert sie raus.

Wenn du beides Ausschliessen kannst (dürfte im lst-file leicht zu 
erkennen sein) liegt dein Fehler vermutlich GANZ woanders.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In der avr-libc ist diese Funktion nichts weiter als ein Makro,

Nein, es ist tatsächlich eine Funktion.

> oder der optimizer im compiler erkennt,daß es sich hier um scheinbar
> unnötige Schleifen handelt, in denen nichts passiert und optimiert sie
> raus.

Die Funktion ist so implementiert, daß das nicht passieren kann. Sie ist 
sogar auf den Optimizer angewiesen, um korrekt zu funktionieren.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.