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:
1
#define F_CPU 3686400UL
2
3
#include<util/delay.h>
4
5
voidwait_ms(intmiliSec){
6
_delay_loop_2(((F_CPU/250)*miliSec));
7
}
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
> 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?
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.
@ 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
>> 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.
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.
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.
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
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
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.
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.
> 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.