Forum: Mikrocontroller und Digitale Elektronik Frage zu delay (wie bekomme ich genau 1 Sekunde)


von Thomas (Gast)


Lesenswert?

Hallo, habe ml eine ganz simple frage und zwar gibt es ja für delay 
einmal

delay_ms  für millisekunden und
delay_us  für mikrosekunden

richtig??

Wenn ich jetzt aber im Programm delay_ms(1000) benutze müsste das ja 
quasi 1Sekunde bedeuten. Ist es aber nicht. Ich verwende einen Atmega 32 
mit den internen 4MHz Quarz oder hat das auch was mit der eingestellten 
Taktfrequenz was zu tun ?

Gruß Thomas

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas schrieb:
> Ist es aber nicht.
Was ist es denn?

> Ich verwende einen Atmega 32 mit den internen 4MHz Quarz
> oder hat das auch was mit der eingestellten Taktfrequenz was zu tun ?
Du hast ja 4 MHz eingestellt.
Nur mußt du das jetzt im C-Code auch noch angeben (einstellen tust du 
da nichts!). Das passiert mit F_CPU. Und denk daran, die Optimierung auf 
-Os zu stellen...

von Falk B. (falk)


Lesenswert?

@  Thomas (Gast)

>delay_ms  für millisekunden und
>delay_us  für mikrosekunden

>richtig??

Ja.

>Wenn ich jetzt aber im Programm delay_ms(1000) benutze müsste das ja
>quasi 1Sekunde bedeuten.

Ist auch so.

> Ist es aber nicht.

Dann ist was falsch eingestellt. Entweder die AVR Fuses oder dein 
F_CPU define im Quelltext.

> Ich verwende einen Atmega 32
>mit den internen 4MHz Quarz

Es gibt keinen internen Quarz, nur einen internen RC-Oszillator. Und der 
ist nur mäßig genau, so 1..5%.

MfG
Falk

von Thomas (Gast)


Lesenswert?

Ok ich hab da jetzt mal ein
#define F_CPU 4000000

eingefügt aber wenn ich jetzt 10sec einstellen möchte mit delay macht 
der da höchstens 3 raus oder gibt es einen maximalen wert dür delay_ms ?

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:
> Ok ich hab da jetzt mal ein
> #define F_CPU 4000000

Und?
Hast du deinen µC auch auf 4Mhz eingestellt (per Fuse)?


Bei F_CPU kannst du hinschreiben was du willst! Das ist einfach nur eine 
Zahl mit der gerechnet wird, nichts weiter. Nur weil du dort 8Mhz 
hinschreibst, heißt das noch lange nicht, dass dein µC auch tatsächlich 
mit 8Mhz arbeitet.

Auf einen Trabbi Tacho kann ich auch als Höchstgeschwindigkeit 320km/h 
hinschreiben. Hinschreiben kann ichs und der Fahrer kann das auch auf 
dem Tacho ablesen. Aber fahren, fahren wird der Trabbi weiterhin mit 80, 
solange ich nicht den Motor tausche.

> eingefügt aber wenn ich jetzt 10sec einstellen möchte mit delay macht
> der da höchstens 3 raus

Dann arbeitet dein µC nicht mit 4Mhz
So einfach ist das.

F_CPU ist eine Information für den Compiler. Und du solltest besser 
sicherstellen, dass diese Information mit der Realität übereinstimmt.

von Thomas (Gast)


Lesenswert?

hab die Fuses grade noch mal ausgelesen also stehen definitiv auf

int Rc Osz. 4MHz; Start up Time: 6CK+ 4ms

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:
> hab die Fuses grade noch mal ausgelesen also stehen definitiv auf
>
> int Rc Osz. 4MHz; Start up Time: 6CK+ 4ms


dann zeig dein Programm

Es gibt 3 Dinge zu beachten:

* #define F_CPU 4000000
  bevor delay.h includiert wird!

* Den Optimizer vom Compiler einschalten

* Obergrenze der Zeit beachten (weis nicht auswendig wie hoch die liegt)
  steht aber in der Doku


Gegen vergessenen Optimizer kann man nicht viel tun. Aber wenn F_CPU 
nicht rechtzeitig definiert ist, ist delay.h so geschrieben, dass der 
Compiler eine Warnung ausgibt. Siehst du eine Warnung?

von AKKS (Gast)


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

_delay_ms() kann mit einem Argument bis 6553,5 ms (= 6,5535 Sekunden) 
benutzt werden

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> eingefügt aber wenn ich jetzt 10sec einstellen möchte mit delay macht
> der da höchstens 3 raus oder gibt es einen maximalen wert dür delay_ms ?
Bedieungsanleitung lesen:
http://de.wikibooks.org/wiki/C-Programmierung_mit_AVR-GCC/_Warteschleifen
1
  _delay_ms() kann mit einem Argument bis 6553,5ms (= 6,5535 Sekunden) benutzt werden.
Und 10sec - 6,5sec = 3,5sec. Passt also.

EDIT: Pech, Zweiter...  :-/

von Thomas (Gast)


Lesenswert?

Hier ist der Codeausschnitt, den ich meine nach lade Eingaenge sollten 
das 10s sein nach delay
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
5
#include "lc7981.h"
6
#include "graphics.h"
7
#include "touch.h"
8
#include "images.h"
9
#include "windows.h"
10
11
#define F_CPU 4000000
12
13
void print_start()
14
{
15
16
char str_koord[30];
17
char str_button_pressed[17];
18
  uint16_t x,y;
19
  str_koord[0] = '\0';
20
  str_button_pressed[0] = '\0';
21
22
while(1)
23
      {
24
  g_draw_string(1,1, "lade Eingaenge..");
25
//  _delay_ms(1500);
26
  g_draw_string(1,1, "lade Eingaenge....");
27
//  _delay_ms(1500);
28
  g_draw_string(1,1, "lade Eingaenge......");
29
//  _delay_ms(1500);
30
  g_draw_string(1,1, "lade Eingaenge........");
31
//  _delay_ms(1500);
32
  g_draw_string(1,1, "lade Eingaenge........ok");
33
  _delay_ms(10000);
34
  g_draw_string(1,10, "setze Ausgaenge..");
35
//  _delay_ms(1500);
36
  g_draw_string(1,10, "setze Ausgaenge....");
37
//  _delay_ms(1500);
38
  g_draw_string(1,10, "setze Ausgaenge......");
39
//  _delay_ms(1500);
40
  g_draw_string(1,10, "setze Ausgaenge......ok");
41
  _delay_ms(1500);
42
  g_draw_string(1,20, "hole Sensoren..");
43
//  _delay_ms(1500);
44
  g_draw_string(1,20, "hole Sensoren....");
45
//  _delay_ms(1500);
46
  g_draw_string(1,20, "hole Sensoren....ok");
47
  _delay_ms(1500);
48
  g_draw_string(1,30, "starte Menue..");
49
//  _delay_ms(1500);
50
  g_draw_string(1,30, "starte Menue....");
51
//  _delay_ms(1500);
52
  g_draw_string(1,30, "starte Menue......");
53
//  _delay_ms(1500);
54
  g_draw_string(1,30, "starte Menue........");
55
//  _delay_ms(1500);
56
  g_draw_string(1,30, "starte Menue........ok");
57
  _delay_ms(1500);
58
  
59
  g_draw_rectangle(8, 48, 33, 11);
60
  g_draw_string(10,50, "RESET");
61
  g_draw_rectangle(68, 48, 33, 11);
62
  g_draw_string(70,50, "START");
63
64
  x = touch_readX();
65
  y = touch_readY();

von Thomas (Gast)


Lesenswert?

Ok dann könnte das ja doch passen, wenn ca6 s mx sind und ich hab
#include <util/delay.h> vergessen seh ich grade wohl

von Thomas (Gast)


Lesenswert?

Aber demnach müsste das dann doch mit einem zweifachem aufruf klappen 
oder ?

delay_ms(5000);
delay_ms(5000);

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:
> Aber demnach müsste das dann doch mit einem zweifachem aufruf klappen
> oder ?
>
> delay_ms(5000);
> delay_ms(5000);

Sicher.
Du kannst aber auch
1
void delay_sec( uint8_t sec )
2
{
3
  while( sec-- )
4
    _delay_ms( 1000 );
5
}
6
7
8
int main()
9
{
10
11
  ...
12
13
  delay_sec( 20 );   // 20 Sekunden warten
14
15
  ...
16
}


Meistens ist es besser, wenn man irgendwelche Beschränkungen in 
Funktionen verpackt, und die Funktionen so schreibt, dass die 
Beschränkung umgangen wird.

In einem halben Jahr fragst du dich nämlich dann, warum du da
  delay_ms(5000);
  delay_ms(5000);
geschrieben hast und nicht die beiden delay zu einem einzigen 
zusammengefasst hast :-)

von Thomas (Gast)


Lesenswert?

Ok super danke für die schnelle Hilfe und Tipps ;-)

von Pete K. (pete77)


Lesenswert?

Immer wieder das delay.h Thema...

Vielleicht wäre es an der Zeit, in der delay.h mal ein Makro delay_sec() 
anzubieten.
Oder eine Warnung ausgeben, wenn die Obergrenze des Arguments 
überschritten wird (defensives Programmieren).

von Karl H. (kbuchegg)


Lesenswert?

Pete K. schrieb:
> Immer wieder das delay.h Thema...
>
> Vielleicht wäre es an der Zeit, in der delay.h mal ein Makro delay_sec()
> anzubieten.
> Oder eine Warnung ausgeben, wenn die Obergrenze des Arguments
> überschritten wird (defensives Programmieren).

Na, ja.
Das eigentliche Problem ist ja, dass man derartig lange Wartezeiten ganz 
einfach nicht mit einerm _delay realisiert.

* entweder man blockiert sich die Maschine für lange Zeit damit
* oder man erledigt alles zwischendurch in Interrupts, dann stimmen
  aber wiederrum die delay Zeiten nicht

Bis auf wenige Ausnahmen (ganz kurze delay Zeiten um ein Timing 
einzuhalten), kann man sagen:

Kommt in einem Programm ein _delay_ms vor, hat man meistens eine 
unglückliche Designentscheidung getroffen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Kommt in einem Programm ein _delay_ms vor, hat man meistens eine
> unglückliche Designentscheidung getroffen.
Ich würde das ein wenig relativieren:
Bei der Initialisierung von (externen) Komponenten mag ein _delay_ms 
noch angehen. Kommt aber in der Hauptschleife eines Programms ein 
_delay_ms vor, hat man meistens mindestens eine unglückliche 
Designentscheidung getroffen.
Aber auch bei der Initialisierung sollte man die Grenzen von _delay_ms 
nie zu spüren bekommen...

von Klaus W. (mfgkw)


Lesenswert?

@KHB:
So pauschal würde ich das nicht sagen.

Ich kann mir schon Situationen vorstellen, wo man alles Schnelle
in Interrupts erledigt (wenn es nicht viel Aufwand macht) und im
Hauptprogramm nur alle paar Sekunden etwas zu kontrollieren ist.

Unbedingt verwerflich muß es nicht sein, ein paar Sekunden zu warten.

Edit: ok, zweiter.

Aber er redet ja auch von "meistens"

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:

> Ich kann mir schon Situationen vorstellen, wo man alles Schnelle
> in Interrupts erledigt (wenn es nicht viel Aufwand macht) und im
> Hauptprogramm nur alle paar Sekunden etwas zu kontrollieren ist.

...

> Aber er redet ja auch von "meistens"

Eben. Keine Regel ohne Ausnahme.


Ne, ist schon klar. Natürlich gibt es immer wieder Ausnahmen, bei denen 
das ok ist. Auch die Initialisierungsphase ist oft extra.
(welchen Sinn es haben soll auf einem µC, der nach dem Einschalten 
sofort da ist, einen PC mit Bootprozedur zu simulieren indem man gefakte 
Messages auf ein LCD schreibt mit Wartezeiten dazwischen, lass ich mal 
dahingestellt)

von U.R. Schmitt (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Messages auf ein LCD schreibt mit Wartezeiten dazwischen, lass ich mal
> dahingestellt)

Na ja er will seine Nachrichten halt lesen...
Ohne delay müsste er dazu wohl Schnellleseweltmeister sein :-)

von Karl H. (kbuchegg)


Lesenswert?

U.R. Schmitt schrieb:
> Karl heinz Buchegger schrieb:
>> Messages auf ein LCD schreibt mit Wartezeiten dazwischen, lass ich mal
>> dahingestellt)
>
> Na ja er will seine Nachrichten halt lesen...
> Ohne delay müsste er dazu wohl Schnellleseweltmeister sein :-)

Wenn ich den Smily nicht gesehen hätte, hätte ich gesagt: Wozu die 
Meldungen?

Aber da ich den :-) gesehen habe, sag ich jetzt nichts.

(Vor einiger Zeit war hier im Forum ein Programm zu bewundern, das 
ähnliches machte.
Am LCD: 1. Zeile    "Booting"
        2. Zeile    eine Punktzeile die länger wurde
während die Punktzeile aufgebaut wurde, hat das Programm nichts anderes 
gemacht als zu warten. Hätte er sich das gespart, hätte es nicht so cool 
ausgesehen, allerdings wäre der µC sofort einsatzbereit gewesen.
Soll ich noch ergänzen, dass das so ziemlich die einzige Funktionalität 
im Programm war, die funktioniert hat?)

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.