www.mikrocontroller.net

Forum: Compiler & IDEs Zeitgesteuerter Programmablauf mit ATMEGA1280


Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
in meinem Programm sollen ein paar Temperatursensoren und weitere 
Sensoren alle 10 Sekunden abgefragt werden. Manche Sensoren sollen aber 
auch dauernd abgefragt werden. Auch die UART wird die ganze Zeit 
abgefragt und bekommt jede Sekunde einen NMEA Datensatz übermittelt, der 
verarbeitet wird.
Ausserdem will ich bestimmte while-Schleifen mit einem Timeout nach ein 
paar Sekunden beenden.
Zusätzlich sollen in verschiedenen Zeiten verschiedene Strings 
übermittelt werden.
Timer1 habe ich aktiviert und jede ms wird eine Interrupt-Routine 
durchlaufen.

So zu meiner Frage: Wie realisiere ich die Zeitsteuerung am besten bzw. 
einfachsten?

Mein erster Gedanke war in der Interrupt-Schleife mehrere Variablen hoch 
zu zählen und beim Erreichen eines bestimmten Wertes wieder 0-Zu-Setzen.
In meinen einzelnen Programmabschnitten vergleiche ich dann die 
einzelnen Variablen mit einem bestimmten Wert und führe die Funktionen 
dann bei Übereinstimmung aus.
Den Timeout erzeugt ich dann so, dass ich beim Erreichen der Schleife 
den Variablenwert speicher und wenn die Schleife wiederholt wird mit dem 
aktuellen Wert vergleiche. Bei z.B. 3 Sekunden unterscheidet sich der 
Wert um >= 3 und die Schleife wird beendet.

Ich habe aber auch den Scheduler von Peter Dannegger gefunden
Beitrag "Wartezeiten effektiv (Scheduler)"
Ist das die beste Lösung für meine Aufgabe? Oder schieße ich damit mit 
Kanonen auf Spatzen?
Wisst ihr zu diesen Problemstellungen ein gutes Tutorial oder eine 
hilfreiche Seite?
Vielen Dank für eure Hilfe.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter Dannegger:
Würde deinen Scheduler gerne nutzen und ausprobieren, aber es kommen 
beim compilieren schon einige Fehler, die ich nicht lösen kann.
Was ich verändert habe ist:
TCCR0 = 1<<CS02; in TCCR0B = 1<<CS02;
TIMSK = 1<<TOIE0; in TIMSK0 = 1<<TOIE0;

XTAL 8e6
und
#include <avr/signal>
habe ich gelöscht!
Sonst habe ich nichts verändert. Mein µC ist ein ATMEGA1280

Die Ausgabe des Compilers:
Compiling C: main.c
avr-gcc -c -mmcu=atmega1280 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -fno-inline-small-functions             -Wa,-adhlns=./main.lst  -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o 

Linking: main.elf
avr-gcc -mmcu=atmega1280 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -fno-inline-small-functions             -Wa,-adhlns=main.o  -std=gnu99 -MMD -MP -MF .dep/main.elf.d main.o SCHEDULE.C TOV0.C GETKEY.C main.h --output main.elf -Wl,-Map=main.map,--cref     -lm
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but not for C++
SCHEDULE.C: In function 'unsigned char timeradd(void (*)(), unsigned int)':
SCHEDULE.C:39: warning: 'ipre' may be used uninitialized in this function
SCHEDULE.C: In function 'unsigned char timerremove(void (*)())':
SCHEDULE.C:82: warning: 'irem' may be used uninitialized in this function
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but not for C++
TOV0.C: In function 'void __vector_23()':
TOV0.C:18: warning: suggest parentheses around arithmetic in operand of ^
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but not for C++
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe:main.o: file format not recognized; treating as linker script
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe:main.o:1: syntax error
make.exe: *** [main.elf] Error 1

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nenn mal alle *.C in *.c um.


Peter

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok super. Funktioniert jetzt alles bestens.
Noch zwei Fragen dazu:
1. Mein Compiler gibt die Warnmeldung raus:
Compiling C: TOV0.c
avr-gcc -c -mmcu=atmega1280 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -fno-inline-small-functions             -Wa,-adhlns=./TOV0.lst  -std=gnu99 -MMD -MP -MF .dep/TOV0.o.d TOV0.c -o TOV0.o 
TOV0.c: In function '__vector_23':
TOV0.c:18: warning: suggest parentheses around arithmetic in operand of ^

2. Mein Compiler gibt die folgende Warnmeldung raus:
Kann ich die zwei Variablen einfach =0 setzen?
SCHEDULE.c: In function 'timeradd':
SCHEDULE.c:39: warning: 'ipre' may be used uninitialized in this function
SCHEDULE.c: In function 'timerremove':
SCHEDULE.c:82: warning: 'irem' may be used uninitialized in this function

Danke für deine Hilfe!

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verstehe ich das eigentlich richtig, dass ich keine while-Schleife mehr 
benutzen darf, weil sonst das Timing durcheinander kommt?

z.B. frage ich in meiner main loop einen NMEA-Datensatz ab und schreibe 
alle benötigten Werte in verschiedene Arrays. Bei der Abfrage werden ein 
paar while-Schleifen benutzt um auf verschiedene Zeichen zu "warten".

Dem Scheduler adde ich eine Funktion die nur eine Ausgabe auf einer 
anderen uart-Schnittstelle macht und sich dann wieder selber "addet", im 
sekundentakt.
Die Ausgabe ist dann aber nicht sekündlich, sondern teilweise um einiges 
länger. Kann ich das dann auch umgehen oder muss ich das so hinnehmen.
Wäre nicht sonderlich schlimm, aber besser, wenn es genau wäre.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktionen dürfen nicht länger dauern, als ein Aufruftakt des 
Schedulers, sonst verliert man Takte.

Bei der UART ist das aber kein Problem, die kann man ja mit Interrupt 
machen. D.h. der Scheduler schreibt nur in den Sendepuffer und der 
UART-Interrupt sendet dann Byte für Byte.


Peter

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also meine uarts sind interruptgesteuert. Das ist deine Lib die ich 
verwende.
Wäre es dann sinnvoll den Aufruftakt zu verlängern?
Bei mir dauert der bisher 8,2ms, wenn ich mich nicht verrechnet habe.
Was wäre ansonsten denn dann eine Alternative zu z.B.

while ( zeichen != '\n');  // Zeilende v. Datensatz erkennen

?
Danke.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bene Jan schrieb:
> Was wäre ansonsten denn dann eine Alternative zu z.B.
>
> while ( zeichen != '\n');  // Zeilende v. Datensatz erkennen

Nicht wartend, sondern abbrechend programmieren.
Hat eine Funktion nichts zu tun, gibt sie die Rechenzeit der Mainloop 
zurück.

Schlecht:
main()
{
while( 1 ){
  fkt1();
  fkt2();
  fkt3();
  ...
  fktn();
]

fkt1()
{
  while( bedingung == unwahr );
  mache_was();
}

Gut:
main()
{
while( 1 ){
  fkt1();
  fkt2();
  fkt3();
  ...
  fktn();
]

fkt1()
{
  if( bedingung == unwahr )
    return;
  mache_was();
}

Hat eine Funktion an mehreren Stellen zu warten, setzt sie sich einen 
Merker (Variable), wo sie weiter machen muß (switch/case).


Peter

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,
ich habe mal versucht eine Funktion von mir abbrechend zu programmieren. 
Das ganze funktioniert soweit, ist aber höchst wahrscheinlich alles 
andere als perfekt. In meiner main loop befindet sich nur der Aufruf zu 
dieser Funktion und die if-Schleife (f_timer_tick) von dir.
Ausserhalb der mainloop wird eine Funktion geadded die das Ergebnis 
meiner Funktion auf die uart 1x pro Sekunde ausgibt und sich dann wieder 
selber added.
Ich erreiche aber leider keine genaue Sekunde (mehr oder weniger), eher 
2 Sekundentakt.
Du hattest in einem anderen Thread geschrieben, dass man die Ablaufzeit 
größer machen soll, damit die mainloop mindestens einmal pro Tick 
durchlaufen wird, wenn ich das richtig verstanden habe.
Ich habe dann in der main.h
#define TIMERTICK  (XTAL  256  256)
ersetzt mit
#define TIMERTICK  (XTAL  512  512)
Dadurch wird die Uart-Ausgabe aber 3x so schnell?!
Muss ich noch etwas anderes verändern?

Damit beim nächsten Durchlauf meiner Funktion die Variablenwerte noch 
vorhanden sind, kann ich doch jetzt nur noch globale Variablen 
verwenden, oder sehe ich das falsch?

Hier mal meine alt Warte-Funktion:
char gsmsignal[3];
char *GsmSignalAbrufen(void)
{
  if(gsmreg[0] == '1')  
  {  uint8_t i=0;
    char gsmzeichen;
    char gsmsatz[20];
    
    while (!(0 == ukbhit2()))            //Alle noch vorhandenen Zeilen im Speicher abrufen und verwerfen
      while (ugetchar2() != 10);

    uputs2("AT+CSQ\r\n");              //Eingabe AT-Befehl
    while (ugetchar2() != 10);            //Erste Zeile bis Linefeed (\r\n) einlesen und verwerfen
    do                        // Kompletten Datensatz empfangen
    {
      gsmzeichen = ugetchar2();          // Zeichen von USART einlesen
      gsmsatz[i] = gsmzeichen;          // Zeichenkette erweitern
      i++;
    } while (gsmzeichen != 10);            // Zeilenende v. Datensatz erkennen
      
    strncpy(gsmsignal, gsmsatz+6, 2);        //Benötigte Zahl in gsmtmp speichern
    gsmsignal[2] = '\0';              //Stringende manuell setzen
    
  }
  return gsmsignal;
}

Und hier meine neue "Abbruch"-Funktion:
uint8_t merkergsm1=0;
uint8_t igsm=0;
char gsmzeichen;
char gsmsatz[20];

char *GsmSignalAbrufen(void)
{
  gsmreg[0] = '1';
  switch (merkergsm1)
  {
    case 0 :   if(!(gsmreg[0] == '1'))
          {
            merkergsm1=0;
            break;
          }
            
    case 1 :   if(!(0 == ukbhit2()))
          {
            ugetchar2();
            merkergsm1=1;
            break;
          }
          uputs2("AT+CSQ\r\n");
    
    case 2 :  if(!(ugetchar2() == 10))
          {
            merkergsm1=2;
            break;  
          }    
          
    case 3 :  gsmzeichen = ugetchar2();          // Zeichen von USART einlesen
          gsmsatz[igsm] = gsmzeichen;          // Zeichenkette erweitern
          igsm++;
          if(!(gsmzeichen == 10))
          {
            merkergsm1=3;
            break;
          }
          igsm=0;                      //Zeichenkettenlaufvariable rücksetzen
          strncpy(gsmsignal, gsmsatz+6, 2);        //Benötigte Zahl in gsmtmp speichern
          gsmsignal[2] = '\0';              //Stringende manuell setzen
          merkergsm1=0;                  //Merker rücksetzen
          break;
          
  }
  if(gsmsignal[2] != '\0')
    gsmsignal[2] = '1';
  return gsmsignal;
}

Vielen Dank für deine Hilfe!

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

Bewertung
0 lesenswert
nicht lesenswert
Deine SChreibweise der switch-case mit den generellen Durchfallern zum 
nächsten case und deine verquerten Abfragen machen mich wahnsinnig!

Dein ugetchar2, ist das ein wartendes getchar?

Ausserdem, denke ich, ist die Logik nicht dieselbe.

Schreib doch die Statemaschine mal ordentlich, so dass man nicht ständig 
um die Ecke denken muss. Du bist in einem Zustand, was muss passieren, 
damit in den nächsten Zustand gewechselt wird und nicht anders rum: 
Unter welchen Umständen wird der Zustand nicht gewechselt und man fällt 
durch in den nächsten Zustand.

Und schreib deine Abfrage vernünftig.
if(!(ugetchar2() == 10))
ist doch ein Schuss ins eigene Knie
if( ugetchar2() != 10)

Mach dir einen Plan welche Zustände es gibt und unter welchen Umständen 
und unter Abarbeitung welchen Codes von diesem zustand aus in einen 
anderen Zustand gewechselt wird.

Dein Zustand 0 wird zb sofort verlassenm, wenn du am Anfang der Funktion 
schon die Bedingung zum verlassen herstellst. Dieser Zustand ist von 
vorne herein schon mal sinnlos. Gerade Zustandsmaschinen haben einen 
enormen Vorteil: man kann sie gut und einfach planen. Einfaches 
Drauflosprogrammieren hingegen wird mit Fehlern bestraft.

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir mal einen Plan gemacht und die Statemachine danach 
programmiert.
Wenn ich es jetzt richtig verstanden habe, solle es jetzt besser sein.
Mein ugetchar ist ein wartendes, deshalb frage ich es jetzt immer erst 
mit ukbhit ab.
Das am Anfang der Funktion
gsmreg[0] = '1';
steht, hat nur die Bedeutung, dass ich die Funktion die gsmreg[0] 
zurückgibt, zur Zeit noch nicht vorher aufrufe. Daher setze ich den Wert 
zur Zeit manuell.
Aber nochmal zu meinen anderen Fragen:
Wie kann in etwa eine mehr oder weniger genaue Sekunde erreichen?
Muss ich
#define TIMERTICK  (XTAL  256  256)
umändern?

Kann man bei statemachines nur noch globale Variablen benutzen? Muss ich 
dann jede Laufvariable global anlegen?

Hier mein verbesserter Code:
uint8_t merkergsm1=0;
uint8_t igsm=0;
char gsmzeichen;
char gsmsatz[20];

char *GsmSignalAbrufen(void)
{
  gsmreg[0] = '1';
  switch (merkergsm1)
  {
    case 0 :   if(gsmreg[0] == '1')              //GSM-Modul eingebucht?
            merkergsm1=1;
          break;
            
    case 1 :   if(0 != ukbhit2())                //Zeichen vorhanden?
          {
            ugetchar2();                //Zeichen abrufen und verwerfen
            break;
          }
          merkergsm1=2;
          break;
          
    case 2 :  uputs2("AT+CSQ\r\n");              //AT-Befehl senden!
          merkergsm1=3;                
          break;
      
    case 3 :  if(0 != ukbhit2())                //Zeichen vorhanden?
            if(ugetchar2() == 10)            //Ersten Datensatz abrufen und verwerfen
              merkergsm1=4;              //Später noch Timeout, wenn keine Zeichen zurückkommen!
          break;
          
    case 4 :  if(0 != ukbhit2())
          {
            gsmzeichen = ugetchar2();          // Zeichen von USART einlesen
            gsmsatz[igsm] = gsmzeichen;          // Zeichenkette erweitern
            igsm++;
            if(gsmzeichen == 10)            //Kompletter Datensatz empfangen?
            {
              igsm=0;                  //Laufvariable für nächsten Durchlauf rücksetzen
              merkergsm1=5;
              break;
            }
          }  
          break;  
          
    case 5 :  strncpy(gsmsignal, gsmsatz+6, 2);        //Benötigte Zahl in gsmtmp speichern
          gsmsignal[2] = '\0';              //Stringende manuell setzen
          merkergsm1=0;                  //Merker rücksetzen
          break;
          
  }
  if(gsmsignal[2] != '\0')
    gsmsignal[2] = '1';
  
  return gsmsignal;
}

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist es so schlecht programmiert?

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

Bewertung
0 lesenswert
nicht lesenswert
Ich seh immer noch nicht, wie diese Statemachine dem hier
char gsmsignal[3];
char *GsmSignalAbrufen(void)
{
  if(gsmreg[0] == '1')  
  {  uint8_t i=0;
    char gsmzeichen;
    char gsmsatz[20];
    
    while (!(0 == ukbhit2()))            //Alle noch vorhandenen Zeilen im Speicher abrufen und verwerfen
      while (ugetchar2() != 10);

    uputs2("AT+CSQ\r\n");              //Eingabe AT-Befehl
    while (ugetchar2() != 10);            //Erste Zeile bis Linefeed (\r\n) einlesen und verwerfen
    do                        // Kompletten Datensatz empfangen
    {
      gsmzeichen = ugetchar2();          // Zeichen von USART einlesen
      gsmsatz[i] = gsmzeichen;          // Zeichenkette erweitern
      i++;
    } while (gsmzeichen != 10);            // Zeilenende v. Datensatz erkennen
      
    strncpy(gsmsignal, gsmsatz+6, 2);        //Benötigte Zahl in gsmtmp speichern
    gsmsignal[2] = '\0';              //Stringende manuell setzen
    
  }
  return gsmsignal;
}

entsprechen soll.

Auch wenn der Teil etwas seltsam ist (und ich denke das es nicht das ist 
was du eigentlich wolltest), aber das hier

    while (!(0 == ukbhit2()))            //Alle noch vorhandenen Zeilen 
im Speicher abrufen und verwerfen
      while (ugetchar2() != 10);


finde ich zb in der Statemaschine nicht wieder. Der case 0 ist immer 
noch ein sinnloser Zustand. Der untere Teil der Statemaschine sieht ok 
aus.

Bis auf das

 if(gsmsignal[2] != '\0')
    gsmsignal[2] = '1';

darauf kann ich mir überhaupt keinen Reim machen, was du da vor hattest.

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while (!(0 == ukbhit2()))            //Alle noch vorhandenen Zeilen
im Speicher abrufen und verwerfen
      while (ugetchar2() != 10);

Das habe ich so abgeändert, weil ich alle noch vorhandenen Zeichen 
abrufen und verwerfen will (Wenn welche vorhanden sind)und nicht nur bis 
zum Zeilenende.

Ich weiß nicht, warum du den case 0 sinnlos findest. Soll ich die 
Abfrage vor dem Eintreten in die Funktion machen? Ich muss doch 
überprüfen ob das GSM-Modul eingebucht ist.

Mit
if(gsmsignal[2] != '\0')
    gsmsignal[2] = '1';
will ich der nachfolgenden Funktion, die gsmsignal[0] und gsmsignal[1] 
ausgibt, eine Möglichkeit geben zu überprüfen, ob ein "vernünftiger" 
Wert in der Variable steht. Aber das ist in der Tat ausbaufähig.
Das soll aber eh entfallen, das die nachfolgende Funktion gsmreg[0] 
abfragt.
Und wenn der Wert nicht == 1 ist, wird sie gar nicht ausgeführt.

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

Bewertung
0 lesenswert
nicht lesenswert
Bene Jan schrieb:

>
> Ich weiß nicht, warum du den case 0 sinnlos findest.

Weil du am Anfang der Funktion mittels

  gsmreg[0] = '1';

dafür sorgst, dass hier

    case 0 :   if(!(gsmreg[0] == '1'))

die Bedingung niemals falsch sein kann! gsmreg[0] ist immer gleich '1'. 
Jedes einzelne mal, wenn die Funktion aufgerufen wird.

> while (!(0 == ukbhit2()))            //Alle noch vorhandenen Zeilen
> im Speicher abrufen und verwerfen
>       while (ugetchar2() != 10);
>
> Das habe ich so abgeändert, weil ich alle noch vorhandenen Zeichen
> abrufen und verwerfen will (Wenn welche vorhanden sind)und nicht
> nur bis zum Zeilenende.

Und was, wenn noch gar nicht alle Zeichen einer Zeile über die UART 
eingetroffen sind?
Dann kriegst du spätestens beim Abwarten der 2.ten Antwort nachdem du 
deinen Text rausgeblasen hast, ein Problem weil dann plötzlich ein \n 
zuviel eintrudelt.
Aber das musst du wissen, du hast die Hardware bei dir und du kannst das 
testen.

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja das steht ja nur im Moment so, zum testen der Statemachine:
Bene Jan schrieb:
> Das am Anfang der Funktion
> gsmreg[0] = '1';
> steht, hat nur die Bedeutung, dass ich die Funktion die gsmreg[0]
> zurückgibt, zur Zeit noch nicht vorher aufrufe. Daher setze ich den Wert
> zur Zeit manuell.

Karl heinz Buchegger schrieb:
> Und was, wenn noch gar nicht alle Zeichen einer Zeile über die UART
> eingetroffen sind?
> Dann kriegst du spätestens beim Abwarten der 2.ten Antwort nachdem du
> deinen Text rausgeblasen hast, ein Problem weil dann plötzlich ein \n
> zuviel eintrudelt.

Stimmt! Das änder ich wieder um!

Es ist aber doch richtig, dass ich nur noch globale Variablen in einer 
Statemachine verwenden kann oder?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke mal, UART-Empfang als Statemaschine ist keine gute Idee.

Üblicher Weise sammelt man die Datenbytes im Empfangsinterrupt in einen 
Puffer. Der Interrupt prüft dann auch, ob ein Endezeichen (z.B. '\n') 
empfangen wurde und setzt ein Flag.
Und erst dann schnappt sich das Main den Puffer und wertet ihn aus. Das 
kann in einem Ruck geschehen, da man auf nichts mehr warten muß.


Peter

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe doch in meiner Frage oben beschrieben, was ich machen will etc. 
Daraufhin hast du (peda) mir deinen Scheduler empfohlen. Und dann hast 
du mir auch eine statemachine empfohlen.
Jetzt auf einmal sagst du, dass eine statemachine nicht sinnvoll bei 
Uart-Empfang ist?!? Jetzt weiß ich gar nicht mehr, was ich machen soll?!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Statemaschine ist generell eine gute Sache, um komplexe Abläufe 
übersichtlich zu halten.

Nur für die UART ist sie das falsche Werkzeug, weil man nicht weiß, wann 
und ob überhaupt Zeichen reinkommen.
Wenn Du mit jemandem sprichst, wartest Du ja auch erst ab, bis er seinen 
Satz beendet hat und ziehst nicht vorher falsche Schlüsse.

Es gibt nicht das eine Universalwerkzeug, was für alles paßt. Man muß 
immer das am besten geignetste auswählen.

Der C-Compiler meckert Dich z.B. an, wenn die Leerzeile am Ende fehlt.
Das ist nämlich für ihn das Zeichen, mit der Compilierung beginnen zu 
können.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bene Jan schrieb:
> Ich habe doch in meiner Frage oben beschrieben, was ich machen will etc.

Wir sind ja hier keine Supportmitarbeiter, die dafür bezahlt werden.
Du mußt also davon ausgehen, daß die Tips allgemein meistens richtig 
sind, aber vielleicht Dein Problem nicht zu 100% treffen.

Oftmals ist es auch schwierig für einen Außenstehenden, Dein Problem 
richtig zu erkennen. Man kann ja nicht in Deinen Kopf oder auf Deine 
Festplatte sehen, sondern kennt nur den kleinen Teil, den Du geschrieben 
hast.


Peter

Autor: Bene Jan (terfagter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, habe es mit der Statemachine jetzt erstmal versucht, bzw. versuche 
es gerade und bisher klappt alles super! Ich benutze ja einen Fifo mit 
Interruptsteuerung zum Uart-Empfang, dann sollte es ja eigentlich mit 
der statemachine gehen?!?
Danke für deine Hilfe.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eine Statemaschine ist generell eine gute Sache, um komplexe Abläufe
>übersichtlich zu halten.

>Nur für die UART ist sie das falsche Werkzeug, weil man nicht weiß, wann
>und ob überhaupt Zeichen reinkommen.
>Wenn Du mit jemandem sprichst, wartest Du ja auch erst ab, bis er seinen
>Satz beendet hat und ziehst nicht vorher falsche Schlüsse.


Wobei das streng genommen ja auch nur eine Statemaschine ist ;-)

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.