【问题标题】:write() to serial port fails when called twice两次调用时,写入()到串行端口失败
【发布时间】:2014-06-21 03:39:30
【问题描述】:

我正在尝试将 char 数组写入串行端口两次。由于某种原因,我第二次调用 write() 它失败了,我不知道为什么。奇怪的是第一次写入成功。

这是我的写函数:

void write_port()
{
  unsigned char writeBuffer[5];
  int i;
  size_t len;

  writeBuffer[0] = 0x00;
  writeBuffer[1] = 0x01;
  writeBuffer[2] = 0x02;
  writeBuffer[3] = 0x03;
  writeBuffer[4] = 0x04;  

  len = sizeof(writeBuffer);

  for (i=0; i < len; i++)
  {
    printf("Write: %x\n", writeBuffer[i]);
  }

  //First Write:
  int n = write(fd, writeBuffer, len);
  if (n < 0)
    fputs("Serial Port Write Failed!\n", stderr);
  else
    printf("Wrote %0d bytes to serial port\n", n);

  //Second Write:
  n = write(fd, writeBuffer, len);
  if (n < 0)
    fputs("Serial Port Write Failed!\n", stderr);
  else
    printf("Wrote %0d bytes to serial port\n", n);  
}

这里是我配置端口的地方:

int open_port(void)
{
  struct termios options;

  fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);

  bzero(&options, sizeof(options));   // set everything to 0 

  if (fd != -1)
  {
    printf("Serial Port Open\n");

    tcgetattr(fd, &options_original);
    tcgetattr(fd, &options);
    cfsetispeed(&options, B460800);
    cfsetospeed(&options, B460800);
    options.c_cflag |= (CLOCAL | CREAD); /* Enable the receiver and set local mode */
    options.c_cflag &= ~ECHO; // Disable echoing of input characters
    options.c_cflag &= ~ECHOE;
    options.c_cflag &= ~PARENB; // parity disabled
    options.c_cflag &= ~CSTOPB; // 1 stop bit
    options.c_cflag &= ~CSIZE;  // Mask the character size bits
    options.c_cflag |=  CS8;    // 8 data bits    
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Raw Input Mode */

    if (tcsetattr(fd, TCSANOW, &options))    /* Set the new options for the port */
    {
      perror("could not set the serial settings!");
      return -1;
    }
  }
  else
  {
    /* Could not open the port */
    perror("open_port: Unable to open /dev/ttyUSB0 - ");
  }

  return (fd);
}

最后这是我的控制台输出。

Serial Port Open
Flushing IO Buffers
Write: 0
Write: 1
Write: 2
Write: 3
Write: 4
Wrote 5 bytes to serial port
Serial Port Write Failed!
Serial Port Closed

因此,由于某种未知原因,我从第二次 write() 中得到了 -1 并且完全不知道为什么,到底是什么导致了这种情况?

【问题讨论】:

  • 我不确定这是否重要,但是串行端口连接到什么?串行写入的输出缓冲区有多大?
  • 你为什么不使用perror 来获取更多关于为什么第二次写入失败的信息?
  • 在我的电脑上,'ttyUSB0' 是一个键跨 USB 串行转换器,并从那里连接到带有 rs232 控制器的 fpga 开发板。我不确定输出缓冲区有多大。更新:我返回的错误号是errno = 11,perror 返回perror = : Resource temporarily unavailable
  • 也许串口不能一次占用10个字节。您可以通过在前 5 个字节后放置 sleep 几秒钟来测试该概念,看看这是否会使问题消失。如果是这样,请检查 FPGA 开发板信息以查看有关串行通信的内容。也可能 USB/串行驱动程序未设置为预期的流量控制模式。
  • 在搜索了一些错误之后(感谢@Grapsus),可能的原因是我错误地设置了 O_NONBLOCK。我通过将| O_NONBLOCK 更改为&amp; ~O_NONBLOCK 来清除它,我的问题消失了,第二次写入也通过了。希望这能解决它!

标签: c linux serial-port


【解决方案1】:

我认为您的发送缓冲区已满,并且您正在使用非阻塞套接字,这意味着该进程不会像阻塞套接字那样等待缓冲区清除,而是返回“资源暂时不可用错误”。有关更多信息,请参阅此线程:What can cause a “Resource temporarily unavailable” on sock send() command

【讨论】:

    【解决方案2】:

    如果失败则写入系统调用设置 errno 变量。您可以检查以获取有关写入失败原因的确切详细信息。另外你可以参考这个项目的linux原生代码,看看write是如何实现的https://github.com/RishiGupta12/serial-communication-manager

    【讨论】:

    • 欢迎来到 SO。我认为您的第一句话会更清楚,因为“如果 write 系统调用失败,那么它会设置 errno 变量。”这是你的意思吗?这个答案作为评论可能比作为答案更好。不幸的是,你还没有发布 cmets 的声誉,所以你最终能做的事情并不多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多