繁体   English   中英

使用boost asio从串行端口读取最新数据

[英]Reading the latest data from serial port using boost asio

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

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

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

读取缓冲区后,我尝试在缓冲区上consume() ,但这仍然是一项繁琐的工作,直到我知道我已从设备读取了最新数据。

有人对这个问题有意见吗?

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

  • 从流中读取,直到读取操作因超时而失败。 尽管Boost.Asio既不提供无阻塞的同步读取,也不为串行I / O对象提供带超时的读取,但是可以使用异步读取和计时器来实现此行为。 Boost.Asio提供了一组超时示例 由于“ \\r\\n ”字符序列用于数据边界,请考虑使用async_read_until()尊重数据边界,而不必在应用程序代码内引入边界处理。 如果进入速率大于消耗速率,则超时可能不确定。
  • 使用串行端口的native_handle()和系统特定的调用来确定可读取的字节数。 然后,采用一种读取策略,该策略使用可用的字节数来确定何时停止读取。 请注意,可用字节数可能不会直接落在数据边界上。 因此,应用程序将需要处理碎片。 例如,一个async_read_until()可能超时。 但是,一旦消耗了先前已知的可用字节数,就可以显式停止异步调用链。 即使入口速率超过消耗速率,这也为异步调用链提供了确定性的终结。 请查阅系统文档以确定如何查询准备读取的可用字节,但是在Linux上通常是ioctl(..., FIONREAD, ...) ,在Windows上通常是ClearCommError()
  • 从串行端口解耦消耗的数据,并查询最近接收到的数据。 在职责分离的情况下,使用者线程将通过async_read_until()调用链连续从串行端口读取并保留最近读取的数据。 根据人们访问最新数据的方式,可能需要使用同步机制(例如互斥体)来避免争用情况。 一种消除从串行端口读取后锁定的需要的替代方法是使用async_read_until() ,并将满足诺言的操作发布到运行async_read_until()循环的同一async_read_until()
  • 如果以足够高的频率写入数据,这样可以等待轮询中的完整样本,则可以刷新串行端口的接收缓冲区 ,从而丢弃所有数据。 一旦丢弃,就可以从串行端口读取数据,等待写入发生,从而得到最新数据。 由于清空缓冲区可能会丢弃一部分样本,因此可能需要读取第二个数据边界以确保已读取完整的样本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM