【问题标题】:Program hangs when closing serial port connection关闭串口连接时程序挂起
【发布时间】:2013-04-04 08:00:13
【问题描述】:

我正在使用 PL2303 驱动程序通过 USB 连接作为串行端口读取数据。它在执行open 以及设置它们的 TTY 选项和非阻塞时成功返回。当我尝试关闭连接时,它挂起。在这种状态下,它读取“�”而不是字符。

我可以用cutecom完美地连接到设备。这是奇怪的部分:

  1. 如果我首先通过cutecom(串行监视器)连接到设备,之后我的程序每次都可以正常连接和关闭。它读取字符,因为我希望它们被读取。 (没有 �)。
  2. 如果我断开并重新连接硬件,我的程序将再次挂起,直到我运行 cutecom。

因为在我使用cutecom 后它可以工作,它让我觉得我在初始连接或连接设置中遗漏了一些东西。这是我用来连接的:

baud_rate = 38400;
fd =  open (device_path, O_RDONLY | O_NOCTTY );

在我的set_tty_options 函数中:

struct termios tty_options;

memset (&tty_options, 0, sizeof(tty_options));
tcgetattr (fd, &tty_options);

cfsetispeed(&tty_options, baud_rate);                         // set baud rate
tty_options.c_cflag = (tty_options.c_cflag & ~CSIZE) | CS8;   // 8 bit msgs
tty_options.c_cflag |= (CLOCAL | CREAD);                      // enable reading

tty_options.c_cflag &= ~(PARENB | PARODD);                    // shut off parity
tty_options.c_cflag |= parity;
tty_options.c_cflag &= ~CSTOPB;
tty_options.c_cflag &= ~CRTSCTS;

if (tcsetattr (fd, TCSANOW, &tty_options) != 0) 
{
  printf("error %d from tcsetattr\n", errno);
  return TTY_ERROR;
}

set_blocking函数中:

if (tcgetattr (fd, &tty) != 0)
{
  printf("error %d from tggetattr", errno);
  return FAILURE;
}

// 0 or 1 byte is enough to return from read
tty.c_cc[VMIN]  = should_block ? 1 : 0; 
tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

if (tcsetattr (fd, TCSANOW, &tty) != 0) 
{
  printf("error %d setting term attributes", errno);
  return FAILURE;
}

【问题讨论】:

  • 我发现您的代码存在 2 个问题。首先是set_tty_options 函数似乎没有完全初始化tty_options 结构。这可以解释“如果我先运行 X,我的程序可以工作,但如果单独运行,则会挂起/失败”。这是程序没有正确或完全初始化其环境的典型症状。其次,set_blocking 函数对于规范输入是虚假的。 c_cc[VMIN]c_cc[VTIME] 只能用于非规范(又名原始)输入。对于规范输入的非阻塞 read(),请使用 fcntl() 进行设置。

标签: c linux serial-port


【解决方案1】:

我认为您想将 | O_SYNC 添加到打开标志以坚持同步 i/o。不过我怀疑这会导致问题。

但是,我认为您想忽略中断信号,该信号被报告为 NUL 字符,就像您得到的那样:

tty_settings.c_iflag &= ~IGNBRK;         // ignore break signal

另外,您要确保输入处理完全关闭,以便收到退格键、^C、^\ 等不会触发任何反应:

tty_settings.c_lflag = 0;                // no signaling chars, no echo,
                                         // no canonical processing

您似乎已经在使用my set_blocking() function,所以应该没问题。

【讨论】:

    【解决方案2】:

    这就是我最终要做的。我基本上是通过从cutecom's 源代码中复制和粘贴部分来解决这个问题的。

    1. 打开时...

      int fd, n;
      fd = open (device_path, O_RDONLY | O_NOCTTY | O_NDELAY);
      
      ... error check fd ...
      
      n = fcntl(ail_info->ail_serial_fd, F_GETFL, 0);
      fcntl(fd, F_SETFL, n & ~O_NDELAY);
      
    2. 你不能像我一样设置波特率。你必须使用定义的B38400;

      baud = B38400;

    3. 然后,我添加了 wallyk 的答案。

      tty_settings.c_lflag = 0;

    编辑:根据锯末评论,我找到了一种将其设置为原始输入的更好方法。

    tty_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    

    它有效。

    【讨论】:

    • "然后,我添加了wallyk的答案。tty_settings.c_lflag = 0;" -- 你还没有正确配置串口。 c_oflag 设置为什么?请注意,不建议根据 POSIX 硬分配给 termios 结构成员。您应该调用tcgetattr(),然后启用或禁用每个属性字段(就像您为c_cflag 所做的那样)。见Serial Programming Guide for POSIX Operating Systems。您正在使用 POSIX 调用,因此请遵循它们的规则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 2022-01-16
    相关资源
    最近更新 更多