Hallo Community,
Ich entwickle gerade eine Software in C++ unter Linux um von einem
Rasperry Befehle per RS232 an einen Mikrocontroller zu senden. Dies
funktioniert auch soweit. Wenn ich einen einzigen Befehl sende bekomme
ich auch die richtige Rückantwort. Wenn ich jedoch vor diesem Sende
befehl ein sleep(..) habe bekomme ich eine falsche Rückantwort. Und wenn
ich einen zweiten Befehl sende, also nachdem ich die Rückantwort vom
ersten Befehl erhalten habe, bekomme ich auch eine falsche Rückantwort.
Weis leider mittlerweile echt nicht mehr weiter.
Dies ist meine Funktion um RS232 zu aktivieren.
int openRS232()
{
int uart0_filestream = -1;
uart0_filestream = open("/dev/ttyS0", O_RDWR | O_NOCTTY
|O_NONBLOCK);
if (uart0_filestream == -1) {
printf("[ERROR] UART open()\n");
}
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
options.c_iflag = IGNPAR;
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
return uart0_filestream;
}
Dies ist meine Funktion um einen Befehl zu senden und die Rückantwort zu
empfangen:
// Bytes senden
unsigned char BUF_TX[20];
unsigned char *TX;
TX = &BUF_TX[0];
*TX++ = a;
*TX++ = b;
*TX++ = c;
*TX++ = 0;
*TX++ = 0;
*TX++ = 0;
*TX++ = 0;
*TX++ = 0;
if (uart0_filestream != -1) {
int out = write(uart0_filestream, &BUF_TX[0], (TX - &BUF_TX[0]));
if (out < 0) {
printf("[ERROR] UART TX\n");
} else {
printf("[STATUS: TX %i Bytes] %s\n", out, BUF_TX);
}
} // if uart0
sleep(1);
// Bytes empfangen
if (uart0_filestream != -1) {
unsigned char BUF_RX[50];
int rx_length = read(uart0_filestream, (void*)BUF_RX, 50);
if (rx_length < 0) {
printf("[ERROR] UART RX\n");
} else if (rx_length == 0) {
printf("[ERROR] UART RX - no data\n");
} else {
BUF_RX[rx_length] = '\0';
if(BUF_RX[8]==6)
{
printf("AKG Empfangen \n");
if(BUF_RX[7]==4)
{
printf("Refinitial \n");
}
}else{
printf("try again \n");
}
} //rx_length check
} //if uart0
close(uart0_filestream);
}
und dies ist meine Main Methode wie Sie funktioniert:
int main() {
readRS232(openRS232(),'R','S','T');
return 0;
}
So bekomme ich eine falsche antwort:
int main() {
sleep(1);
readRS232(openRS232(),'R','S','T');
return 0;
}
so bekomme ich beim ersten eine richtige Antwort, beim zweiten eine
falsche:
int main() {
readRS232(openRS232(),'R','S','T');
sleep(1);
readRS232(openRS232(),'R','S','T');
return 0;
}
Ich hoffe man kann den Code einigermaßen lesen, bin noch sehr frisch in
C++ und im embedded bereich.
Möglicherweise erkennt ja hier jemand den Fehler und kann mir
weiterhelfen, über Rückantworten würde ich mich sehr freuen.
Mit freundlichen Grüßen
Julian
1 | int rx_length = read(uart0_filestream, (void*)BUF_RX, 50); |
du kannst nicht einfach davon ausgehen, das du alles auf einmal bekommst. Es kann durchaus passieren, das bei jeden read nur 1 Byte gelesen wird. Du musst also noch eine schleife schreiben und die Daten sammeln.
Habe das read jetzt in eine while Schleife gepackt:
int rx_length =0;
while(rx_length<9)
{
rx_length = read(uart0_filestreamm, (void*)BUF_RX,50);
}
Dies funktioniert auch beim ersten Aufruf wunderbar. Und wenn der zweite
Befehl aufgerufen wir bleibt er für immer in der while-Schleife hängen.
Julian M. schrieb: > while(rx_length<9) > { > rx_length = read(uart0_filestreamm, (void*)BUF_RX,50); > } du überschreibt dir immer den buffer.
vielen Dank für die Antwort leider weis ich nicht ganz wie ich das
realisieren soll. Da in der Dokumentation von read steht: read(int
handle, void *buffer, int nbyte).
Nun dachte ich mir dass es so aussehen müsste:
while(rx_length<9)
{
rx_length += read(uart0_filestreamm, (void*)BUF_RX, 1);
}
jedoch kommt dann auch etwas falsches heraus. da er bei diesem Befehl
eine -1 als antwort bekommt.
so in der Art
1 | int rx_length = 0; |
2 | char BUF_RX[50]; |
3 | |
4 | while(rx_length<9) |
5 | {
|
6 | int r = read(uart0_filestreamm, &BUF_RX[rx_length], rx_length-9); |
7 | if ( r < 1 ) { |
8 | //Fehlerbehandlung
|
9 | //break;
|
10 | }
|
11 | rx_length += r; |
12 | }
|
Vielen Dank, habe nun herausgefunden, dass immer wenn es nicht geht, genau 3 bytes fehlen. Woran könnte das liegen? Meine Antwort die ich bekommen sollte lautet: ['S']['T']['V'][][][][4][6] kann es vielleicht daran liegen, dass 3 Null Bytes in der Mitte übertragen werden? Also die 3 leeren Bytes werden nicht verwendet. Aber das AKG also die 6 muss an letzter Stelle sein.
Julian M. schrieb: > kann es vielleicht daran liegen, dass 3 Null Bytes in der Mitte > übertragen werden? dann zeige doch mal die Daten als Hex an.
Diese HEX Daten sind vorhanden wenn es funktioniert: 53, 54, a7, 8, 0, 0, 0, 4, 6 Und diese wenn es nicht funktioniert: 52, 69, 2c, 40, 0, e4, 0, 0, 0
Julian M. schrieb: > kann es vielleicht daran liegen, dass 3 Null Bytes in der Mitte > übertragen werden? ... es könnte natürlich sein, daß C ein '\0' als Stringende betrachtet ...
Julian M. schrieb: > Diese HEX Daten sind vorhanden wenn es funktioniert: hast du eine Beschreibung von dem Protokoll?
Was meinen Sie genau mit Beschreibung von dem Protokoll? Und zu der vorherigen Antwort, Ja unter C ist "\0" String Ende. Deswegen setze ich nach dem Empfang BUF_RX[rx_length] = '\0';. Aber ich bekomme ja eigentlich kein '\0' oder? Ich verstehe halt auch nicht wieso es bei der ersten Anfrage immer funktioniert.
Vielen Dank an alle. Habe es jetzt mit WiringPi erledigt. Anfangs das gleiche Problem. Vermutlich liegt es an sleep(). Den als ich sleep ersetzt habe durch delay() ging es auf einmal. Nochmal danke an alle.
> Den als ich sleep ersetzt habe durch delay() ging es auf einmal.
Das klingt arg nach Pfusch und auch nicht so, als könnte es wirklich
zuverlässig immer gehen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.