Forum: Mikrocontroller und Digitale Elektronik Linux RS232 Problem


von Julian M. (julianm94)


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

von Peter II (Gast)


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.

von Julian M. (julianm94)


Lesenswert?

Vielen Dank, versuche ich gleich einmal.

von Julian M. (julianm94)


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.

von Peter II (Gast)


Lesenswert?

Julian M. schrieb:
> while(rx_length<9)
> {
>   rx_length = read(uart0_filestreamm, (void*)BUF_RX,50);
> }

du überschreibt dir immer den buffer.

von Peter II (Gast)


Lesenswert?

Nachtrag:

du musst auch die länge aufaddieren.

von Julian M. (julianm94)


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.

von Peter II (Gast)


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
}

von Julian M. (julianm94)


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.

von Peter II (Gast)


Lesenswert?

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.

von Julian M. (julianm94)


Lesenswert?

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

von Markus F. (mfro)


Lesenswert?

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 
...

von Peter II (Gast)


Lesenswert?

Julian M. schrieb:
> Diese HEX Daten sind vorhanden wenn es funktioniert:

hast du eine Beschreibung von dem Protokoll?

von Julian M. (julianm94)


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.

von Julian M. (julianm94)


Lesenswert?

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.

von Georg A. (georga)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.