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 fderscheinen den Trick gemacht haben:
sleep(2); //required to make flush work, for some reason
tcflush(fd,TCIOFLUSH);
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
12814900cookie-checkLöschen des Puffers der seriellen Schnittstelleyes