Hallo,
ich bin neu hier. Nach stundenlangem Suchen hier im Forum, habe ich
keine Antwort auf meinem Problem gefunden.
Ich bin von Bascom auf WinAVR umgestiegen. In dem Programm benutze ich
die "_delay_ms(50)"-Funktion. Aber ich kann machen was ich will, die
Zeiten stimmen nie. Auch eine Änderung von "#define F_CPU 7372800"
(Quarz und Fusbits sind korrekt) hat keinen Einfluss. Egal was ich
angebe, es ändert sich nichts.
Ich habe lange gesucht und weiß jetzt nicht mehr weiter. Jetzt bitte
ich hier um Rat.
Danke und schöne Grüße
Walter
Bei aktuellem WinAVR geht das ganze auch so:
#define F_CPU 14745600 /* Clock in HZ */
#include <avr/delay.h>
[..]
_delay_ms(25.5); /* delay 25.5ms */
[..]
Hallo Walter,
ich benutze CodeVisonAVR und hatte mal das gleiche Problem.
Bei mir war´s eine falsche Einstellung der Clock-Frequenz in der
Entwicklungsumgebung. Ich weiß nicht, ob es diese Einstellung bei
WinAVR auch gibt, aber es wäre eine Fehler - Möglichkeit. An sonsten,
so wie OldBug def. bzw. dek., dann sollte es gehn.
Schreib mal ob du es hinbekommen hast.
Gruß
seacrash
Danke, erstmal für die Antworten.
ich habe das Problem vorerst mit einer Schleife gelöst. Später möchte
ich es aber eleganter lösen.
Ich meine, ich kann überall meine verwendete F_CPU = 7372800 eintragen
und es ändert sich nichts. Auch nicht, wenn ich nur 1MHz eintrage.
_delay_ms(200) entspricht momentan ca. 50ms.
Ich habe alles durchsucht.
Vielleicht hat jemand mal das gleiche Problem mal gehabt. Bitte
melden.
Grüße
Walter
Hallo und danke,
ich hänge mal die "delay.h" dran. Es ist die, die im WinAVR mit
installiert wird.
Folgende Versionen sind dabei mit installiert worden:
- GCC: 3.4.3.
- avr-libc: 1.2.3.
Ich weiß nicht, ob es wirklich die aktuellen Versionen sind, die
Angaben habe ich aus der "WinAVR-user-manual.txt"-Datei.
Bitte verzeiht, ich mache gerade meine ersten Gehversuche mit GCC.
Walter
Hm, Jörg:
Ich habe gerade mal Dein ledgame.c ausprobiert, und wollte da mal eine
echte RGBA-Leiste anklemmen. Habe da beim Starten einfach mal alle
Farben geschaltet und wollte dazwischen ein bißchen Pause machen
(q&d).
Ich habe die Zeiten jetzt nicht gemessen, aber 2 x _delay_ms(255) ist
viiiiieeeel zu flott...
Ich versuche mal, da genaueres rauszufinden...
Hier mal ein kleines Testprogramm.
Ich habe mal _delay_ms(128.5) und _delay_ms(255) ausprobiert: für mich
sieht der erzeugte Code absolut identisch aus!?
@OldBug:
Wenn ich mir die header-Datei anschaue und Deine Taktfrequenz
berücksichtige, dann komme ich auf maximal 17.777778ms. Beide von Dir
angegebenen Zeiten liegen darüber, also wird der Max-Wert genommen.
Daher ist der erzeugte Code gleich.
Volkmar
Die Aussage versteh ich nicht ganz, denn laut avr/delay.h:
Perform a delay of \c __ms milliseconds, using _delay_loop_2().
The macro F_CPU is supposed to be defined to a
constant defining the CPU clock frequency (in Hertz).
The maximal possible delay is 262.14 ms / F_CPU in MHz.
Sollte man maximal 262.14ms "einstellen" können...
Du hast die Lösung des Problemes selbst zitiert:
" The maximal possible delay is 262.14 ms / F_CPU in MHz.
Sollte man maximal 262.14ms "einstellen" können..."
Wenn F_CPU 1 MHz beträgt.
Du aber arbeitest mit 7.3728 MHz, also resultieren aus der Division
etwa 35 msec.
Schade, dass man aus einer inline function nicht auch noch ein #error
(oder #warning) schmeißen kann, sonst hätte ich das gern getan, um all
diejenigen, die die Beschreibung nicht richtig lesen, mit der Nase
drauf zu drücken. ;-)
Ich hab's aber vorsätzlich nicht mit Präprozessor-Mimik gemacht,
damit
man auch Gleitkommaausdrücke benutzen kann. Vielleicht hätte ich ja
bei Überlauf statt des Maximalwertes jeweils um 42 Takte verzögern
sollen, damit es den Leuten besser auffällt? :-)
Bei meinem AT90S2323 habe ich genau das selbe Problem mit dem
_delay_ms() - Befehl.
Egal was ich im Makefile bei F_CPU oder bei #define F_CPU eingebe, die
delay-Zeiten sind nur bei einem Takt von 1 MHz korrekt.
Wenn ich z.B. einen Quarz mit 10 MHz anschliese und im Makefile
10000000 Hz eingebe, die delay-Zeiten sind trotzdem viel zu schnell.
@Tobi:
- Welches delay möchtest Du denn erreichen?
- In welcher Reihenfolge hast Du F_CPU definiert und die
Include-Anweisung?
- Hast Du noch andere defines für F_CPU?
Volkmar
Hallo Volkmar,
zu 1:
Die delay-Zeiten bewegen sich zwischen 1 ms und 250 ms.
(bzw. mehrere _delay_ms (250) hintereinander um einige Sekunden zu
errreichen oder in einer Schleife mit einer bestimmten Anzahl von
Durchläufen.) Wie schon gesagt bei 1 MHz Takt stimmen die
delay-Zeiten.
zu 2:
F_CPU wird nur im Makefile definiert. Testweise hatte ich einmal F_CPU
im Makefile gelöscht und im Programm folgendes zuerst geschrieben:
#define FCPU = 10000000
#include <avr\delay.h>
zu 3:
Die Variable F_CPU verwende ich im gesamten Programm nicht.
> #define FCPU = 10000000
Ohne Gleichheitszeichen und F_CPU mit Unterstrich. Sollte sich sonst
aber gar nicht compilieren lassen.
> #include <avr\delay.h>
<avr/delay.h> bitte, auch auf Windows. (Windows hat kein Problem mit
einem Vorwärtsstrich als Verzeichnistrenner, nur command.com und
cmd.exe haben eins.)
Irgendwas musst du mit diesen Makros in der Tat versaut haben (ich
vermute mal, das oben waren nur Schreibfehler im Posting). Kannst ja
mal den generierten Assemblercode ansehen.
Das 1 MHz ist der default-Wert in avr/delay.h. Wenn der greift,
bekommst du aber auch eine Compilerwarnung gespuckt. Hast du das mal
verifiziert?
Hallo Jörg,
sorry hatte den Text vorhin etwas zu schnell getippt.
<avr/delay.h>
Im Code stehts richtig, sonst würde der Compiler einen Fehler bringen.
Ich weiß, echt nicht mehr weiter !
Compiler Meldung: siehe Anhang
Schein mal alles in Ordnung zu sein.
Hallo Tobi,
Du hast geschrieben:
> Die delay-Zeiten bewegen sich zwischen 1 ms und 250 ms.> (bzw. mehrere _delay_ms (250) hintereinander um einige Sekunden zu> errreichen oder in einer Schleife mit einer bestimmten Anzahl von> Durchläufen.) Wie schon gesagt bei 1 MHz Takt stimmen die> delay-Zeiten.
sowie
> #define FCPU = 10000000
D.h. Du hast einen 10MHZ-Takt?
Aus dem Header-File:
"The maximal possible delay is 262.14 ms / F_CPU in MHz."
D.h. Du kommst bei 10MHz auf maximal 26ms, die Du verwenden kannst. Wie
hoch sind denn die Delay-Zeiten, die Du erreichst?
Volkmar
Umm, ja, nachgerechnet hatte ich noch gar nicht...
26 ms wenn 250 gewünscht sind -- das klingt natürlich gut so,
als würde ein Takt von 1 MHz angenommen. ;-)
Ich hatte nicht erst gerechnet, weil Tobi so tat, als ob auch
die kürzeren Delays zu kurz geworden wären, aber wahrscheinlich
hat er die gar nicht erst nachgemessen...
Soll das also heißen, dass bei höherer Taktfrequnz die max. delay-Zeit
automatisch kleiner wird.
Also sind es bei 1 MHz noch 255 ms, dann sind es bei 10 MHz nur noch 25
ms ???
Dann muss ich nun wohl, um delay-Zeiten von mehreren 100 ms zu
erreichen wieder Schleifen mit 25 ms programmieren, oder gibts da eine
elegantere Lösung ?
> Soll das also heißen, dass bei höherer Taktfrequnz die> max. delay-Zeit automatisch kleiner wird.
Klar, logisch, wie denn sonst? Du hast halt maximal 64K Zyklen, die
diese kleinen Schleifen durchlaufen können. Die sind zwanghaft bei
höherer Taktfrequenz dann schneller vorbei.
Ungern wärme ich diesen Thread wieder auf, aber etwas Senf möchte ich
doch dazugeben.
Diese Tage hatte ich eine Diskussion über util/delay.h - und über diesen
Artikel. Eine Suche auf mikrocontroller.net mit "avr delay" liefert
diesen Artikel als ersten Eintrag.
Ich kopiere aus meiner avr/delay.h:
1
/**
2
\ingroup util_delay
3
4
Perform a delay of \c __ms milliseconds, using _delay_loop_2().
5
6
The macro F_CPU is supposed to be defined to a
7
constant defining the CPU clock frequency (in Hertz).
8
9
The maximal possible delay is 262.14 ms / F_CPU in MHz.
10
11
When the user request delay which exceed the maximum possible one,
12
_delay_ms() provides a decreased resolution functionality. In this
13
mode _delay_ms() will work with a resolution of 1/10 ms, providing
14
delays up to 6.5535 seconds (independent from CPU frequency). The
15
user will not be informed about decreased resolution.
16
*/
17
void
18
_delay_ms(double__ms)
19
{
20
uint16_t__ticks;
21
double__tmp=((F_CPU)/4e3)*__ms;
22
if(__tmp<1.0)
23
__ticks=1;
24
elseif(__tmp>65535)
25
{
26
// __ticks = requested delay in 1/10 ms
27
__ticks=(uint16_t)(__ms*10.0);
28
while(__ticks)
29
{
30
// wait 1/10 ms
31
_delay_loop_2(((F_CPU)/4e3)/10);
32
__ticks--;
33
}
34
return;
35
}
36
else
37
__ticks=(uint16_t)__tmp;
38
_delay_loop_2(__ticks);
39
}
(avr-libc: 1:1.6.8-2, ubuntu)
Also:
When the user request delay which exceed the maximum possible one,
_delay_ms() provides a decreased resolution functionality. In this mode
_delay_ms() will work with a resolution of 1/10 ms, providing delays up
to 6.5535 seconds (independent from CPU frequency). The user will not
be informed about decreased resolution.
Hoffe den in Zukunft Suchenden etwas geholfen zu haben, und über sowas
nicht mehr diskutieren zu müssen ;)