web-dev-qa-db-fra.com

Vider le tampon du port série

Voici à quoi ressemble ma fonction pour ouvrir le port série (en utilisant 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);
}

Le problème est que lorsque j'exécute ce programme et si mon périphérique série est déjà branché, le tampon contient du contenu. J'ai besoin d'un moyen d'effacer le tampon avant de commencer à lire. Je pensais que l'utilisation de tcsetattr(fd, TCSAFLUSH, &options); résoudrait ce problème, en vidant les tampons IO avant d'initialiser le port, mais pas de chance. Une idée?

17
capcom

Je pense que je l'ai compris. Pour une raison quelconque, je dois ajouter un délai avant de rincer. Ces deux lignes ajoutées avant de renvoyer fdsemblent pour avoir fait l'affaire:

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

La cause de ce problème réside dans l'utilisation d'un port série USB. Si vous utilisez un port série standard, vous n'aurez pas ce problème.

La plupart des pilotes de port série USB ne prennent pas correctement en charge le rinçage, probablement parce qu'il n'y a aucun moyen de savoir s'il y a encore des données dans le registre à décalage interne, FIFO ou dans le sous-système USB.

Voir aussi la réponse de Greg à un problème similaire signalé précédemment ici .

Votre sleep peut résoudre le problème, mais ce n'est qu'une solution de rechange. Malheureusement, il n'y a pas d'autre solution que d'utiliser un port série standard.

6
Robert

J'ai rencontré des symptômes similaires avec une carte Arduino Uno qui se réinitialise sur open (). Je recevais des données après l'appel open () qui a été généré avant la réinitialisation de la carte Arduino et donc avant l'appel open ().

En recherchant le problème avec les appels ioctl (), j'ai appris que les données n'étaient tout simplement pas encore arrivées dans le tampon d'entrée au moment de l'appel de tcflush (). Donc, le tcflush () a fonctionné mais il n'y avait aucune donnée à vider. Un sommeil de 1000 nous après l'appel open () semblait résoudre le problème. C'est parce que le délai a permis aux données d'arriver avant que tcflush () soit appelé et donc tcflush () a effectivement vidé le tampon d'entrée.

Vous rencontrez peut-être le même problème.

5
areslagae