Forum: Mikrocontroller und Digitale Elektronik Mehrere Werte über RS485 versenden


von Daniel O. (daniel_o)


Lesenswert?

Hallo zusammen.
Ich habe zwar schon gegoogelt, aber keine passende Lösung gefunden, 
deshalb hoffe ich hier auf Erleuchtung.

Ich möchte mit einem Arduino 3 Messwerte einlesen. Die sollen dann über 
RS485 versendet werden und an einem zweiten Arduino über ein Display 
ausgegeben werden. Die Kommunikation über RS485 läuft so einigermaßen. 
Ich habe serial.write und serial.read verwendet. Die Werte treffen nicht 
gleichmäßig ein, als würden Pakete verpasst. Ist das normal?

Die Hauptfrage ist, wie ich die Werte versenden kann und am Enpfanger 
wieder auseinander nehme. Ich denke, ein Array würde da passen. Wie 
lässt sich ein Array seriell versenden?

von Jobst Q. (joquis)


Lesenswert?

Über RS485 werden einzelne Zeichen gesendet und empfangen. Mehrere 
Zeichen sind ein String. Die Werte gibst du entweder dezimal oder 
hexadezimal aus.

Hexadezimal ist platzsparend und hat den Vorteil einer konstanten Länge 
der Werte. Zwischen den Werten empfehlen sich Leerzeichen oder andere 
Trennzeichen.

Dass nur bestimmte Zeichen (0-9,A-F) zulässig sind, ist schon ein 
bisschen Schutz gegen Übertragungsfehler. Besser ist aber noch eine 
Checksumme anzuhängen und zu überprüfen.

: Bearbeitet durch User
von Daniel O. (daniel_o)


Lesenswert?

Jobst Q. schrieb:
> Mehrere Zeichen sind ein String. Die Werte gibst du entweder dezimal
> oder hexadezimal aus.

Also nacheinander:
Ich müsste aus dem Array erstmal einen String machen und zwischen die 
Werte ein Trennungszeigen setzen, hab ich das so richtig verstanden?

von Jobst Q. (joquis)


Lesenswert?

Daniel O. schrieb:
> Ich müsste aus dem Array erstmal einen String machen und zwischen die
> Werte ein Trennungszeigen setzen, hab ich das so richtig verstanden?

Ja, ist so zu empfehlen.

von Daniel O. (daniel_o)


Lesenswert?

Alles klar, das probiere ich ersteinmal. Habe mich mit sowas noch nie 
beschäftigt. ^^

von Falk B. (falk)


Lesenswert?

Daniel O. schrieb:
> Also nacheinander:
> Ich müsste aus dem Array erstmal einen String machen und zwischen die
> Werte ein Trennungszeigen setzen, hab ich das so richtig verstanden?

Das KANN man so machen, ist aber bei drei Meßwerten nicht wirklich nötig 
oder sinnvoll. Es reicht hier wahrscheinlich, die drei Meßwerte direkt 
binär zu senden, ggf. mit einer einfachen Prüfsumme an Schluß. Der Trick 
liegt im Empfänger, der die Zeichen empfangen und richtig zuordnen muss. 
Dabei muss vor allem berücksichtigt werden, daß irgendwie die 
Übertragung gestört sein kann. D.h. der Empfänger muss immer wieder den 
Anfang des Datenpakets erkennen. Bei der einfache Situation hier reicht 
ein timeout. D.h. wenn ein Zeichen empfangen wird, wird ein Timeout von 
??ms gestartet. Treffen innerhalb dieser Zeit nicht alle Zeichen ein, 
liegt ein Übertragungsfehler vor und die Empfangsroutine wartet erneut 
auf den Anfang des Datenpakets.

von Klaus H. (nikolaus10)


Lesenswert?

Hallo

RS485 ist in der Regel nicht biderecktional.
Du must hardwertechnisch zwischen senden und empfangen umschalten.

Gruesse

von Gerald K. (geku)


Lesenswert?

Ich würde ein Startzeichen (1 Byte), einen Telegrammzählerwert (1 Byte), 
die 3 Datenbytes und eine Prüfsumme (1 Byte) übertragen.

Es werden pro Telegramm 6 Bytes übertragen. Es können so 
Übertragungsfehler und fehlende Telegramme erkannt werden.

von Harry L. (mysth)


Lesenswert?

Der Suchbegriff lautet: "Daten serialisieren".

von mm (Gast)


Lesenswert?

Gerald K. schrieb:
> Ich würde ein Startzeichen (1 Byte), einen Telegrammzählerwert (1 Byte),
> die 3 Datenbytes und eine Prüfsumme (1 Byte) übertragen.

Wie kommst Du darauf, dass ein Messwert ein Byte ist.

@Daniel O.:
Welchen Datentyp haben denn Deine Werte?
Wie sieht dein aktueller Code für's Senden aus?

von Christian K. (christian_rx7) Benutzerseite


Lesenswert?

Wenn du es gerne standardisiert haben willst, dann schau dir Modbus RTU 
an, macht genau das was du erreichen willst und ist sehr einfach 
gehalten.

von Daniel O. (daniel_o)


Lesenswert?

mm schrieb:
> Wie sieht dein aktueller Code für's Senden aus?

Da ich von Anfang an begonnen habe, um keine Fehler fort zu führen, so:
1
#include <OneWire.h>
2
#include <DallasTemperature.h>
3
4
#define ONE_WIRE_BUS 12
5
#define TEMPERATURE_PRECISION 9
6
7
OneWire oneWire(ONE_WIRE_BUS); 
8
DallasTemperature sensors(&oneWire); 
9
10
DeviceAddress Thermometer1 = { 0x28, 0xFF, 0x64, 0x1E, 0x83, 0x44, 0xA8, 0x20 };
11
DeviceAddress Thermometer2 = { 0x28, 0xFF, 0x64, 0x1E, 0x83, 0x4F, 0x2D, 0xB0 };
12
13
float tempC; //Wert zum speichern der DS18B20-Fühler
14
15
16
void setup(void)
17
{
18
  Serial.begin(9600);
19
  sensors.begin();
20
  sensors.setResolution(Thermometer1, TEMPERATURE_PRECISION);
21
  sensors.setResolution(Thermometer2, TEMPERATURE_PRECISION);
22
}
23
24
25
26
void loop(void)
27
{
28
  sensors.requestTemperatures();
29
  Serial.print("Temp 1: ");
30
  Serial.print(sensors.getTempC(Thermometer1));
31
  Serial.print(", ");
32
  Serial.print("Temp 2: ");
33
  Serial.print(sensors.getTempC(Thermometer2));
34
  Serial.println();
35
}


Christian K. schrieb:
>schau dir Modbus RTU
an

Das werd ich gleich mal machen.

von Falk B. (falk)


Lesenswert?

Klaus H. schrieb:
> Hallo
>
> RS485 ist in der Regel nicht biderecktional.

Genau anders herum.
RS485 wird MEISTENS bidirektional genutzt.
RS422 ist nur unidirektional.
Was du meinst ist Halbduplex. Da gibt es nur ein Signalpaar, auf dem die 
Daten in beide Richtungen gehen. Im Gegensatz zu Vollduplex, da gibt es 
für jede Richtung ein Signalpaar, ähnlich RS232, nur daß das nicht 
differnetiell arbeitet.

> Du must hardwertechnisch zwischen senden und empfangen umschalten.

Nö, denn der OP will ja nur unidirektional Daten senden.

Vielleicht klappt's ja mit sinnvollen Beträgen beim nächsten Mal.

von Falk B. (falk)


Lesenswert?

Daniel O. schrieb:
>>schau dir Modbus RTU
> an
>
> Das werd ich gleich mal machen.

Naja, wenn gleich man da einiges lernen kann, ist das für den Anfang 
eher etwas zuviel.

von A. S. (Gast)


Lesenswert?

mm schrieb:
> Wie kommst Du darauf, dass ein Messwert ein Byte ist.

Gerald K. schrieb:
> die 3 Datenbytes

von A. S. (Gast)


Lesenswert?

Das Verpacken in binäre strukturen plus Start/Stopp/Checksumme ist 
üblich. Vor allem weil es die Programmierfähigkeiten herausfordert und 
man da zeigen kann, was man kann.

Es ist aber wesentlich einfacher, gerade für einen Beginner, Einfache 
"Strings zu senden. D.H.

 * mit sprintf oder ähnlichem einen String zu erzeugen, z.B. "M1=23456"
 * Den inclusive der terminierenden 0 zu übertragen und/oder "\n".
 * Auf der Empfangsseite das ganze mit scanf oder ähnlichem wieder in 
eine Zahl zu zerlegen.


Der Vorteil:
 * Egal welche Endian ein System hat oder welche sizeof(int)
 * Mitlesen der Daten funktioniert im Klartext, man muss nicht extra ein 
Tool dafür basteln.
 * Für die Sicherheit reicht es oft, Parity einzuschalten, 
Framing-Errors auszuwerten und daraufhin ganze Strings zu verwerfen.

Für Anfänger die was erreichen wollen, die beste Wahl. Für Anfänger die 
auf die lernen wollen, gerne fancy Protokolle

von mm (Gast)


Lesenswert?

A. S. schrieb:
> mm schrieb:
>> Wie kommst Du darauf, dass ein Messwert ein Byte ist.
>
> Gerald K. schrieb:
>> die 3 Datenbytes

Äääh eine Behauptung mit der selben Behauptung zu "belegen" spricht 
jetzt nicht unbedingt von Kompetenz...

Wie der Code zeigt, ist es nicht nur ein Byte. Aber er zeigt halt auch, 
dass da Arduinotypisch irgendwas zusammengehackt wurde, ohne genau zu 
wissen, was man da macht.

von Olaf (Gast)


Lesenswert?

1
struct HeaderType
2
{
3
  uint8_t  Data1;
4
  uint8_t  Data2
5
  uint8_t  Data3;
6
  uint8_t  crc8;          //Pruefsumme
7
} __attribute__ ((packed));
8
9
union HeaderUnion
10
{
11
  struct HeaderType Header;
12
  uint8_t           Byte[4]; 
13
};

>  Vor allem weil es die Programmierfähigkeiten herausfordert und
> man da zeigen kann, was man kann.

Wenn solche Banalitaeten schon ausreichen um zu zeigen "was man kann",
dann fange ich an mir Sorgen um die Programmierer zu machen. .-)

Olaf

von Angsthase (Gast)


Lesenswert?

Daniel O. schrieb:
> void loop(void)
> {
>   sensors.requestTemperatures();
>   Serial.print("Temp 1: ");
>   Serial.print(sensors.getTempC(Thermometer1));
>   Serial.print(", ");
>   Serial.print("Temp 2: ");
>   Serial.print(sensors.getTempC(Thermometer2));
>   Serial.println();
> }

denke dein Programm überholt sich, du brauchst für die Ausgabe ca. 
30msec oder dein Buffer läuft voll. Man kann leider nicht erkennen ob 
bei serial.print gewartet wird bis alle Zeichen gesendet sind

von Falk B. (falk)


Lesenswert?

Angsthase schrieb:
> denke dein Programm überholt sich, du brauchst für die Ausgabe ca.
> 30msec oder dein Buffer läuft voll. Man kann leider nicht erkennen ob
> bei serial.print gewartet wird bis alle Zeichen gesendet sind

Kann man, denn der interne FIFO ist nicht unendlich groß. Wenn zu wenig 
Platz ist, muss serial.print() warten. Aber egal, man ballert keine 
Meßwerte ohne Pause so schnell raus, das ist sinnlos und 
kontraproduktiov. Man sollte eine sinnvolle Übertragungsfrequenz 
festlegen, erst recht bei  sehr langsamen Temperatursensoren.

von mm (Gast)


Lesenswert?

Falk B. schrieb:
> Man sollte eine sinnvolle Übertragungsfrequenz
> festlegen, erst recht bei sehr langsamen Temperatursensoren.

Dies in der Kombination mit Olafs Vorschlag dürfte zum Ziel führen. In 
Arduinosprache könnte es so aussehen.
1
struct
2
{
3
  float  temp1;
4
  float  temp2;
5
  float  dritterWert;
6
  uint8_t  crc;          //Pruefsumme
7
} txData __attribute__ ((packed));
8
9
...
10
11
void loop(void)
12
{
13
  sensors.requestTemperatures();
14
  txData.temp1 = sensors.getTempC(Thermometer1);
15
  txData.temp2 = sensors.getTempC(Thermometer2);
16
  txData.dritterWert = wasAuchImmer();
17
  crc8.restart();
18
  crc8.add(txData, sizeof(txData) - sizeof(txData.crc));
19
  txData.crc = crc8.getCRC();
20
  serial.write((char *) &txData, sizeof(txData));
21
  delay(1000);
22
}

Durch die Pause (die durchaus auch noch länger sein dürfte) muss man 
sich empfängerseitig auch nicht so viel Gedanken machen. Falls man 
zufällig mittendrin anfängt zu hören (mit Timeout), bekommt man nicht 
genug Daten, also werden sie einfach verworfen und nochmal gehört, bis 
man dann mal genug auf einmal bekommt. Ist zwar nicht schön, aber für 
eine Arduino-Bastelei sollte es reichen.


OT: Kaum wirft man einen Blick in die Arduino-Referenz fallen einem 
schon drei Dinge auf, die "suboptimal" (bzw. fehlerträchtig) sind. Ich 
mag das Zeug wohl zurecht nicht.

von Daniel O. (daniel_o)


Lesenswert?

Also dem Teilmit der Checksumme widme ich mich später. Ich habe schon 
drüber nachgedacht, ob es einfacher wäre, das I2C-Display mit Extendern 
zu betreiben, aber das ist ja nicht die Lösung.

Aktuell gibt das Programm die Werte seriell in einer Zeile aus. Diese 
Werte müsste ich jetzt in einen String bekommen?

von Falk B. (falk)


Lesenswert?

Daniel O. schrieb:
> Also dem Teilmit der Checksumme widme ich mich später. Ich habe schon
> drüber nachgedacht, ob es einfacher wäre, das I2C-Display mit Extendern
> zu betreiben,

Sicher, denn so eine Anzeige macht ein Mikrocontroller mit links 
nebenbei. Dafür 2 Controller zu verwenden ist meistens nicht nötig. 
Einzig dann, wenn der Abstand mehrere Meter beträgt, dann ist I2C eher 
nicht gut geeignet (wenn gleich möglich).

> aber das ist ja nicht die Lösung.

Warum nicht?

> Aktuell gibt das Programm die Werte seriell in einer Zeile aus. Diese
> Werte müsste ich jetzt in einen String bekommen?

Das ist schon einer ;-)

von mm (Gast)


Lesenswert?

Daniel O. schrieb:
> Aktuell gibt das Programm die Werte seriell in einer Zeile aus. Diese
> Werte müsste ich jetzt in einen String bekommen?

Deine Zeile ist doch schon ein lesbarer Text-String. Aber 
"Human-Readable" macht halt die Empfangsseite nicht unbedingt einfacher.

Wenn ich von Maschine zu Maschine (µC zu µC) kommuniziere, besteht keine 
Notwendikeit, es für den Menschen lesbar zu machen. Die Daten roh 
(binär) zu schicken verringert den Aufwand enorm.
Wenn die Daten in einem packed struct gespeichert sind, liegen sie 
netterweise schon genau so im Speicher, wie man sie senden kann. Auf der 
anderen Seite einfach in den Speicher geschrieben können sie wieder als 
das gleiche struct ausgewertet werden.


Daniel O. schrieb:
> ob es einfacher wäre, das I2C-Display mit Extendern
> zu betreiben

Einfacher natürlich... Um welche Strecke geht es denn?

von Daniel O. (daniel_o)


Lesenswert?

mm schrieb:
> Daniel O. schrieb:
>> Aktuell gibt das Programm die Werte seriell in einer Zeile aus. Diese
>> Werte müsste ich jetzt in einen String bekommen?
>
> Deine Zeile ist doch schon ein lesbarer Text-String. Aber
> "Human-Readable" macht halt die Empfangsseite nicht unbedingt einfacher.
>
> Wenn ich von Maschine zu Maschine (µC zu µC) kommuniziere, besteht keine
> Notwendikeit, es für den Menschen lesbar zu machen. Die Daten roh
> (binär) zu schicken verringert den Aufwand enorm.
> Wenn die Daten in einem packed struct gespeichert sind, liegen sie
> netterweise schon genau so im Speicher, wie man sie senden kann. Auf der
> anderen Seite einfach in den Speicher geschrieben können sie wieder als
> das gleiche struct ausgewertet werden.
>
>
> Daniel O. schrieb:
>> ob es einfacher wäre, das I2C-Display mit Extendern
>> zu betreiben
>
> Einfacher natürlich... Um welche Strecke geht es denn?


Es geht um ca. 30m.
Also müsste ich die Daten z.B. als "Wert1,Wert2,Wert3" versenden?

von Falk B. (falk)


Lesenswert?

Daniel O. schrieb:
> Es geht um ca. 30m.
> Also müsste ich die Daten z.B. als "Wert1,Wert2,Wert3" versenden?

BINGO!

von Wolfgang (Gast)


Lesenswert?

Jobst Q. schrieb:
> Hexadezimal ist platzsparend und hat den Vorteil einer konstanten Länge
> der Werte.

Bei hexadezimaler Übertragung müssen pro Byte zwei Byte, ggf. zzgl. 
Trennzeichen übertragen werden. Was ist daran platzsparend.

In welchem Wertebereich liegen die zu übertragenden Werte?

von mm (Gast)


Lesenswert?

Daniel O. schrieb:
> Es geht um ca. 30m.

Also nix mit I²C direkt.

> Also müsste ich die Daten z.B. als "Wert1,Wert2,Wert3" versenden?

Natürlich, wenn Du Dir das Leben unnötig schwer machen willst. Einmal 
ist Wert1 "23.4" ein anderes Mal "34.56" oder "45.678". Du musst also 
entweder jedesmal den Text aufwändig interpretieren oder eine feste 
Anzahl an Nachkommastellen verwenden oder Dich von "float" 
verabschieden.
Du kannst aber auch ganz einfach Deine Werte als Rohdaten übertragen wie 
oben demonstriert.

von Jester (Gast)


Lesenswert?

Da war doch die Sache mit der Synchronität ...

Bit-Synchronität kann der UART von Haus aus. Wenn man ihm sagt, mit 
wie viel BPS die Daten reintröpfeln, synchronisiert er anhand der 
Signalwechsel seinen internen Takt so, dass das empfangene Signal in 
Bitmitte abgetastet wird.

Auch die Wort-Synchronität stellt der UART sicher, indem er anhand von 
Start- und Stopp-Bits - richtige Konfiguration vorausgesetzt - den 
Anfang eines Zeichens (7- bzw. 8-Bit) findet.

Was du die vorgenommen ist die Übertragung von Telegrammen/Paketen, 
bestehend aus mehreren Zeichen. Wie will der Empfänger entscheiden, 
welches Zeichen das Erste im Telegramm ist - wenn du es ihm nicht sagst?

Üblicherweise definiert man Frames mit Start-Zeichen, ev. Stopp-Zeichen 
und/oder auch Prüfsummen, ev, auch eine fixe Frame-Länge - eben um es 
dem Empfänger einfach zu machen, auf die Frames zu synchronisieren -> 
Frame-Synchronität.

Ohne jetzt das Fass "ISO/OSI-Referenzmodell" aufzumachen (man rutscht 
hier schon deutlich in Layer 2 / data link layer) rein, braucht man sich 
das nicht aus den Fingern zu saugen. Es ist durchaus legitim, bei den 
"Anderen" abzukucken. Als Starpunkt bietet sich z.B. 
https://en.wikipedia.org/wiki/Data_link_layer#Protocol_examples an.

von Jobst Q. (joquis)


Lesenswert?

Wolfgang schrieb:
> Jobst Q. schrieb:
>> Hexadezimal ist platzsparend und hat den Vorteil einer konstanten Länge
>> der Werte.
>
> Bei hexadezimaler Übertragung müssen pro Byte zwei Byte, ggf. zzgl.
> Trennzeichen übertragen werden. Was ist daran platzsparend.

Es ist platzsparend gegenüber dem Dezimalformat, die konstante Länge ist 
aber bedeutsamer. Wenn man Dezimalzahlen durch führende Nullen eine 
konstante Länge gibt, tappt man leicht in die Oktalfalle.

Binär ist zwar platzsparender als Text, ist aber nur bei großen 
Datenmengen von Vorteil. Gerade beim Experimentieren von Anfängern 
erleichtert die menschenlesbare Textform deutlich die Fehlersuche.

von Daniel O. (daniel_o)


Lesenswert?

Ich habe jetzt etwas gefunden, was meinen Anforderungen genügt.
Ich sende seriell "<abc,11.11,22.22,33.33,44.44,55.55>" und auf der 
Empfängerseite kommt es richtig in den Variabeln an.
Das Original hat auch die Möglichkeit, Text als erste aAriabel zu 
senden. Ich bekomme den Teil des "Auf-Text-Warten" aber nicht aus dem 
Programm bei "parseData" raus, vielleicht hat jemand einen Tipp. Hier 
der Code:

1
// Empfänger
2
3
const byte numChars = 32;
4
char receivedChars[numChars];
5
char tempChars[numChars];        // temporary array for use when parsing
6
7
// variables to hold the parsed data
8
char messageFromPC[numChars] = {0};
9
float integerFromPC = 0.0;
10
float wert1 = 0.0;
11
float wert2 = 0.0;
12
float wert3 = 0.0;
13
float wert4 = 0.0;
14
float wert5 = 0.0;
15
16
boolean newData = false;
17
18
//============
19
20
void setup() {
21
  Serial.begin(9600);
22
  Serial.println("bereit");
23
  Serial.println();
24
}
25
26
//============
27
28
void loop() {
29
  recvWithStartEndMarkers();
30
  if (newData == true) {
31
    strcpy(tempChars, receivedChars);
32
    // this temporary copy is necessary to protect the original data
33
    //   because strtok() used in parseData() replaces the commas with \0
34
    parseData();
35
    showParsedData();
36
    newData = false;
37
  }
38
}
39
40
//============
41
42
void recvWithStartEndMarkers() {
43
  static boolean recvInProgress = false;
44
  static byte ndx = 0;
45
  char startMarker = '<';
46
  char endMarker = '>';
47
  char rc;
48
49
  while (Serial.available() > 0 && newData == false) {
50
    rc = Serial.read();
51
52
    if (recvInProgress == true) {
53
      if (rc != endMarker) {
54
        receivedChars[ndx] = rc;
55
        ndx++;
56
        if (ndx >= numChars) {
57
          ndx = numChars - 1;
58
        }
59
      }
60
      else {
61
        receivedChars[ndx] = '\0'; // terminate the string
62
        recvInProgress = false;
63
        ndx = 0;
64
        newData = true;
65
      }
66
    }
67
68
    else if (rc == startMarker) {
69
      recvInProgress = true;
70
    }
71
  }
72
}
73
74
//============
75
76
void parseData() {      // split the data into its parts
77
78
  char * strtokIndx; // this is used by strtok() as an index
79
80
  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
81
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
82
83
  strtokIndx = strtok(NULL, ","); 
84
  wert1 = atof(strtokIndx);
85
86
  strtokIndx = strtok(NULL, ","); 
87
  wert2 = atof(strtokIndx);    
88
   
89
  strtokIndx = strtok(NULL, ",");
90
  wert3 = atof(strtokIndx);     
91
92
  strtokIndx = strtok(NULL, ",");
93
  wert4 = atof(strtokIndx);     
94
95
  strtokIndx = strtok(NULL, ",");
96
  wert5 = atof(strtokIndx);     
97
98
}
99
100
//============
101
102
void showParsedData() {
103
  Serial.print("Text: ");
104
  Serial.println(messageFromPC);
105
  Serial.print("Wert 1: ");
106
  Serial.println(wert1);
107
  Serial.print("Wert 2: ");
108
  Serial.println(wert2);
109
  Serial.print("Wert 3: ");
110
  Serial.println(wert3);
111
  Serial.print("Wert 4: ");
112
  Serial.println(wert4);
113
  Serial.print("Wert 5: ");
114
  Serial.println(wert5);
115
}

von Forist (Gast)


Lesenswert?

Daniel O. schrieb:
> Hier der Code:
> ...

Was mag wohl der Hinweis
"Wichtige Regeln - erst lesen, dann posten!
...
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

bedeuten?
Schon Mal drüber nachgedacht?

von Daniel O. (daniel_o)


Angehängte Dateien:

Lesenswert?

Man möge es verzeihen, habe nicht dran gedacht. Hier also als Datei.

von Peter D. (peda)


Lesenswert?

Daniel O. schrieb:
> Ich bekomme den Teil des "Auf-Text-Warten" aber nicht aus dem
> Programm bei "parseData" raus, vielleicht hat jemand einen Tipp.

Du rufst in der Loop quasi im Vorbeigehen eine Funktion auf, die jedes 
Byte in einen Puffer schreibt, wenn ein Byte empfangen wurde. Dabei 
prüft sie, ob ein Zeilenende erkannt wird und erst dann übergibt sie den 
Puffer dem Parser. Auch prüft sie auf Pufferüberlauf/-unterlauf.
Zwischen diesen Aufrufen kann die Loop beliebig viele andere Sachen 
machen. Wie lange es dauert, eine Zeile zu empfangen, spielt dann keine 
Rolle mehr.
1
void receive_command(void)                              // receive from UART
2
{
3
  static char cbuf[CMD_MAX_LEN];                        // command buffer
4
  static uint8_t idx = 0;
5
  uint8_t ch;
6
7
  if (ukbhit0() == 0)
8
    return;
9
  ch = ugetchar0();
10
  switch (ch)
11
  {
12
    default:
13
      cbuf[idx] = ch;
14
      if (idx < sizeof(cbuf) - 1)
15
        idx++;
16
      return;
17
    case '\b':
18
      if (idx)
19
        idx--;                          // remove last char (interactive mode)
20
      return;
21
    case '\n':
22
    case '\r':
23
      if (idx == 0)                     // do nothing on empty commands
24
        return;
25
      cbuf[idx] = 0;
26
      idx = 0;
27
      execute(cbuf);
28
      uputs0(cbuf);                     // send answer
29
  }
30
}

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.