【问题标题】:Reading from serial port with Boost Asio使用 Boost Asio 从串口读取
【发布时间】:2011-02-17 22:06:28
【问题描述】:

我想使用boost.asio 检查串行端口上的传入数据包。每个数据包都以一个字节长的标头开始,并指定已发送的消息类型。每种不同类型的消息都有自己的长度。我要编写的函数应该不断地监听新的传入消息,当它找到一个它应该读取它,并调用其他函数来解析它。我目前的代码如下:

void check_for_incoming_messages()
{
    boost::asio::streambuf response;
    boost::system::error_code error;
    std::string s1, s2;
    if (boost::asio::read(port, response, boost::asio::transfer_at_least(0), error)) {
        s1 = streambuf_to_string(response);
        int msg_code = s1[0];
        if (msg_code < 0 || msg_code >= NUM_MESSAGES) {
            // Handle error, invalid message header
        }
        if (boost::asio::read(port, response, boost::asio::transfer_at_least(message_lengths[msg_code]-s1.length()), error)) {
            s2 = streambuf_to_string(response);
            // Handle the content of s1 and s2
        }
        else if (error != boost::asio::error::eof) {
            throw boost::system::system_error(error);
        }
    }
    else if (error != boost::asio::error::eof) {
        throw boost::system::system_error(error);
    }
}

boost::asio::streambuf 是正确的工具吗?以及如何从中提取数据以便解析消息?我还想知道我是否需要一个单独的线程来只调用这个函数,以便更频繁地调用它。我是否应该担心由于高流量和串口缓冲区耗尽而在两次调用函数之间丢失数据?我正在使用 Qt 的 GUI 库,但我真的不知道处理所有事件需要多少时间。

编辑: 有趣的问题是:如何检查串口是否有任何传入数据?如果没有传入数据,我不希望函数阻塞...

【问题讨论】:

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


    【解决方案1】:

    本文有助于了解如何将 ASIO 与串行端口异步使用:

    更新(2019-03)

    我链接到的原始文章不再可用,即使在 Internet 档案中也很难找到。 (这里是snapshot。)。现在有较新的文章关于使用 ASIO 进行串行 I/O 很容易通过搜索找到,但是这篇较旧的文章仍然非常有用。我把它放在一个公共要点中,这样它就不会丢失:

    文章中描述的代码似乎是复制到这里的:

    作者似乎已经为 C++11 更新了它。我相信这篇文章是 原作者fede.tft

    【讨论】:

    • 谢谢! :) 我发现我也必须这样做。
    • 我发现我必须异步读取才能不中断程序流程。之前,我使用的是read 函数,而async_read 是正确的函数。写入也是一样,async_write 用于防止由于某种原因导致读取暂停时程序冻结。
    • @HelloGoodbye 你能把fede网页的源代码分享给我吗?该站点现在正在移动到 Internet 存档,并且无法再克隆。谢谢!
    • @ShawnLe 我希望原始源代码很快就会在 Internet Archive 上用于克隆。但是,原始文章的来源似乎也可以在 Github 上找到:github.com/fedetft/serial-port
    【解决方案2】:

    杰森,

    如果它适合您的应用程序,我强烈建议您实现基于回调的异步串行 RX。 How do I perform a nonblocking read using asio? 有一个很好的小例子,说明如何使用超时实现异步串行。正如您所认识到的,它需要多线程实现才能获得性能优势,因此您需要考虑将接收到的数据缓存在哪里,以确保您不会进行大量复制。

    boost::streambuff 的内容而言,我个人更喜欢将一些内存作为字符数组-char m_RXBuffer[m_RXBuffSize] 并使用boost::asio::buffer(m_RXBuffer, m_RXBuffSize) 将目标缓冲区传递给async_read_some。特别是对于 RS232,我一直发现底层数据是字节流的事实自然比任何更复杂的数据结构更好地映射到简单的 char 数组。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      相关资源
      最近更新 更多