【问题标题】:Clearing the serial port's buffer清除串口缓冲区
【发布时间】:2012-10-12 09:04:42
【问题描述】:

这是我打开串口的功能(使用 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 缓冲区,但没有这样的运气。有什么见解吗?

【问题讨论】:

    标签: c linux serial-port flush


    【解决方案1】:

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

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

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

    【讨论】:

    • 最后,我不是一个人。
    【解决方案2】:

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

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

    另请参阅 Greg 对先前报告的类似问题的回复 here

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 我认为是Linux内核中的这个错误:见lkml.iu.edu//hypermail/linux/kernel/0707.3/1776.html
      • Linux 4.8.0, ubuntu 16.04x64, cp210x USB UART driver (USB VID/PID: 10c4:ea60) - 在这个设置中遇到了同样的问题。解决方案:将usleep(10000); 放在open() 之后。两秒太长了,但是@areslagae 建议的 1000us 太短了。 10ms 对我来说正好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 1970-01-01
      • 2016-08-18
      相关资源
      最近更新 更多