Forum: Compiler & IDEs Delay -Problem


von Walter M. (Gast)


Angehängte Dateien:

Lesenswert?

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

von zonk (Gast)


Lesenswert?

#include <avr/delay.h>
#define FCLK 16e6
#define Delay_us(t) _delay_loop_2((uint16_t)(((t)*1e-6*FCLK)/4))

so hab ichs gemacht.sind allerdings us.

von OldBug (Gast)


Lesenswert?

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 */
[..]

von seacrash (Gast)


Lesenswert?

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

von Walter M. (Gast)


Lesenswert?

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

von Jörg Wunsch (Gast)


Lesenswert?

Seltsam.  Du bist der Erste, der sowas erzählt.

Nur für alle Fälle: das ist auf einem realen Chip, nicht bloß im
Simulator, ja?

von Walter M. (Gast)


Angehängte Dateien:

Lesenswert?

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

von OldBug (Gast)


Lesenswert?

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...

von OldBug (Gast)


Angehängte Dateien:

Lesenswert?

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!?

von Volkmar (Gast)


Lesenswert?

@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

von OldBug (Gast)


Lesenswert?

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...

von Rufus T. Firefly (Gast)


Lesenswert?

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.

von OldBug (Gast)


Lesenswert?

Naja, typischer Fall von "missunderstood" ;)

Nagut, ich sehs ein!

F_CPU beträgt allerdings 14745600Hz...

von Rufus T. Firefly (Gast)


Lesenswert?

Ich hab' nur den Wert aus dem ersten Posting genommen ... da steht
7.irgendwas MHz.

von Walter M. (Gast)


Lesenswert?

Vielen Dank für die ganz Mühe.
Jetzt habe ich es auch gelesen. Es steht ja dabei.
Sorry. Beim nächsten mal muss ich es genau durchlesen.

von Jörg Wunsch (Gast)


Lesenswert?

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? :-)

von OldBug (Gast)


Lesenswert?

Also: ich habs einfach nur falsch verstanden.
Vielleicht wäre da ein kleines (ausführlicheres) Rechenbeispiel
angebracht!?

von Tobi (Gast)


Lesenswert?

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.

von Volkmar (Gast)


Lesenswert?

@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

von Tobi (Gast)


Lesenswert?

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.

von Jörg Wunsch (Gast)


Lesenswert?

> #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?

von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Jörg Wunsch (Gast)


Lesenswert?

"make rgb.s"

Was steht dann da drin?

von Volkmar (Gast)


Lesenswert?

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

von Jörg Wunsch (Gast)


Lesenswert?

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...

von tobi (Gast)


Lesenswert?

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 ?

von Chris (Gast)


Lesenswert?

> oder gibts da eine elegantere Lösung ?

Ja, siehe Abschnitt "Timer" im Datenblatt.

von Jörg Wunsch (Gast)


Lesenswert?

> 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.

von mru (Gast)


Lesenswert?

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
  else if (__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 ;)

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.