Hallo,
ich habe ein Programm geschrieben, dass Daten an einen Microcontroller sendet, die Antwort des Controllers empfängt und diese ausgibt.
Die empfangenen Daten sollen nicht nur einfach ausgegeben, sondern vorher nach bestimmten Kritierien geprüft und bei Bedarf verändert werden.
Die Daten vom Controller kommen in folgender Form:
Startflag (1Byte), Länge(1Byte), Befehl(1Byte), Daten(Länge-1 Byte), Checksumme(1 Byte), Endflag(1 Byte)
Die Länge gibt an, wie viele Byte Befehl+Daten dem Länge-Byte folgen werden.
Beispiel: 0x02 0x01 0x22 0xBA 0x03 Die Länge ist 1, d.h. das es keine Daten gibt, nur das Command.
Mit diesem Wissen muss ich die eingehenden Bytes prüfen. Ich muss das StartByte erkennen, mir Länge und Command holen und je nach Command entsprechend handeln.
Ich habe schon sehr viel versucht und auch per Such-Funktion eingiges gefunden aber keine passende Lösung.
Im Wesentlichen habe ich 2 Varianten ausprobiert und mit ihnen experimentiert.
-Variante 1: Erst alle Daten in einen ByteFeld-Buffer schreiben und den dann über eine For-Schleife durchgehen
ausgabe ist ein Textfield, ich verwende (im Moment) einen normalen InputStream.
Probleme: Die Antwort des Controllers ist nicht immer gleich lang und oft sind es mehrere Frames hintereinander.
Ausserdem sind es nicht immer nur Bytes, die der Controller sendet.
Wenn der Befehl 0x55 ist, sendet der Controller mehrere Frames mit Characters, die auch als solche ausgegeben werden sollen. Aber sie werden als Bytes ausgegeben
Bei allen anderen Befehlen sollen die Bytes direkt in hexadeziamler Form ausgegeben werden. Das funktioniert ja soweit.
Oft kommt es bei der Ausgabe zu Fehlern, vor allem dann wenn es sich um mehrere Frames handelt, oder wenn man viele Befehle nacheinander sendet.
Beispiel: Das soll eigentlich immer die gleiche Antwort sein, aber es werden Bytes vergessen, oder sind 0,...
Ich glaube das hat mit dem Buffer zu tun.
2 1 7 131 3
2 1 0 0 0
2 1 7 131 3
2 1 7 0 0
2 1 7 131 3
2 1 7 131 3
2 1 7 131 3
2 1 7 131 3
Variante 2: Mit Switch-Case und dann while(Abbruchbedingung). Dummerweise funktioniert -1 als Abbruchbedingung nicht und ich weiss nicht, ob ich überhaupt auf die folgenden Bytes zugreifen kann oder nur auf das aktuelle.
Das ist aus einem Sample des javax.com Pakets.
Ich wäre über Hilfe sehr sehr dankbar, ich komme alleine nicht mehr weiter.
Danke
ich habe ein Programm geschrieben, dass Daten an einen Microcontroller sendet, die Antwort des Controllers empfängt und diese ausgibt.
Die empfangenen Daten sollen nicht nur einfach ausgegeben, sondern vorher nach bestimmten Kritierien geprüft und bei Bedarf verändert werden.
Die Daten vom Controller kommen in folgender Form:
Startflag (1Byte), Länge(1Byte), Befehl(1Byte), Daten(Länge-1 Byte), Checksumme(1 Byte), Endflag(1 Byte)
Die Länge gibt an, wie viele Byte Befehl+Daten dem Länge-Byte folgen werden.
Beispiel: 0x02 0x01 0x22 0xBA 0x03 Die Länge ist 1, d.h. das es keine Daten gibt, nur das Command.
Mit diesem Wissen muss ich die eingehenden Bytes prüfen. Ich muss das StartByte erkennen, mir Länge und Command holen und je nach Command entsprechend handeln.
Ich habe schon sehr viel versucht und auch per Such-Funktion eingiges gefunden aber keine passende Lösung.
Im Wesentlichen habe ich 2 Varianten ausprobiert und mit ihnen experimentiert.
-Variante 1: Erst alle Daten in einen ByteFeld-Buffer schreiben und den dann über eine For-Schleife durchgehen
ausgabe ist ein Textfield, ich verwende (im Moment) einen normalen InputStream.
Probleme: Die Antwort des Controllers ist nicht immer gleich lang und oft sind es mehrere Frames hintereinander.
Ausserdem sind es nicht immer nur Bytes, die der Controller sendet.
Wenn der Befehl 0x55 ist, sendet der Controller mehrere Frames mit Characters, die auch als solche ausgegeben werden sollen. Aber sie werden als Bytes ausgegeben
Bei allen anderen Befehlen sollen die Bytes direkt in hexadeziamler Form ausgegeben werden. Das funktioniert ja soweit.
Oft kommt es bei der Ausgabe zu Fehlern, vor allem dann wenn es sich um mehrere Frames handelt, oder wenn man viele Befehle nacheinander sendet.
Beispiel: Das soll eigentlich immer die gleiche Antwort sein, aber es werden Bytes vergessen, oder sind 0,...
Ich glaube das hat mit dem Buffer zu tun.
2 1 7 131 3
2 1 0 0 0
2 1 7 131 3
2 1 7 0 0
2 1 7 131 3
2 1 7 131 3
2 1 7 131 3
2 1 7 131 3
Code:
public class Receiver implements SerialPortEventListener{
public void serialEvent(SerialPortEvent event) {
if(event.getEventType()==SerialPortEvent.DATA_AVAILABLE){
byte[] readBuffer = new byte[256];
try {
while (in.available() > 0) {in.read(readBuffer);}
ausgabe.append("\n");
for (int i=0;i<readBuffer.length;i++) {
if(readBuffer[i]==0x02 && readBuffer[i+2]==0x55){
//0x02 is Startbit und 0x55 ein Befehl auf den ich reagieren will.
//Wenn ich 0x02 finde, weiss ich dass das übernächste Byte das Command ist.
byte laenge = readBuffer[i+1];
//ich weiss, dass nach dem Startbit die Länge kommt
for (int j=0;j<(laenge-1);j++){
//ich gebe nur die Daten aus, ohne start,länge,befehl,crc,endbit
ausgabe.append(readBuffer[i+3+j]+" ");
}
}
if(readBuffer[i]==0x02 && readBuffer[i+2]!=0x55){
//Gibt alle Frames aus, die ein anderes Command als 0x55 haben.
byte laenge = readBuffer[i+1];
for (int j=0;j<(laenge+4);j++){
ausgabe.append(unsignedByteToInt(readBuffer[i+j])+" ");
}
}
}
}
catch (IOException e) {System.out.println("Fehler: "+e);}
}
}
}
Variante 2: Mit Switch-Case und dann while(Abbruchbedingung). Dummerweise funktioniert -1 als Abbruchbedingung nicht und ich weiss nicht, ob ich überhaupt auf die folgenden Bytes zugreifen kann oder nur auf das aktuelle.
Das ist aus einem Sample des javax.com Pakets.
Code:
public void serialEvent(SerialPortEvent e) {
// Create a StringBuffer and int to receive input data.
StringBuffer inputBuffer = new StringBuffer();
int newData = 0;
// Determine type of event.
switch (e.getEventType()) {
// Read data until -1 is returned. If \r is received substitute
// \n for correct newline handling.
case SerialPortEvent.DATA_AVAILABLE:
while (newData != -1) {
try {
newData = is.read();
if (newData == -1) {
break;
}
if ('\r' == (char)newData) {
inputBuffer.append('\n');
} else {
inputBuffer.append((char)newData);
}
} catch (IOException ex) {
System.err.println(ex);
return;
}
}
// Append received data to messageAreaIn.
messageAreaIn.append(new String(inputBuffer));
break;
// If break event append BREAK RECEIVED message.
case SerialPortEvent.BI:
messageAreaIn.append("\n--- BREAK RECEIVED ---\n");
}
}
Ich wäre über Hilfe sehr sehr dankbar, ich komme alleine nicht mehr weiter.
Danke