c++ - 使用boost asio从串口读取最新数据

标签 c++ boost serial-port boost-asio

我有一些代码需要从串行设备读取。它是由速率 r 调用的轮询函数。

设备以 \r\n 分隔的行形式输出数据,速度很快,大约 100Hz。每当我轮询时,我都想读取整个串行缓冲区。我发现这很难用 boost::asio 来做,因为它似乎没有为我提供 available() 函数。

我尝试的方法之一是使用 read_until() 但它没有解决我的问题,因为在 \r\n 之后缓冲区中可能有更新的数据> read_until() 停止于。

我在读取缓冲区后尝试了 consume(),但在我知道我已从设备读取最新数据之前,这仍然是一项 hack 工作。

有人对这个问题有建议吗?

最佳答案

由于串行端口是作为流而不是随机访问句柄读取的,因此必须按照接收数据的顺序读取数据。鉴于此行为,这里有一些获取最新数据的选项:

  • 从流中读取,直到读取操作因超时而失败。虽然 Boost.Asio 既不提供非阻塞同步读取也不提供串行 I/O 对象的超时读取,但可以使用异步读取和计时器来实现这一行为。 Boost.Asio 提供了一个超时集合examples .由于“\r\n”字符序列用于数据边界,请考虑使用 async_read_until()尊重数据边界,而不必在应用程序代码中引入边界处理。如果入口速率大于消耗速率,则超时可能不确定。
  • 使用串口的native_handle()使用系统特定的调用来确定可用于读取的字节数。然后,制定一个读取策略,使用可用字节数来确定何时停止读取。请注意,可用字节数可能不会直接落在数据边界上。因此,应用程序需要处理碎片。例如,可以使用超时 async_read_until()。但是,一旦消耗了先前已知的可用字节数,就可以显式停止异步调用链。这为异步调用链提供了一个确定性的结束,即使入口速率超过消费速率。查阅系统文档以确定如何查询准备读取的可用字节,但通常是 ioctl(..., FIONREAD, ...)在 Linux 上,和 ClearCommError()在 Windows 上。
  • 将使用数据与串行端口和查询最近接收到的数据分离。通过职责分离,消费者线程将通过 async_read_until() 调用链不断从串行端口读取数据,并保留最近读取的数据。根据访问最新数据的方式,可能需要同步机制(如互斥锁)来避免竞争条件。从串行端口读取后无需锁定的一种替代方法是使用 future / promise ,并将实现 promise 的操作发布到运行 async_read_until() 循环的同一链中。
  • 如果数据写入频率足够高,可以接受在轮询中等待完整样本,那么可以 flush the serial port's receive buffer ,导致所有数据被丢弃。一旦被丢弃,就可以从串行端口读取,等待写入发生,从而产生最新的数据。由于刷新缓冲区可能会丢弃样本的一部分,因此可能需要读取第二个数据边界以保证已读取完整的样本。

关于c++ - 使用boost asio从串口读取最新数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27678647/

相关文章:

c++ - 如何使用wt实现ajax请求处理?

C++ "delayed"模板参数

c++ - 定义可变大小的元组

vb.net - 串口读取包括vb.net中已经写入的内容

c# - 如何在 Visual C# 中打开连接之前检查 COM 端口是否存在

c++ - 为什么 sizeof(std::variant) 与具有相同成员的结构的大小相同?

c++ - 如何使用 mingw 在 Windows 中静态链接 qt 应用程序

c++ - 如何安排一个操作在未来的时间运行

c++ - 为什么 C++11/Boost `unordered_map` 在删除时不重新散列?

java - RxTx 库的许可限制是什么