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

时间:2014-12-28 17:08:16

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

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

设备以\r\n及其快速,以100Hz左右的速度将数据吐出。每当我轮询时,我想读取整个串行缓冲区。我发现很难用boost :: asio,因为它似乎没有为我提供available()函数。

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

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

有人对此问题有任何建议吗?

1 个答案:

答案 0 :(得分:1)

由于串行端口被读取为流而不是随机访问句柄,因此必须按接收顺序读取数据。鉴于此行为,以下是获取最新数据的几个选项:

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