Löschen des Puffers der seriellen Schnittstelle

Lesezeit: 3 Minuten

Benutzer-Avatar
capcom

So sieht meine Funktion zum Öffnen der seriellen Schnittstelle aus (mit Ubuntu 12.04):

int open_port(void)
{
  int fd; /* File descriptor for the port */

  fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

  if (fd == -1)
  {
   // Could not open the port.          
   perror("open_port: Unable to open /dev/ttyUSB0 - ");
  }
  else
    fcntl(fd, F_SETFL, 0);

  struct termios options;

  tcgetattr(fd, &options); 
  //setting baud rates and stuff
  cfsetispeed(&options, B19200);
  cfsetospeed(&options, B19200);
  options.c_cflag |= (CLOCAL | CREAD);
  tcsetattr(fd, TCSANOW, &options);

  tcsetattr(fd, TCSAFLUSH, &options);

  options.c_cflag &= ~PARENB;//next 4 lines setting 8N1
  options.c_cflag &= ~CSTOPB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;

  //options.c_cflag &= ~CNEW_RTSCTS;

  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw input

  options.c_iflag &= ~(IXON | IXOFF | IXANY); //disable software flow control

  return (fd);
}

Das Problem ist, dass, wenn ich dieses Programm ausführe und mein serielles Gerät bereits angeschlossen war, der Puffer Inhalt enthält. Ich brauche eine Möglichkeit, den Puffer zu löschen, bevor ich anfange, daraus zu lesen. Ich dachte mit tcsetattr(fd, TCSAFLUSH, &options); würde dieses Problem beheben, indem die IO-Puffer geleert werden, bevor der Port initialisiert wird, aber kein solches Glück. Irgendeine Einsicht?

Ich glaube, ich habe es herausgefunden. Aus irgendeinem Grund muss ich vor dem Spülen eine Verzögerung hinzufügen. Diese beiden Zeilen wurden vor der Rückkehr hinzugefügt fd erscheinen den Trick gemacht haben:

  sleep(2); //required to make flush work, for some reason
  tcflush(fd,TCIOFLUSH);

  • Ich denke, es war dieser Fehler im Linux-Kernel: siehe lkml.iu.edu//hypermail/linux/kernel/0707.3/1776.html

    – Etienne

    28. März 2014 um 8:37 Uhr


  • Linux 4.8.0, Ubuntu 16.04×64, cp210x USB UART-Treiber (USB VID/PID: 10c4:ea60) – hat das gleiche Problem mit diesem Setup. Lösung: setzen usleep(10000); nach open(). Zwei Sekunden sind zu lang, aber die von @areslagae vorgeschlagenen 1000 us waren zu kurz. 10 ms sind in meinem Fall genau richtig.

    – Dmitri

    5. Juli 2017 um 10:01 Uhr

Die Ursache dieses Problems liegt in der Verwendung eines seriellen USB-Anschlusses. Wenn Sie eine normale serielle Schnittstelle verwenden, haben Sie dieses Problem nicht.

Die meisten USB-Seriell-Port-Treiber unterstützen das Leeren nicht richtig, wahrscheinlich weil es keine Möglichkeit gibt zu wissen, ob noch Daten im internen Schieberegister, FIFO oder im USB-Subsystem vorhanden sind.

Siehe auch Gregs Antwort auf ein früher gemeldetes ähnliches Problem hier.

Dein sleep kann das Problem beheben, aber es ist nur eine Problemumgehung. Leider gibt es keine andere Lösung als die Verwendung einer normalen seriellen Schnittstelle.

Ich habe ähnliche Symptome bei einem Arduino Uno-Board erlebt, das bei open() zurückgesetzt wird. Ich habe Daten nach dem Aufruf von open() empfangen, der generiert wurde, bevor das Arduino-Board zurückgesetzt wurde und somit bevor open() aufgerufen wurde.

Dem Problem mit ioctl()-Aufrufen auf der Spur Ich erfuhr, dass die Daten zum Zeitpunkt des Aufrufs von tcflush() einfach noch nicht im Eingabepuffer angekommen waren. Das tcflush() hat also funktioniert, aber es waren keine Daten zum Spülen vorhanden. Ein Schlaf von 1000 us nach dem Aufruf von open() schien das Problem zu lösen. Dies liegt daran, dass die Verzögerung es ermöglichte, dass die Daten ankamen, bevor tcflush() aufgerufen wurde, und daher hat tcflush() tatsächlich den Eingabepuffer geleert.

Möglicherweise haben Sie das gleiche Problem.

  • Schließlich bin ich nicht der Einzige.

    – Oskar

    14. Mai 2018 um 13:43 Uhr

1281490cookie-checkLöschen des Puffers der seriellen Schnittstelle

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy