【发布时间】: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