串口性能 - VB.NET vs C ++&促进

时间:2018-02-25 17:31:28

标签: c++ vb.net performance serial-port boost-asio

我无法理解为什么我的应用程序需要花费很长时间才能通过Windows 10上的串行端口与设备进行通信。我已经编写了两个小型测试应用程序,试图查看是什么让它变得如此之慢。这是两个代码:

''VB.NET code    
Imports System.IO.Ports

Module Module1

    Sub Main()
        Dim port As New SerialPort("COM3", 921600, Parity.None, 8, 1)

        port.Open()

        port.DtrEnable = True
        port.RtsEnable = True

        Dim profiler As New Stopwatch

        profiler.Start()

        For i As Integer = 1 To 100
            port.Write("1PA?" & vbCrLf)
            port.ReadLine()
            port.Write("TB" & vbCrLf)
            port.ReadLine()
        Next

        profiler.Stop()

        Console.WriteLine("Average: " & profiler.ElapsedMilliseconds / 100 & "ms")

        Console.ReadKey()
    End Sub

End Module

//C++ code
#include <iostream>
#include <string>

#include "boost/asio/io_service.hpp"
#include "boost/asio/serial_port.hpp"
#include "boost/asio/read_until.hpp"
#include "boost/asio/write.hpp"
#include "boost/asio/streambuf.hpp"
#include "boost/asio/buffer.hpp"
#include "boost/thread.hpp"
#include "boost/ref.hpp"
#include "boost/lexical_cast.hpp"

using boost::asio::io_service;
using boost::asio::serial_port;
using boost::asio::streambuf;

size_t read_until(serial_port& port, streambuf& buf, const std::string& delim)
{
    return boost::asio::read_until(port, buf, delim);
}

void complete(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    if (error)
        std::cout << "Error\n";
}

int main()
{
    std::cout << "Starting...\n";

    io_service io;
    serial_port port(io, "COM3");
    streambuf buf(1000);

    boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::local_time();

    port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
    port.set_option(boost::asio::serial_port_base::parity());
    port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port::flow_control::hardware));
    port.set_option(boost::asio::serial_port_base::baud_rate(921600));
    port.set_option(boost::asio::serial_port_base::character_size(8));


    for (int i = 0; i < 100; ++i)
    {
        boost::asio::write(port, boost::asio::buffer("1PA?\r\n", 6));

        read_until(port, buf, "\r\n");
        buf.consume(buf.size());

        boost::asio::write(port, boost::asio::buffer("TB\r\n", 4));

        read_until(port, buf, "\r\n");
        buf.consume(buf.size());
    }

    boost::posix_time::ptime tE = boost::posix_time::microsec_clock::local_time();

    std::cout << (tE-t0).total_milliseconds() << '\n';

    std::cin.get();
}

问题是VB.NET代码每次循环迭代报告平均约6ms(即每个写/读对3ms),而C ++代码每次迭代占用60ms。

项目的其余部分是用C ++编写的,所以我需要改进代码并且不能简单地使用另一个代码。目前,我发现最快的方法是通过TCP / IP与将TCP / IP路由到串行端口的VB.NET应用程序进行通信。奇怪的是,尽管涉及额外的步骤,但这比直接C ++实现快两倍。

我有什么遗漏,也许是C ++实现中的一个设置?我已经尝试过所有流量控制选项,不同的缓冲区大小......

1 个答案:

答案 0 :(得分:4)

您看到的写入/读取/写入/读取序列的60 ms与预定传输的典型默认值相当。这是FTDI(非常流行的USB串口芯片组)的端口配置

enter image description here

如果串口初始化代码没有明确设置超时,那么你得到的是每16ms的预定传输。

如果您改为呼叫SetCommTimeouts,则可以安排USB设备在每次串行RX线路上有间隙时转发接收的数据缓冲区。为此,请将ReadIntervalTimeout设置为传输时间仅几个字节。在921 kbaud时,每个字节需要10-11微秒,因此ReadIntervalTimeout的最小可能超时1毫秒对应于大约92字节的间隙。

但是,由于各种USB设备附带的驱动程序的实施质量不同,因此可能会遇到不具备字符间超时硬件支持的设备。在这种情况下,最好禁用ReadIntervalTimeoutReadTotalTimeoutMultiplier,并使用ReadTotalTimeoutConstant

使用这些超时配置中的任何一种,USB上的数据传输都会更加及时,您的代码也会取得进展。

然而,USB延迟仍将是每次接收3毫秒的数量级(当RX线路忙时为1毫秒,1毫秒空闲以触发超时,另外1毫秒等待下一个USB时隙)。要做到每3毫秒更好的消息,你需要进行管道处理,以便通过一些滑动窗口方案替换stop-and-wait协议来传输多条消息。