www.mikrocontroller.net

Forum: Compiler & IDEs Was anderes als "delay_ms" ?


Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @ all,

ich brauche unbedingt eine "Zeitschleife" in der ich per 
Übergabeparameter eine gewissen Zeit warte, jedoch müssen während dieser 
Wartezeit auch noch andere "Aufgaben" (Interuptauslösung) abgearbeitet 
werden.

Was mich dann gezwungenermaßen dazu bewegt einen Timer zu verwenden aber 
wie kann ich den Timer per Übergabewert (z.B. 10ms) so nutzen wie die 
delay_ms() Funktion... geht das überhaupt ?

Ich sitz da schon eine ganze Weile davor, vielleicht seh ich deshalb 
auch den Wald vor Bäumen nicht mehr aber ich hab momentan keine Ahnung 
wie ich das machen soll!

Gruß Andreas P.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie groß ist der minimale/maximale Wert der Wartezeit?

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

Bewertung
0 lesenswert
nicht lesenswert
Du initialisiert den Timer so, dass er regelmäßig (bspw. alle 1 ms)
einen Interrupt auslöst.  In diesem Interrupt zählst du eine Variable
hoch.  Dein delay_ms() könnte dann so aussehen:
#include <avr/io.h>
#include <util/atomic.h>

volatile int32_t ticks;

ISR(TIMER1_COMPA_vect)
{
  ticks++;
}

void delay_ms(int32_t ms)
{
  int32_t now, target;

  ATOMIC_BLOCK(ATOMIC_FORCEON) { now = ticks; }

  target = now + ms;

  do {
    ATOMIC_BLOCK(ATOMIC_FORCEON) { now = ticks; }
  } while (now - target < 0);
}

Autor: delay (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
mit dieser Variante hat er aber einen Jitter von 1ms. Soll heißen das 
wenn er pech hat gar nicht wartet.
Besser ist es den Timer direkt in der Funktion zu setzten und zu 
starten.

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

Bewertung
0 lesenswert
nicht lesenswert
delay schrieb:
> mit dieser Variante hat er aber einen Jitter von 1ms.

Ja, hängt von der Anwendung ab, ob das ein Problem wird.  Meist braucht
man aber in einer Applikation ohnehin einen regelmäßig laufenden Timer,
da kann man das einfach reinklinken.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich brauch die Wartefunktion für min. 1ms - max 1600ms.
Ich brauch die Wartezeit für eine LIN-/CAN Kommunikation und daher auch 
nicht die Standard DELAY_MS, da mir sonst wichtige Infos verloren gehen 
könnten!

Was wäre für diese Anwendung jetzt die beste Variante als Warteschleife 
?

Thx Andreas

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:

> Was wäre für diese Anwendung jetzt die beste Variante als Warteschleife
> ?

Gar keine.

In dem Moment, in dem du Warten und Zählschleifen in einem Satz nennst 
(jetzt mit Ausnahme von kleinen Schleifen im µs bereich), stinkt das 
nach Ärger.

Ist einfach so.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich die standard "delay_ms" verwende kann parallel nichts weiteres 
ausgeführt werden..... wenn ich jedoch einen Timer mit Interrupten nutze 
können noch nebenbei weitere Zeichen per Interrupt empfangen werden...
Oder etwa nicht ?!

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
delay_ms kann von Interrupts unterbrochen werden, nur stimmt die zeit 
dann nicht mehr ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:
> Wenn ich die standard "delay_ms" verwende kann parallel nichts weiteres
> ausgeführt werden..... wenn ich jedoch einen Timer mit Interrupten nutze
> können noch nebenbei weitere Zeichen per Interrupt empfangen werden...
> Oder etwa nicht ?!

Das können sie sowieso solange du die Interrupts nicht abdrehst.

Im Grunde hast du nämlich durch einen Timer und dem aktiven darauf 
warten, dass dieser Timer runtergezählt hast, nicht sehr viel gewonnen. 
OK, die Wartezeit wird auch dann noch stimmen, wenn während des Wartens 
Interrupts auftreten. Aber: Du hast im Grunde ja noch immer eine aktive 
Warteschleife und damit steht alles andere (was nicht über Interrupts 
läuft wie zb Tastenabfrage, Displayaktualisierung etc)

Das beste ist es, seine grundsätzliche Denkweise umzustellen. Nicht mehr 
in Schleifen und in Wartezeiten denken, sondern in Ereignissen.
Du bleibst ja auch nicht bei einem Wecker sitzen und wartest, bis der 
die Wckzeit runtergezählt hat. Stattdessen machst du irgendetwas anderes 
und wenn die Zeit rum ist, dann benachrichtigt dich der Wecker.

So ähnlich funktionier auch meistens ein empfehlenswerter Programmaufbau 
im µC:

Es gibt nur 1 Schleife und das ist die Hauptschleife in main.
In dieser Schleife werden alle möglichen Ereignisse nacheinander 
abgeprüft, ob sie eingetreten sind. Wenn ja, dann wird die zughörige 
Aktion ausgeführt, wenn nein, dann wird reihum immer wieder das nächste 
mögliche Ereignis geprüft, ob es vorliegt.

Mit so einem Programmaufbau schafft man es Programme zu schreiben, die 
scheinbar mehrere Dinge gleichzeitig machen.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also hier mal ein Bsp für mein Problem.

Während ich meine Standard Nachrichten verschicke (alle 5ms) muss ich 
gleichzeitig den Datenverkehr auf dem LIN mitloggen und auf eine 
SD-Karte speichern.
Wenn jetzt während der 5ms Wartezeit eine Nachricht empfangen wird, 
könnte mir die delay_ms wichtige Infos verwerfen.... sprich ich bekomme 
nichts von der empfangenen Nachricht mit.

Das Problem muss ich jetzt irgendwie in den Griff bekommen... das muss 
doch irgendwie gehen. Da ich aber das erstemal vor dem Problem stehe 
weiß ich jetzt auch nicht wirklich wie ich da weiter machen soll.

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:
> Das Problem muss ich jetzt irgendwie in den Griff bekommen... das muss
> doch irgendwie gehen.

Ja, aber nicht durch warten. ;-)

Du brauchst irgendeine Art von scheduler, auch ein kleines OS kann
hilfreich sein.

Ersteres habe ich mal selbst geschrieben:

http://www.sax.de/~joerg/avr-timer/

Auch wenn das "one-shot timers" sind, kann man damit regelmäßige
tasks (wie "alle 5 ms meine Standard Nachrichten verschicken")
erledigen: im timer callback wird als erstes eine neuer Timer für
5 ms programmiert, danach schickt der callback die "Standard-
Nachricht".

main() besteht nur noch aus einer Endlosschleife, die könnte
sich eigentlich sogar noch ein sleep_mode() leisten (solange man
im idle sleep bleibt, d. h. der Systemtakt läuft weiter).  Alle tasks
lässt man über die Timer anwerfen, der Rest tüddelt als Interrupts
ohnehin von außen ein.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
könnte man wie folgt machen...

1ms Timer...

in ISR

{
if (5ms um)
 ...

(else) if (LIN)
  ...

(else) if (SD Karte)
  ...

}

kommt natürlich drauf an ob das alles in unter 1ms erledigt werden kann 
(wenn nicht alles zusammen dann halt if ... else if)

Autor: Leo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wartezeiten effektiv (Scheduler)
Beitrag "Wartezeiten effektiv (Scheduler)"

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg Wunsch
Da in meiner Schedule ca. 30 Nachrichten verschickt werden, gehen mir 
ca. >150ms an Wartezeit verloren.
Ich habe auch eine Schedule, siehst wie folgt aus:
int main()
{
  while (1)
  {
    if(Taster_S==1)
    {
     MSG_Lin_Init();  // LIN Nachrichteninhalt
     Schedule();  // starten der MAXSchedule
    }
  }
}

void Schedule()
{
 Sende(msg1);
 delay_ms(5);
 Sende(msg2);
 delay_ms(5);
 Sende(msg3);
 delay_ms(5);
 Sende(msg4);
 delay_ms(5);
 Sende(msg5);
 delay_ms(5);
 Sende(msg6);
 delay_ms(5);
 ...
 Sende(msg30);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:


Dein Beispiel ist ja schon fast ein Schulbuchbeispiel dafür, wie und wo 
man den oben angesprochenen Ansatz mit Ereignissen sinnvoll einsetzen 
kann (und noch eine kleine State-machine in Ansätzen drüberstreut)

> Ich habe auch eine Schedule, siehst wie folgt aus:

Und genau das ist der Ansatz wie man es nicht macht :-)
Du hast nämlich keinen Scheduler, du hast aktive Warteschleifen und 
genau deswegen rennst du in Probleme.
Nur weil du etwas 'Schedule' nennst, wird es dadurch nicht dazu.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als allererstes brauchst du einen Timer, der dir samt ISR die 
Millisekunden zählt. Ob du da jetzt 1 Millisekunde oder gleich 5 in 
einem Aufwasch abzählst, ist Geschmackssache und hängt auch davon ab, ob 
du im restlichen Programm die 5 bzw 1 Millisekunden noch an anderen 
Stellen sinnvoll einsetzen kannst.

Aber gehen wir mal davon aus, dass du eine ISR hast, die dir 5 
Millisekunden runterzählt. Die funktioniert wie ein Wecker: Du ziehst 
sie auf, indem du einer Variable die Zeit zuweist.

volatile int8_t WaitTime;     // die Wartezeit zb in 1/10 Millisekunden 
                              // Ist die Zeit positiv, dann läuft der
                              // Wecker noch
                              // Ist sie 0, dann ist der Wecker abgelaufen
                              // und das Ereignis soll bearbeitet werden
                              // Ist sie negativ, dann ist der Wecker abgelaufen
                              // aber das Ereignis wurde schon behandelt



ISR( .... )     // wird regelmässig aufgerufen, in 1/10 Millisekunden Einheiten
{
  if( WaitTime > 0 )
  {
    WaitTime--;
  }
}



int main()
{
   ....

  WaitTime = 50;

  sei();

  while( 1 )
  {
    if( WaitTime == 0 )     // 5ms sind rum?
    {
      WaitTime = 50;

      nextMsg++;
      if( nextMsg == 31 )
        nextMsg = 0;

      Sende( msg[nextMsg] );
    }

    ...XXX...
  }
}

Das sendet nacheinander alle 30 Messages( die in einem Array stehen), 
wobei zwischen den Messages jeweils 5 Millisekunden Pause eingelegt 
werden. Und zwar ohne das irgendwo ein _delay passiert. Die Anweisungen 
an der Stelle ...XXX... werden laufend ausgeführt, auch dann (oder 
speziell dann), wenn die 5 Millisekunden Wartezeit laufen.
Deine Aufgabe ist es jetzt noch, den Timer entsprechend einzurichten. Ob 
du den jetzt so einstellst, dass die ISR alle 1/10 Millisekunden oder 
alle Millisekunden oder alle 1/100 Millisekunden aufgerufen wird, ... 
das musst du entscheiden und macht sich im Grunde nur in den 
Zahlenwerten bemerkbar. Ich habe hier 50 genommen, weil ich davon 
ausgegangen bin, dass die ISR alle 1/10 Millisekunden aufgerufen wird. 
Bei dir mag das anders aussehen.

Wichtig ist hier das Prinzip:
WaitTime ist ein Ereignisanzeiger. Durch einen speziellen Wert zeigt er 
hier an, dass ein bestimmtes Ereignis (nämlich das Ablaufen der 
Wartezeit) eingetreten ist. Ist das Ereignis da, so wird es behandelt, 
indem die zugehörigen Aktionen ausgeführt werden.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich möchte nochmal das Thema hier aufgreifen, da ich wieder (noch immer) 
vor dem Problem stehe gewisse Operationen in bestimmten Zeitabständen zu 
starten.

Das Versenden der Nachrichten habe ich wie oben beschrieben gelöst, 
jedoch benötige ich noch für viele kleine weitere Aufgaben einen 
"delay".
z.B.
- beim Drücken eines Tasters nicht gleich 20 Tastendrücke zu erkennen 
habe ich ein Delay_ms von 200ms eingefügt
- versenden einzelnes Requests/Response
- ...

Ich habe mir auch mal den Schedule angeschaut der oben gepostet wurde, 
jedoch blicke ich da nicht durch. Der Code ist mir viel zu komplex.

Vielen dank schonmal !!

Gruß Andreas

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas P. schrieb:

> Ich habe mir auch mal den Schedule angeschaut der oben gepostet wurde,
> jedoch blicke ich da nicht durch. Der Code ist mir viel zu komplex.

Der wichtigste Grundgedanke ist es, einen Timer samt zugehöriger ISR als 
eine Art 'interne Uhr' oder 'interner Takt' einzusetzen. Das ist dein 
Basistakt, von dem alles andere ausgeht.

Einen Timer aufsetzen kannst du hoffentlich. Die Weiterführung, einen 
Timer so aufzusetzen, dass alle regelmässige Zeitintervalle x eine ISR 
aufgerufen wird, sollte auch kein Problem sein.

Mal angenommen, du hast einen Timer, der alle 10ms seine 
Overflowbedingung erreicht. Dann kannst du zb daraus eine runterzählende 
Uhr bauen, indem du einen Zähler installierst, der alle 10ms um 1 
verringert wird (so er nicht 0 ist)
volatile int8_t timeCounter;   // > 0   Stoppuhr läuft
                               // == 0  Stoppuhr ist abgelaufen
                               // < 0   Stoppuhr ist abgelaufen und ausgewertet

ISR( ..... )   // wird alle 10ms aufgerufen
{
  if( timeCounter > 0 )
    timeCounter--;
}

Setzt du hier zb den timeCounter auf 100, dann wird dieser Zähler nach 1 
Sekunde (mit einem kleinen Jitter) durch laufende ISR Aufrufe wieder den 
Wert 0 erreichen.

Du kannst damit zb in deiner main() das hier machen
int main()
{
  ....
  Timer initialisieren, so dass die ISR alle 10ms aufgerufen wird
  ...

  timeCounter = -1;    // Stoppuhr ist in Grundstellung
                       // läuft nicht und es ist auch nichts auszuwerten

  while( 1 ) {

    if( Irgendwas_zb_ein Taster wird gedrückt ) {
      timeCount = 100;          // Stoppuhr starten
      LED einschalten;
    }


    if( timeCount == 0 ) {      // ist die Stoppuhr abgelaufen und noch nicht ausgewertet?
      LED ausschalten;
      timeCount = -1;
    }

    ... (A) mach ganz was anderes

  }
}

dann hast du die Funktionalität, dass eine LED sich auf Tastendruck 
einschaltet und 1 Sekunde später wieder abschaltet.
Aber:
Da ist nirgends ein _delay_ms. Während die Zeit runterzählt, kommt deine 
Hauptschleife immer wieder an der Stelle (A) vorbei und kann dort Arbeit 
erledigen.

Dieser timeCount ist eine spezielle Form eines Jobflags, in der eine ISR 
der Hauptschleife mitteilt, dass es Arbeit zu tun gibt. In diesem Fall 
zählt die ISR im Prinzip im Jobflag mit, wie oft sie schon aufgerufen 
wurde und die Hauptschleife weiß, dass es bei einem Wert von 0 etwas zu 
tun gibt.

Das ist jetzt nur ein Beispiel. So ein oder ein ähnliches Prinzip lässt 
sich auf vieles übertragen. Tasten entprellen wird man zb 
sinnvollerweise komplett in der ISR abhandeln (siehe den Wiki Artikel 
"Entprellung") und der Tastendruck selber ist das Jobflag, das in der 
Hauptschleife abgefragt wird.


Das andere Konzept, das man an dieser Stelle oft sinnvoll einsetzen 
kann, ist das Konzept einer Statemachine (oder Zustandsautomat). Dein 
Programm oder dein Prozess ist in einem bestimmten Zustand, ausgedrückt 
durch einen Wert, der in einer State-Variablen steht. Die Maschine 
wechselt zustände durch äussere Einflüsse wie zb Zeit abgelaufen (wie 
man das macht, kennst du schon) oder Tastendrücke oder eintreffende 
Nachrichten oder was auch immer.

Die Zustände bzw. die Zustandswechsel sind mit Aktionen verknüpft, die 
ausgeführt werden, wenn das entsprechende Ereignis eintritt. Die 
Auswertung des Zustands erfolgt wiederrum in der main()-Hauptschleife.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal als Beispiel 2 Statemaschines in Aktion.

Die Aufgabenstellung sei:
Es seien 2 LED im System. Die eine soll permanent 2 mal in der Sekunde 
blinken, die andere soll auf Tastendruck eingeschaltet und nach 1 
Sekunde wieder ausgeschaltet werden. Und natürlich soll der eine 
'Prozess' den anderen nicht beeinflussen. Zumindest nicht soweit, dass 
die Zeiten grob daneben liegen.

Ich möchte das mit Hilfe von 2 Zustandsmaschinen implementierten.
Die eine kümmert sich um LED 1 (die permanent blinkende), die andere um 
LED 2.

Da es in beiden Maschinen um Zeiten geht, postuliere ich wieder eine 
innere Uhr, die in diesem Fall 2 'Stoppuhren' runterzählt. Basistakt sei 
wieder 10ms.

dann hab ich

volatile uint8_t timeCount1;     // blinkende LED
volatile uint8_t timeCount2;     // Tastengesteuerte LED

ISR( .... )
{
  if( timeCount1 > 0 )
    timeCount1--;

  if( timeCount2 > 0 )
    timeCount2--;
}

Gut. Die Stoppuhren sind damit lauffähig.
Wie sieht das mit der blinkenden LED aus? In welchen 'Zuständen' kann 
der Prozess sein?
Man kann das jetzt mit 2 oder mit 4 Zuständen machen.
Bei 4 Zuständen sind diese
   LED_ON_WAIT          Die Led wartet die 'ein' Zeit ab
   LED_OFF_WAIT         Die Led wartet die 'aus' Zeit ab
   LED_TURN_ON          Die Led soll eingeschaltet werden
   LED_TURN_OFF         Die Led soll ausgeschaltet werden

Was die einzelnen Zustände machen, ist auch schnell dokumentiert. Im 
Zustand 'warten' (egal welcher) wird einfach nur die zugehörige Stoppuhr 
überwacht und wenn sie abgelaufen ist, gehts weiter in den nächsten 
Zustand, in dem je nachdem die Led ein oder ausgeschaltet wird und die 
Stoppuhr wieder neu gestartet wird
uint8_t blinkLedState;

#define LED_ON_WAIT   0
#define LED_OFF_WAIT  1
#define LED_TURN_ON   2
#define LED_TURN_OFF  3

void blinkLed( void )
{
  switch( blinkLedState ) {
    case LED_ON_WAIT:
      if( timeCount1 == 0 )     // abgelaufen?
        blinkLedState = LED_TURN_OFF;     // nächster Zustand: LED ausschalten
      break;

    case LED_OFF_WAIT:
      if( timeCount1 == 0 )     // abgelaufen?
        blinkLedState = LED_TURN_ON;      // nächster Zustand: LED einschalten
      break;

    case LED_TURN_ON:
      LED einschalten;
      timeCount1 = 25;               // Uhr aufziehen
      blinkLedState = LED_ON_WAIT;   // nächster Zustand ist ON Zeit abwarten
      break;

    case LED_TURN_OFF:
      LED ausschalten;
      timeCount1 = 25;               // Uhr aufziehen
      blinkLedState = LED_OFF_WAIT;   // nächster Zustand ist ON Zeit abwarten
      break;
  }
}

wird diese Funktion in der Hauptschleife wieder und immer wieder 
aufgerufen, so sorgt sie dafür, dass die LED blinkt.
Die Variante mit nur 2 Zuständen, ist einfach nur eine Zusammenlegung 
der WAIT und der Schalt-Zustände, indem der Zustandswechsel nicht 
einfach nur den Zustand wechselt sondern auch noch eine Aktion ausführt.
uint8_t blinkLedState;

#define LED_TURN_ON   0
#define LED_TURN_OFF  1

void blinkLed( void )
{
  switch( blinkLedState ) {

    case LED_TURN_ON:
      if( timeCount1 == 0 ) {
        LED einschalten;
        timeCount1 = 25;
        blinkLedState = LED_TURN_OFF;
      }
      break;

    case LED_TURN_OFF:
      if( timeCount1 == 0 ) {
        LED ausschalten;
        timeCount1 = 25;
        blinkLedState = LED_TURN_ON;
      }
      break;
  }
}

Damit ist die erste LED abgehandelt. Bleibt nur noch die andere LED. 
Wiedrrum modelliere ich dafür eine Statemaschine.
Die kann die Zustände haben

  LED_AUS
  LED_WARTE

Wie erfolgt der Zustandswechsel?
Von LED_AUS geht es nach LED_WARTE, wenn eine Taste gedrückt wurde. Die 
Aktion die dabei auszuführen ist, lautet: Uhr aufziehen, Led 
einschalten.
Von LED_WARTE wird in den Zustand LED_AUS gewechselt, wenn die Uhr 
abgelaufen ist.

Wenn das soweit klar ist, dann schreibt sich das schon fast von alleine
uint8_t pressedLedState;

#define LED_AUS     0
#define LED_WARTE   1

void pressedLed( void )
{
  switch( pressedLedState) {

    case LED_AUS:
      if( Taste_gedrueckt ) {
        LED einschalten;
        timeCount2 = 100;
        pressedLedState = LED_WARTE;
      }
      break;

    case LED_WARTE:
      if( timeCount2 == 0 ) {
        LED ausschalten;
        pressedLedState = LED_AUS;
      }
      break;
  }
}

bleibt nur noch die main, die nacheinander beiden Zustandsmaschinen im 
Wechsel Gelegenheit zum Arbeiten gibt.
int main()
{
 ....

  while( 1 ) {
    blinkLed();
    pressedLed();
  }
}


Das ist jetzt wieder nur ein Beispiel. Das allgemeine Schema kann und 
soll man natürlich auf seine speziellen Belange zurechtschneiden.
Das was du in der klassischen Schleifenprogrammierung mittels

    while( Zeit nicht abgelaufen )
      warte;

erreichst, wird hier dadurch realisiert, dass die Zustandsmaschine in 
einem bestimmten Zustand ist und nur überprüft, ob die Bedingung 
eingetreten ist, diesen Zustand wieder zu verlassen.
Nur müssen sich alle Prozesse an bestimmte Regeln halten. Und die 
wichtigste aller Regeln: Niemand macht _delay, nirgends wird gewartet, 
kein Zustand verbraucht exzessiv Rechenzeit.
Hat man tatsächlich einmal den Fall, dass ein Zustand komplexe 
Berechnungen durchführen muss, die länger dauern, dann kann man diesen 
Zustand in mehrere Teilzustände unterteilen, wobei jeder Teilzustand 
jeweils auf den nächsten weiterschaltet und die Kontrolle wieder zurück 
an die Hauptschleife gibt. Erlangt der Prozess dann wieder die Kontrolle 
so wird die Berechnung im nächsten Zustand weitergeführt oder beendet. 
Dies deshalb, damit reihum jede Zustandsmaschine regelmässig ein bischen 
Rechenzeit bekommt, um ihre eigenen Belange zu regeln.

Autor: Andreas P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl heinz,

werde meine Wartezeiten jetzt mal mit einem Counter, nach deinem 
Prinzip, umbauen.
Habe einen 1kHz Counter mit dem das dann wunderbar funktionieren sollte!
Danke nochmals !!!

Gruß Andreas

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Multitasking.

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.