【问题标题】:Boost::serial_port and asio::async_write for byte[256] exceeds 200msbyte[256] 的 Boost::serial_port 和 asio::async_write 超过 200ms
【发布时间】:2018-07-01 07:16:22
【问题描述】:

我正在通过串行端口实现一些基本通信。

根据协议,我必须在收到请求后 225 毫秒内回复。最大封装大小为 256B。

因此,当我收到请求时,我创建响应 [header, lenght, payload, crc16](总共 256 B),我需要平均 30 - 40 毫秒。然后,当我将该响应(字节数组)放入asio::async_write 时,就会出现实际问题。该函数平均需要大约 240 毫秒来处理该字节数组。

除了我发送最大长度的包裹外,一切正常。它需要 240ms (asio::async_write) + 40ms(封装组装) 大约 280 ~ 300 ms。

端口:9600 波特,长度 8,一位停止位

知道如何加快速度吗?

    void Example::do_write()
{
    if (pimpl_->WriteBuffer == nullptr)
    {
        boost::lock_guard<boost::mutex> l(pimpl_->WriteQueueMutex);
        pimpl_->WriteBufferSize = pimpl_->WriteQueue.size();
        pimpl_->WriteBuffer.reset(new byte[pimpl_->WriteQueue.size()]);
        std::move(pimpl_->WriteQueue.begin(), pimpl_->WriteQueue.end(), pimpl_->WriteBuffer.get());
        pimpl_->WriteQueue.clear();

        begin = boost::chrono::steady_clock::now();
        async_write(pimpl_->Port, asio::buffer(pimpl_->WriteBuffer.get(), pimpl_->WriteBufferSize), boost::bind(&Example::write_end, this, asio::placeholders::error));
    }
}

void Example::write_end(const system::error_code& error)
{
    if (!error)
    {
        boost::lock_guard<boost::mutex> l(pimpl_->WriteQueueMutex);
        if (pimpl_->WriteQueue.empty())
        {
            pimpl_->WriteBuffer.reset();
            pimpl_->WriteBufferSize = 0;

            end = boost::chrono::steady_clock::now();
            OutputDebugString(string("\nWRITE TIME: " + to_string(boost::chrono::duration_cast<boost::chrono::milliseconds>(end - begin).count()) + "\n").c_str());

            return;
        }

        pimpl_->WriteBufferSize = pimpl_->WriteQueue.size();
        pimpl_->WriteBuffer.reset(new byte[pimpl_->WriteQueue.size()]);

        std::move(pimpl_->WriteQueue.begin(), pimpl_->WriteQueue.end(), pimpl_->WriteBuffer.get());
        pimpl_->WriteQueue.clear();

        async_write(pimpl_->Port, asio::buffer(pimpl_->WriteBuffer.get(), pimpl_->WriteBufferSize), boost::bind(&Example::write_end, this, asio::placeholders::error));
    }
    else
    {
        set_error_status(true);
        do_close();
    }
}

【问题讨论】:

  • 你的代码在哪里?你如何衡量给定的时间?
  • 您的互斥锁不适合保护写入缓冲区,因为异步操作在互斥锁下运行

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


【解决方案1】:

根据我的经验, boost::asio 本身只需要几微秒。您使用 40 毫秒来获取数据,通信需要 220 毫秒(在 9600 波特上发送 256 个字节大约是最低限度),而在某处您浪费了更多 20-40 毫秒,总和为 280-300 毫秒。

怎么办?

  1. 最有利可图的可能是将波特率提高到 115200 波特(9600 波特的 0.85 毫秒/字节与 115200 波特的 0.07 毫秒/字节)。
  2. 下一个想法是分析这 20-40 毫秒的去向(可能是您编写的消息循环中不需要的东西)。
  3. 最后也有可能减少 40 毫秒的数据获取时间。

【讨论】:

  • 默认协议波特率必须为9600。
  • 9600 波特,长度 8,一个停止位 = 每个字 10 位 = 10/9600 = 1041.66666666 微秒 = 1.041 毫秒 * 256[字] = 266 毫秒,对吗?
  • 是的,可能是我的号码略有偏差。如果你不能提高波特率,那么你就不能用 225 毫秒物理传输 256 个字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多