Linux RS232 Problem

OP #4728289
Lesenswert?
• ▲
▼
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
Gast #4728296
Lesenswert?
• ▲
▼
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.
OP #4728311
Lesenswert?
• ▲
▼
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.
OP #4728386
Lesenswert?
• ▲
▼
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.
Gast #4728395
Lesenswert?
• ▲
▼
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
}
OP #4728453
Lesenswert?
• ▲
▼
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.
OP #4728482
Lesenswert?
• ▲
▼
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren