Linux 清除串口缓冲区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13013387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:40:25  来源:igfitidea点击:

Clearing the serial port's buffer

clinuxserial-portflush

提问by capcom

This is what my function looks like to open the serial port (using Ubuntu 12.04):

这是我的函数打开串行端口的样子(使用 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);
}

What the problem is, is that when I run this program and if my serial device was already plugged in, the buffer has content in it. I need a way to clear the buffer before I start reading from it. I thought using tcsetattr(fd, TCSAFLUSH, &options);would fix this problem, by flushing the IO buffers before initializing the port, but no such luck. Any insight?

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

回答by capcom

I think I figured it out. For some reason, I need to add a delay before flushing. These two lines added before returning fdseemto have done the trick:

我想我想通了。出于某种原因,我需要在刷新之前添加延迟。在返回之前添加的这两行fd似乎已经成功了:

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

回答by Robert

The cause of this problem lies in using a USB serial port. If you use a regular serial port, you will not have this problem.

此问题的原因在于使用 USB 串行端口。如果使用普通的串口,就不会有这个问题。

Most USB serial port drivers don't support flushing properly, probably because there's no way of knowing if there's still data in the internal shift register, FIFO or in the USB subsystem.

大多数 USB 串行端口驱动程序不支持正确刷新,可能是因为无法知道内部移位寄存器、FIFO 或 USB 子系统中是否仍有数据。

See also Greg's reply to a similar problem reported earlier here.

参见Greg的一个类似的问题的答复早些时候报道在这里

Your sleepmay cure the problem, but it's only a work-around. Unfortunately there is no solution other than using a regular serial port.

sleep可能会解决问题,但这只是一种解决方法。不幸的是,除了使用常规串行端口之外,没有其他解决方案。

回答by areslagae

I have been experiencing similar symptoms with an Arduino Uno board that resets on open(). I was receiving data after the open() call that was generated before the Arduino board had been reset and thus before open() had been called.

我一直在使用 Arduino Uno 板遇到类似的症状,该板在 open() 时重置。我在 Arduino 板被重置之前生成的 open() 调用之后接收数据,因此在 open() 被调用之前。

Tracking down the issue with ioctl() calls I learned that the data had simply not yet arrived in the input buffer by the time tcflush() was called. So the tcflush() did work but there was no data to flush. A sleep of 1000 us after the open() call seemed to solve the issue. This is becasue the delay allowed the data to arrive before tcflush() was called and therefore tcflush() did indeed flush the input buffer.

通过 ioctl() 调用跟踪问题,我了解到在调用 tcflush() 时数据还没有到达输入缓冲区。所以 tcflush() 确实有效,但没有要刷新的数据。在 open() 调用后睡眠 1000 us 似乎解决了这个问题。这是因为延迟允许数据在 tcflush() 被调用之前到达,因此 tcflush() 确实刷新了输入缓冲区。

You might be experiencing the same issue.

您可能遇到了同样的问题。