关闭串口连接时程序挂起

时间:2013-04-02 19:12:44

标签: c linux serial-port

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

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

  1. 如果我首先通过cutecom(串行监视器)连接到设备,我的程序每次都会连接并完全关闭。它会读取我希望它们被读取的字符。 (没有 )。
  2. 如果我断开并重新连接硬件,我的程序将再次挂起,直到我运行cutecom。
  3. 因为它在我使用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 个答案:

答案 0 :(得分: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,所以这应该没问题。

答案 1 :(得分:0)

这就是我最终做的事情。我通过基本上复制和粘贴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;

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

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

    它有效。