8

我想检查串行端口上的传入数据包,使用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 库,但我真的不知道处理所有事件需要多少时间。

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

4

2 回答 2

24

本文有助于理解 ASIO 如何与串口异步使用:

更新(2019-03)

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

文章中描述的代码似乎已复制到此处:

作者似乎已经为 C++11 更新了它。我相信这篇文章最初是由fede.tft撰写的。

于 2010-06-06T21:50:40.807 回答
3

杰森,

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

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

祝你好运!

于 2012-03-12T05:57:40.640 回答