读取具有字符间超时的串行端口以获取长数据流

时间:2018-08-09 08:49:10

标签: c unix serial-port uart

在我的应用程序中,我连接到串行设备,该设备将发送大小未知的定期数据。我不想使用StartofFrame和EndOfFrame关键字检测传入的帧。取而代之的是,我想使用字符间超时来检测传入的帧。传入数据帧之间始终会有至少100ms的持续时间。 因此,我可以使用此时间间隔检测帧。我正在使用此功能打开串口:

uint8_t open_serial_port(uart_device* dev)
{
    dev->fd = open(dev->path, O_RDWR | O_NOCTTY);
    if (dev->fd < 0)
    {
    syslog(LOG_CRIT, "Serial Port {%s}-{%s} couldn't opened", dev->name, dev->path);
        return EXIT_FAILURE;
    }

    syslog(LOG_INFO, "Serial Port {%s}-{%s} opened with fd {%d}", dev->name, dev->path, dev->fd);

    struct termios tty;

    if (tcgetattr(dev->fd, &tty) < 0)
    {
        syslog(LOG_CRIT, "Serial Connection attributes get for fd {%d} failed with errno cause {%s}", dev->fd, strerror(errno));
        return EXIT_FAILURE;
    }

    cfmakeraw(&tty);
    cfsetospeed(&tty, (speed_t) dev->speed);
    cfsetispeed(&tty, (speed_t) dev->speed);

    tty.c_cc[VMIN]  = 255;   //! This is used to block to get at least VMIN characters
    tty.c_cc[VTIME] = 10;  //! used to block for tens of seconds timeout 10 -> 1 seconds timeout

    tty.c_cflag |= CLOCAL;
    tty.c_cflag &= ~CSIZE; //! Mask the character size bits
    tty.c_cflag |= get_start_stop_opt(dev->data, dev->stop);    //! Set data, stop bits
    tty.c_cflag |= get_parity_opt(dev->parity); //! set parity configuration
    tty.c_cflag |= get_hw_flow_control(dev->flow_control);

    if (tcsetattr(dev->fd, TCSANOW, &tty))
    {
        syslog(LOG_CRIT, "Serial Connection attributes set for fd {%d} failed with errno cause {%s}", dev->fd, strerror(errno));
        return EXIT_FAILURE;
    }

    syslog(LOG_INFO, "Serial Connection {%s}-{%s} established. speed: %d, parity: %s, data: %d, stop: %d, flw_ctrl: %d", dev->name, dev->path, dev->speed,
    dev->parity, dev->data, dev->stop, dev->flow_control);

    return EXIT_SUCCESS;
}

我正在以阻止模式读取串行端口:

    readSize = read(dev->fd, &buf, UART_MAX_PAYLOAD);
    if (readSize < 0)
    {
        syslog(LOG_CRIT, "UART Read failed while reading {%s}, error {%s}", dev->path, strerror(errno));
        usleep(1000 * 1000);
        continue;
    }

    syslog(LOG_INFO, "Uart read completed. readSize: %d", readSize);

实际上,termios的VMIN和VTIME参数适合我的情况,但是VMIN和VTIME定义为8位。因此,我最多可以声明255个字符。 因此,当设备发送2048字节的数据时,我将其读取为:

Uart read completed. readSize: 496
Uart read completed. readSize: 496
Uart read completed. readSize: 496
Uart read completed. readSize: 496
Uart read completed. readSize: 64

以某种方式,我无法同时读取全部数据。

以阻塞模式读取大数据有什么问题?如何一次读取大型串行数据?

最诚挚的问候。

0 个答案:

没有答案