我有一些需要从串行设备读取的代码。它是一个轮询函数,由速率r
调用。
设备以\r\n
及其快速,以100Hz左右的速度将数据吐出。每当我轮询时,我想读取整个串行缓冲区。我发现很难用boost :: asio,因为它似乎没有为我提供available()
函数。
我尝试过的其中一种方法是使用read_until()
,但它无法解决我的问题,因为在\r\n
read_until()
停止后,缓冲区中可能会有更新的数据。 / p>
我在阅读之后尝试了consume()
缓冲区,但在我知道我已经从设备中读取了最新数据之前,这仍然是一项黑客工作。
有人对此问题有任何建议吗?
答案 0 :(得分:1)
由于串行端口被读取为流而不是随机访问句柄,因此必须按接收顺序读取数据。鉴于此行为,以下是获取最新数据的几个选项:
\r\n
"字符序列用于数据边界,考虑使用async_read_until()
来尊重数据边界,而不必在应用程序代码中引入边界处理。如果入口速率大于消耗速率,则超时可能不是确定性的。native_handle()
与系统特定的调用一起使用,以确定可供读取的字节数。然后,有一个读取策略,使用可用的字节数来确定何时停止读取。请注意,可用的字节数可能不会直接落在数据边界上。因此,应用程序将需要处理碎片。例如,可以async_read_until()
超时。但是,一旦消耗了先前已知的可用字节数,就可以显式停止异步调用链。这为异步调用链提供了确定性结束,即使入口速率超过了消耗速率。请参阅系统文档以确定如何查询准备读取的可用字节,但在Linux上通常为ioctl(..., FIONREAD, ...)
,在Windows上为ClearCommError()
。async_read_until()
调用链从串行端口连续读取并保留最近读取的数据。根据人们访问最新数据的方式,可能需要同步机制(如互斥锁)来避免竞争条件。从串行端口读取后无需锁定的一种替代方法是使用future / promise,并将履行promise的操作发布到运行async_read_until()
循环的同一链中。