C# SerialPort 单字节慢往返时间

问题描述

我编写了一个微控制器 (pyboard),一旦它从 PC 接收到一个字节,就会通过其虚拟通信端口发送一个字节。 在 PC 端,我使用 C# SerialPort。 往返时间(发送字节/接收字节)非常慢,平均为 12 毫秒(-> ~83.3 循环/秒 -> ~ 166.6 B/s)。

当我用 python (pyserial) 尝试同样的方法时,我得到大约 0.12ms (~ 16.7KB/s) 的往返时间!

(数据用于尽可能快地控制和读取 gpio 引脚(8 个输入/8 个输出)。)

我尝试过的课程:

  • 原始 .net System.IO.Ports.SerialPort
  • 来自 Jason Curl 的 RJCP.IO.Ports.SerialPortStream

我尝试过的方法

  • SerialPort.WriteByte() 和 SerialPort.ReadByte()
  • 等待 SerialPort.WriteAsync(...) 并等待 SerialPort.ReadAsync()
  • SerialPort.Write 和 while(SerialPort.Read == 0);

我试过的参数:

  • 更改波特率(115200、230400、921600)
  • 将 SerialPort.ReadBufferSize/WriteBufferSize 减少到 1
  • 尝试使用 Read/WriteTimeout

我尝试过的其他事情:

  • 在调试模式和发布模式下启动程序集
  • 在设备管理器中更改波特率设置

它没有改善往返时间。

是否有我遗漏的参数、设置或其他任何东西? 我可以使用 C# 中的替代方案吗?或者进一步的改进建议?

以下是我尝试过的一些测试方法示例:

SerialPortStream port = new SerialPortStream("COM6",115200);
List<byte> data = new List<byte>();

public PyboardTester()
{
    port.ReadBufferSize = 1;
    port.WriteBufferSize = 1;
    port.ReceivedBytesThreshold = 1;
    port.open();
}

public string Data => string.Join(",",data);

public async Task<TimeSpan> CommTestAsync(int iterations)
{
    data.Clear();
    if (iterations == 0)
        return TimeSpan.Zero;

    byte outp = 0;
    byte inp = 0;
    var sw = Stopwatch.StartNew();
    await Task.Run(() =>
    {
        for (int n = 0; n < iterations; n++)
        {
            port.WriteByte(outp);
            inp = (byte)port.ReadByte();
            outp = inp;
            data.Add(inp);
        }
    });

    return TimeSpan.FromMilliseconds(sw.Elapsed.TotalMilliseconds / iterations);
}

public async Task<TimeSpan> CommTest2Async(int iterations)
{
    data.Clear();
    if (iterations == 0)
        return TimeSpan.Zero;

    var outp = new byte[1];
    var inp = new byte[1];
    var sw = Stopwatch.StartNew();
    for (int n = 0; n < iterations; n++)
    {
        await port.WriteAsync(outp,1);
        while (await port.ReadAsync(inp,1) == 0) ;
        outp[0] = inp[0];
        data.Add(inp[0]);
    }

    return TimeSpan.FromMilliseconds(sw.Elapsed.TotalMilliseconds / iterations);
}

Python 代码

import serial
import time

iterations = 1000

s = serial.Serial("COM6")
inp = bytearray(1)
outp = bytearray(1)
data = bytearray(iterations)

t = time.time()
for n in range(iterations):
    s.write(outp)
    s.readinto(inp)
    outp[0] = inp[0]
    data[n] = inp[0]
    
delta = time.time() - t
print("%s ms per roundtrip" % (delta * 1000 / iterations))
s.close()

pyboard 代码(MicroPython):

import pyb

vcp = pyb.USB_VCP(0)
vcp.init()
vcp.setinterrupt(-1)

inputbuffer = bytearray(1)
outputbuffer = bytearray(1)
while True:
    if not vcp.any():
        continue
    vcp.readinto(inputbuffer)
    outputbuffer[0] = inputbuffer[0] + 1
    vcp.send(outputbuffer,timeout=100)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)