www.mikrocontroller.net

Forum: PC-Programmierung [Java] Serielle Daten kommen in 2 Packungen


Autor: Frank Weigler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Mir ist für folgendes Problem leider kein besserer Titel eingefallen.

Ich kommuniziere über die serielle Schnittstelle mit einem 
angeschlossenen Gerät. Die eingehenenden Daten werden wie in dem 
Beispiel hier auf der Seite [1] eingelesen.

Nach Absenden eines Befehls an das Gerät wird dieser immer mit einer 
Antwort quitiert. Funktioniert auch alles eigentlich wie es soll. Nur 
bekomme ich meine Antowrt mal in zwei Paketen, mal in einem Paket. Mit 
Paket meine ich dass der Eventhandler für DATA_AVAILABLE wohl zweimal 
aufgerufen wird.

Manchmal werden dann die 10 Bytes die als Antwort kommen im ersten 
Aufruf gelesen, aber macnhmal 2 Byte im ersten und die restlichen 8 im 
zweiten. Oder 8 im ersten und die restlichen 2 im zweiten.

Hat jemand spontan eine Idee woran das liegen könnte?

[1] 
http://www.mikrocontroller.net/articles/Serielle_S...

Gruß

Frank

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei read kann man doch angeben, wie viele Byte er lesen soll. 
Möglicherweise muss man noch irgendwo Timeouts anpassen.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hat jemand spontan eine Idee woran das liegen könnte?

Vermutlich, weil das eben einfach so ist. Das System weiß ja nicht, daß 
deine Antwort genau 10 Bytes groß ist. Du bekommst halt Daten, wenn es 
meint, seinen Puffer leeren zu müssen.

Autor: Frank Weigler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bei read kann man doch angeben, wie viele Byte er lesen soll.

Also meine Lesebuffer ist 255 Byte gross. Habe jetzt testweise einfach 
mal diese Grösse verwendet, da keine Antwort gröser sein wird als 255. 
Diese Anzahl von Bytes versuche ich dann zu lesen.

byte[] receiveBuffer = new byte[255];

while (inputStream.available() > 0) {
  numBytes = inputStream.read(receiveBuffer, 0, receiveBuffer.length);
}
      }
> Möglicherweise muss man noch irgendwo Timeouts anpassen.

Kurioserweise scheint eine "Warteschleife" vor dem Lesen das Problem zu 
beheben. Finde ich jetzt aber irgendwie ziemlich unschön und verschafft 
nicht gerade ein gutes Gefühl. An welcher Stelle können denn "irgendwo 
Timeouts angepasst" werden.

for (int i = 0; i < 100000; i++){
  for (int j = 0; j < 1000; j++){}
}

> Vermutlich, weil das eben einfach so ist.

Ich weiss jetzt in dem speziellen Fall eben dass die Antwort 10 Byte 
gross sein muss. WIe oben zu lesen ist, ist der Buffer schon grösser.

Autor: Markus V. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltes Dir mal Gedanken über ein (einfaches) Übertragungs-Protokoll 
machen. Einfach nur irgendwelche Bytes über die Leitung übertragen 
funktioniert schon. Aber wie Rolf schreibt, für das System sind das 
einfach nur Bytes, die es in beliebigen Portionen dem Aufrufer zur 
Verfügung stellt.

Es würde Dir schon helfen, wenn zu zunächst ein definierte Start-Zeichen 
und am Ende ein Stop-Zeichen sendest. Die empfangenen Daten pufferst Du 
über Deinen SerialPort-Event-Handler zwischen und erzeugtst ein eigenes 
Event, wenn eine Nachricht vollständig empfangen wurde. Alles ziemlich 
simpel...

Gruß
Markus

Autor: Markus V. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du Dir übrigens mal die Doku zu InputStream.Read aus Java-Doc zu 
Gemüte führst, wirst Du auf eine Antwort zu Deiner Eingangsfrage stoßen.

Die "Lösung" mit einer Warteschleife (mir rollt es die Fußnägel auf!!!) 
ist keine. Das klappt mehr oder weniger zufällig. Die einzige saubere 
Lösung ist das Zwischenpuffern im Receive-Event-Handler, weil die 
serielle Übertragung so langsam ist, daß die ComPort-Software nicht 
weiß, ob Dein Paket schon übertragen ist und halt mal das zur Verfügung 
stellt, was sie bereits empfangen hat.

Gruß
Markus

Autor: Frank Weigler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal Danke für deine ausführlichen Antworten. Die "Lösung" mit der 
Schleife soll ja keine Lösung darstellen, sondern war nur ein Test um 
rauszubekommen was da vor sich geht.

Ich werde mir das Ganze mal nochmal durch den Kopf gehen lassen. Aber 
ich ging auch irgendwie davon aus dass InputStream.Read mir die Antwort 
durchgehend in "einem Fluss" liefert. Wenn das natürlich nicht der Fall 
ist, dann macht ja im Prinzip wirklich nur ein einfaches Protokoll Sinn, 
in dem dann definierte Anfangs- und Endzustände herrschen, bzw. ich 
diese dann auch überprüfen kann.

Ich denke ihr habt mir aufjedenfall einen Weg in die richtige Richtung 
gezeigt. Werde mir mal wieder ein paar Gedanken zu dem Thema machen.

Vorerst Danke euch beiden.

Autor: Brutal Force (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Musst Du auf Geschwindigkeit optimieren?
Falls ja: Du kommst um das Puffern wohl nicht herum.

Falls nein:

Mach Dir die Sache doch einfach!
Rechne aus, wie lange die 10 Bytes brauchen, um übertragen zu werden.
Verdopple die Zeit.
Und warte solange, bevor Du read aufrufst...

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.