mikrocontroller.net

Forum: Compiler & IDEs sleep als delay


Autor: Markus Gronotte (happyhippo4u)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus Gronotte (happyhippo4u)
Datum:

Bewertung
0 lesenswert
nicht 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? ;)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
#define MHz  * 1e6
#define F_CPU 3.8684 MHz

#include <util/delay.h>

void
delay_355ms(void)
{
  uint8_t i;

  for (i = 0; i < 100; i++)
    _delay_ms(3.55);
}
Sofern die Optimierungen eingeschaltet sind, werden all die
aufwändigen Gleitkomma-Rechnungen vom Compiler erledigt, der
Code enthält dann:
        ldi r18,lo8(0)
        ldi r30,lo8(3433)
        ldi r31,hi8(3433)
.L2:
        movw r24,r30
/* #APP */
        1: sbiw r24,1
        brne 1b
/* #NOAPP */
        subi r18,lo8(-(1))
        cpi r18,lo8(100)
        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.

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: 1001. Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>nämlich ein schlechtes Softwaredesign.

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.