清空串口缓冲区

23

这是我用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);
}

我的问题是,当我运行这个程序时,如果我的串行设备已经插入,则缓冲区中会有内容。我需要一种在开始读取之前清除缓冲区的方法。我认为使用 tcsetattr(fd, TCSAFLUSH, &options); 可以解决这个问题,通过初始化端口之前刷新IO缓冲区,但没有这样的运气。有什么见解吗?

3个回答

31

我想我搞清楚了。出于某种原因,在刷新之前需要添加一些延迟。在返回 fd 之前添加这两行代码似乎已经解决了问题:

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

1
我认为这是Linux内核中的一个bug:请参见http://lkml.iu.edu//hypermail/linux/kernel/0707.3/1776.html。 - Étienne
2
Linux 4.8.0,ubuntu 16.04x64,cp210x USB UART驱动程序(USB VID / PID:10c4:ea60) - 使用此设置遇到了相同的问题。解决方案:在“open()”之后放置usleep(10000);。两秒钟太长了,但是@areslagae建议的1000us太短了。在我的情况下,10毫秒刚刚好。 - Dmitry

11
这个问题的原因在于使用USB串口。如果使用普通的串口,则不会出现此问题。
大多数USB串口驱动程序无法正确地支持刷新,可能是因为没有办法知道内部移位寄存器、FIFO或USB子系统中是否仍有数据。
请参见Greg对早期报告的类似问题的回复 此处
您的sleep可以解决问题,但这只是一个解决方法。不幸的是,除了使用常规串口之外,没有其他解决方法。

9
我遇到了与Arduino Uno板相似的症状,即在open()调用时重置。 在调用open()之后,我收到了由Arduino板在重置之前生成的数据,因此也就在调用open()之前生成的数据。
通过ioctl()调用查找问题,我发现该数据尚未到达输入缓冲区,此时调用tcflush()已经没有任何作用。open()调用后睡眠1000微秒似乎解决了这个问题。 这是因为延迟允许数据在调用tcflush()之前到达,因此tcflush()确实清除了输入缓冲区。
您可能正在遇到同样的问题。

2
最终,我不再是唯一的一个。 - Oscar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接