C# 中的串行端口非常非常高速的串行通信,具有最佳性能并且没有任何数据丢失

问题描述 投票:0回答:1

我在一个示例应用程序中的 C# 串行端口上遇到了数据丢失问题,该应用程序从微控制器板接收非常非常高的数据速度(在 2000 个 18 字节数据包中每秒高达 36000 字节)。

我的波特率是 1.000.000,我使用

DataReceived
事件。我有一个模拟器来生成主要应用程序测试的数据。我将两个 COM 端口(COM1 -> COM2)与“虚拟串口驱动程序”软件配对。

收到数据包后,它们会保存到

*.CSV
文件中,但一些数据会丢失。

我的第一个也是重要的问题是数据丢失。

我的第二个问题是这种情况下的CPU使用性能(高达50%或60%)。

这是我的模拟器串口配置和数据生成器代码:

SerialPort serialPort = new SerialPort("COM1", 1000000, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.Open();
serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

byte[] packet = new byte[] { 83, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 78 };
ulong packetCount = 0;
while (packetCount < 600000);
{
    byte[] timeBytes = BitConverter.GetBytes(packetCount);
    packet[2] = timeBytes[0]; 
    packet[3] = timeBytes[1]; 
    packet[4] = timeBytes[2]; 
    packet[5] = timeBytes[3];
    Write(packet);
    packetCount++;
}

在此代码中,数据包具有标头 {83, 84} 和页脚 {69, 78}

这是我的主应用程序中的串口配置:

SerialPort _serialPort = new SerialPort("COM2", 1000000, Parity.None, 8, StopBits.One);
_serialPort.Handshake = Handshake.None;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
_serialPort.ReadBufferSize = 100;

这是我主应用程序中的

dataReceived
事件:

private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int count = _serialPort.BytesToRead;
    byte[] receivedTemp = new byte[count];
    _serialPort.Read(receivedTemp, 0, count);
    _totalReceived.AddRange(receivedTemp);
    findPacket();
}

这是使用页眉和页脚查找数据包的

findPacket
函数:

int findPacket(int index = 0, bool headerFounded = false)
{
    while (index + 1 < _totalReceived.Count)
    {
        if (_totalReceived[index] == 83 && _totalReceived[index + 1] == 84)
        {
            int headerIndex = index;
            int packetLen = 14; 
            int footerIndex = findPacket(index + 2 + packetLen, true);
            if (footerIndex > -1 && (packetLen == 0 || (footerIndex == headerIndex + packetLen + 2)))
            {
                List<byte> data = totalReceived.GetRange(headerIndex + 2, footerIndex - (headerIndex + 2));
                totalReceived.RemoveRange(headerIndex, footerIndex + 2 - headerIndex);
                if (headerIndex > 0 && !headerFounded)
                    totalReceived.RemoveRange(0, headerIndex);

                calcPacket(data);
                continue;
            }
            else if (footerIndex != -1)
            { 
                 index++; 
                 continue; 
            }
            break;
        }

        if (headerFounded && totalReceived[index] == 69 && totalReceived[index + 1] == 78)
            return index;

        index++;
    }

    return -1;
}

问题是:当模拟器数据生成器启动时,

findPacket
非常非常忙,并且我的主应用程序中的所有其他异步功能(例如主 UI 和 CSV 编写器以及在线图表抽屉等)都无法工作并被锁定。

c# serial-port serial-communication
1个回答
0
投票

您可以在不使用递归函数的情况下完成此操作。递归函数会增加系统使用的资源。这种情况下,可能调用次数过多,导致时间错误 你可以这样做:

  async void findPacket3()
    {
        byte[] header = new byte[] { 83, 84 };
        byte[] footer = new byte[] { 69, 78 };
        int maxLength = header.Length + footer.Length;

        int index = 0;
        int headerIndex = -1;
        int footerIndex = -1;
        while (!_canceltoken.IsCancellationRequested)
        {
            await Task.Delay(5);
            while (index < totalRecieved.Count)
            {
                if (index + (header.Length - 1) < totalRecieved.Count && totalRecieved[index] == header[0] && totalRecieved[index + 1] == header[1])
                {
                    headerIndex = index;
                    int packetLen = 0; // findPacketLen(index);
                    index += header.Length + packetLen;
                    continue;
                }
                if (headerIndex > -1 && index + (footer.Length - 1) < totalRecieved.Count && totalRecieved[index] == footer[0] && totalRecieved[index + 1] == footer[1])
                {
                    footerIndex = index;
                    List<byte> data = totalRecieved.GetRange(headerIndex + header.Length, footerIndex - (headerIndex + header.Length));
                    calcPacket(data);
                    headerIndex = -1;
                }
                index++;
            }
            if (footerIndex > -1)
            {
                totalRecieved.RemoveRange(0, footerIndex + footer.Length);
                footerIndex = -1;
                index = 0;
                headerIndex = -1;
            }
        }

    }

还有,为了避免数据丢失,最好设置一下

_serialPort.ReadBufferSize = 4096;
© www.soinside.com 2019 - 2024. All rights reserved.