Forum: Compiler & IDEs sleep als delay


von Markus G. (happyhippo4u)


Lesenswert?

Moin,

Ich würde gerne mit dem bereits vorhandenen Codemöglichkeiten eine 
Sleepfunktion basteln. In diesem Forum habe ich dazu die funktion 
_delay_ms(msec); gefunden. Diese Funktion hat jedoch ein Maximum von 
262.14 msec bei 1MHz CPU-Frequenz. Ist die Frequenz 8 mal so hoch ist 
der maximalwert für die Millisekunden 8 mal kleiner so weit ich das 
bislang verstehe.

Deshalb habe ich mir die funktion sleep (siehe weiter unten) ausgedacht.
Das Problem war nun eine Warning.

In der Hauptdatei.c des ganzen Programms hatte ich oben # define F_CPU 
8000000UL geschrieben und bekam die Meldung F_CPU sei redefiniert. Also 
habe ich es weggelassen und bin davon ausgegangen, dass der Standard 
1MHz ist.

Bei folgendem Code ist das ganze aber trotzdem viel zu schnell (bzw 
die Zeitspanne zu kurz):

#include <util/delay.h>
#define CPUFREQUENCY 8 // 8 MHz

int sleep(uint32_t msec) {
  //repeat_nothing(msec*240);
  double max_delay = 262.14 / CPUFREQUENCY;
  msec = msec * CPUFREQUENCY;
  if (msec > max_delay)
  {
    msec = msec - max_delay;
    _delay_ms(max_delay);
  }
  else
  {
    _delay_ms(msec);
  };
};


int main (void) {

   DDRD  = 0xff; //Datenrichtung

   sleep(1000);
   PORTD |= (1<<PD4);
   sleep(1000);
   PORTD |= (1<<PD3);
   sleep(1000);
   PORTD |= (1<<PD2);
   sleep(1000);
   PORTD |= (1<<PD1);
   sleep(1000);
   PORTD |= (1<<PD0);

Hat jemand eine Idee, wie man das vernünftig macht ohne einen Timer zu 
benutzen? Ich benötige alle Timer für was anderes und dann wird mir das 
alles zu kompliziert, wenn man dann auch noch Timer aufteilen muss.

von Stefan (Gast)


Lesenswert?

Die Antwort hat Dir der (pre)compiler schon gegeben: F_CPU ist schon 
definiert. Guck mal ins makefile, da sollte man dann die richtige 
frequenz einstellen. Die _delay.... Routinen verwenden auch den Wert 
F_CPU.

Aber was ganz anders: Werden derartig lange Pausen benötigt, deutet das 
auf ein nicht richtig gutes Softwaredesign hin.

Stefan

von Ulrich (Gast)


Lesenswert?

@Stefan:
kommt immer drauf an. Wenn nur ein Ding gleichzeitig passiert wäre es 
doch recht blöd wenn man den Timer einschaltet. (Außer stromsparen 
usw....)
Wenn man allerdings  noch irgend eine andere Schnittstelle usw. bedienen 
muss dann geht das nicht und du hast völlig recht. dann sollte man sein 
softwaredesign verändern.

von Markus G. (happyhippo4u)


Lesenswert?

verdammt... ich hatte die Whileschleife vergessen...

int sleep(int32_t msec) {
  //repeat_nothing(msec*240);
  double max_delay = 262.14 / CPUFREQUENCY;
  msec = msec * CPUFREQUENCY;
  while (msec>0) {
    if (msec > max_delay)
    {
      msec = msec - max_delay;
      _delay_ms(max_delay);
    }
    else
    {
      msec = msec - max_delay;
      _delay_ms(msec);
    };
  };
};

so gehts einwandfrei ^^

BTW: Kann man hier abgegebene Beiträge wieder löschen? ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

_delay_ms() und _delay_us() sollten ausschließlich Argumente
übergeben bekommen, die bereits zur Compilezeit konstant sind,
ansonsten kann der Overhead u. U. erheblich werden, die
Startwerte für die Zählschleife zu berechnen.  Das hängt damit
zusammen, dass sie alles im Gleitkommabereich rechnen, damit die
Benutzung möglichs bequem für den Anwender wird, es lässt sich
also sowas machen wie
1
#define MHz  * 1e6
2
#define F_CPU 3.8684 MHz
3
4
#include <util/delay.h>
5
6
void
7
delay_355ms(void)
8
{
9
  uint8_t i;
10
11
  for (i = 0; i < 100; i++)
12
    _delay_ms(3.55);
13
}
Sofern die Optimierungen eingeschaltet sind, werden all die
aufwändigen Gleitkomma-Rechnungen vom Compiler erledigt, der
Code enthält dann:
1
        ldi r18,lo8(0)
2
        ldi r30,lo8(3433)
3
        ldi r31,hi8(3433)
4
.L2:
5
        movw r24,r30
6
/* #APP */
7
        1: sbiw r24,1
8
        brne 1b
9
/* #NOAPP */
10
        subi r18,lo8(-(1))
11
        cpi r18,lo8(100)
12
        brne .L2
Für längere Zeiten nimmt man sowieso besser einen Timer.  Diese
Funktionen sind wirklich nur für kurze Intervalle sinnvoll, bei
denen es sich nicht lohnen würde, erst einen Timer anzuwerfen.

von AVRFan (Gast)


Lesenswert?

>Hat jemand eine Idee, wie man das vernünftig macht ohne einen Timer zu
>benutzen?

Ich nicht.  Es gibt nichts Vernünftigeres als Timer zu benutzen, und 
nichts Unvernünftigeres als mit Delay-Schleifen zu arbeiten.

>Ich benötige alle Timer für was anderes

Das glaubst Du.  Ich vermute, Du kämst bestens mit einem einzigen 
Timer aus, wenn Du Dein Proggi entsprechend richtig aufbauen würdest.

>und dann wird mir das alles zu kompliziert, wenn man dann auch noch Timer
>aufteilen muss.

Der Grund für "Alles wird in Nullkommanix kompliziert" ist immer 
derselbe, nämlich ein schlechtes Softwaredesign.

von 1001. Rahul (Gast)


Lesenswert?

>nämlich ein schlechtes Softwaredesign.

Mancheiner sollte seine beiden Brötchen mal wieder etwas anfeuchten...

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.