Forum: Mikrocontroller und Digitale Elektronik Problem mit Einlesen von seriellen Daten am RX vom Arduino


von Georg M. (georg_m)


Lesenswert?

Guten Morgen :)

ich hab ein kleines Problem mit dem einlesen der Daten am seriellen 
Eingang meines Arduino Mega 2560.
Ich Überwache den seriellen Eingang RX2 ob Daten verfügbar sind. Dabei 
handelt es sich um seriell weitergeleitete Telegramme  eines TCM320 
Transceivers.
Das Einlesen klappt auch alles wunderbar, solange ich beim überprüfen 
von "Serial2" ein delay von 2 ms in die While-Schleife einbaue. Nehme 
ich dies delay raus, kommt es bei einer bestimmten Verzögerung zwischen 
zwei empfangenen Telegrammen zum Verlust des zweiten Telegramms.

Ein Telegramm besteht aus 38 Byte. Den Ringspeicher der seriellen 
Schnittstelle habe ich bereits auf 256 Byte erhöht. Damit bei zu schnell 
eingehenden Telegrammen das erste nicht wieder überschrieben wird, wenn 
das Bard mit dem auslesen nicht nachkommt.

Aber warum brauche ich das delay von 2 ms??? Bin vollkommen ratlos.

Hier mein Code.

1
#include "klasse.h"
2
3
uint8_t data[200]={0};
4
int dataLen=0;
5
int ausgabe=false;
6
7
Prototype klasse;
8
9
void setup()
10
  {
11
    Serial.begin(115200);
12
    Serial2.begin(57600);
13
  } 
14
15
void loop()
16
  {
17
18
  }
19
  
20
  
21
  void serialEvent2()
22
  {
23
    int sizeofdata=0;
24
    while(Serial2.available())
25
    {
26
      //Zwischenpeichern der Daten in einem Array aus dem Ringspeicher
27
      data[dataLen] =Serial2.read();
28
      Serial.print(data[dataLen],HEX);
29
      Serial.print(",");
30
      delay(2);
31
      dataLen++;
32
      //delay(2);
33
      if(dataLen >= 4)
34
      {
35
        //überwacht die Telegrammgröße
36
        sizeofdata=data[1]+data[2]+data[3]+7;       
37
      }
38
      if((dataLen == sizeofdata)&& (sizeofdata != 0))
39
      { 
40
        //speichern der Daten erfolgt nur, wenn Telegramm komplett 
41
        klasse.speichern(data);
42
        dataLen=0;
43
        break;
44
      }
45
    }
46
  }

von Karl H. (kbuchegg)


Lesenswert?

Georg M. schrieb:

> Aber warum brauche ich das delay von 2 ms???

Weil du hier in dieser Schleife ...
1
    while(Serial2.available())
2
    {
3
      //Zwischenpeichern der Daten in einem Array aus dem Ringspeicher
4
      data[dataLen] =Serial2.read();
5
6
...
7
    }

davon ausgehst, dass du ein komplettes Telegram damit abarbeiten kannst. 
Dem ist aber nicht so. Dein µC rechnet viel schneller, als die USART 
übertragen kann. D.h. die available Schleife ist zu Ende und das 
Telegram ist noch gar nicht vollständig reingekommen.

Beim nächsten Zeichen des Telegramms, welches du mitten drinn 
abgebrochen hast, wird zwar die Event Funktion wieder aufgerufen. Aber 
zu diesem Zeitpunkt hast du die Variable sizeofdata schon verloren (weil 
es eine lokale Variable ist) und keine Ahnung mehr, wieviele Zeichen 
eigentlich noch fehlen, bis dieses eine Telegramm fertig ist.


Baust du dagegen den delay ein, dann zwingst du den µC dazu Zeit zu 
vertrödeln. Zeit, in der die Gegenstelle wieder ein Zeichen per UART 
übertragen kann, welches dann dazu führt, dass available() wieder ein 
Zeichen für den read() hat, wodurch die while-Schleife weiterläuft bis 
dann irgendwann sizeofdata Zeichen bearbeitet wurden.

> Damit bei zu schnell eingehenden Telegrammen

:-) Das genaue Gegenteil ist der Fall. Der µC ist viel schneller, als 
die Gegenstelle senden kann.

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.