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.