【问题标题】:Reading variable length data from serial with timeout超时从串行读取可变长度数据
【发布时间】:2019-01-21 09:49:07
【问题描述】:

我正在使用软件 UART 驱动程序从设备读取数据帧。它是作为 tty 模块编写的,因此从 is 读取是非常标准的:

struct termios options;
int tty = open(path, O_RDWR | O_NOCTTY  | O_SYNC);
tcgetattr(tty, &options);
options.c_cflag = B4800 | CS8 | CLOCAL | CREAD | PARENB;
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcsetattr(tty, TCSANOW, &options);
while (running)
{
    int rx_count = read(tty_device, (void*)header, header_size);
    // parse the header to figure out the total frame size
    rx_count = read(tty_device, (void*)frame_data, frame_size);
}

它大部分时间都可以工作,但有时由于 UART 可靠性的限制,我会丢失一些字节。

我的问题是,当我错过字节时,代码会读取下一帧的初始字节作为前一帧的最终字节。这会导致随机的、不可预测的行为。

我想知道是否有一种基于时间而不是数据大小来读取的好方法。像这样的:

while (running)
{
    // read bytes continuously from the tty device
    // if 1 second passes with no further bytes coming, stop reading
    // process whatever data was read
}

我可能最终会拼凑出一些可以做到这一点的东西,但我想这很有可能已经被弄清楚了,我只是没能在互联网上找到相关信息。

【问题讨论】:

  • 您阅读的帧有特定的格式吗?也许带有独特且易于识别的帧开始和帧结束标记?然后您可以从帧开始到帧结束逐字节读取,如果您在帧结束之前找到帧开始标记,那么您就知道数据包已损坏。
  • 考虑到您无法修改框架的结构,超时可能很有用(man7.org/linux/man-pages/man2/select.2.html
  • 您还可以使描述符成为非阻塞并读取,直到出现errno == EWOULDBLOCK 错误为止。可能结合我之前的建议。
  • @Someprogrammerdude 不幸的是,虽然有一个帧开始标记,但它只是一个字节,这个字节也可能出现在帧数据中。

标签: c serial-port buffer


【解决方案1】:

我能够使用 VMIN 和 VTIME 完成我需要的工作,如锯末评论中的链接中所示: Linux Blocking vs. non Blocking Serial Read

这也与我的问题有关。不知何故,我无法找出正确的搜索词来找到它: VMIN and VTIME Terminal Settings for variable sized messages

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 2017-08-24
    • 2013-02-25
    相关资源
    最近更新 更多