首页 > 解决方案 > 在 C# 中通过串行端口进行高速串行通信

问题描述

我正在使用 Visual Studio 2019。我正在通过 uart/串行端口将数据从微控制器发送到 PC,我想在 PC 端读取它。

波特率为 9600。我正在使用以下代码。但是,它非常缓慢。我需要能够以非常高的速度读取代码(与我使用的波特率相当)。

目前,我每秒收到 2-3 个数据包。计时器间隔设置为 10 毫秒,但即使我将其更改为 1 毫秒,也没有区别。我无法弄清楚我做错了什么。帮助将不胜感激。

问候,萨尔曼

    public void  readCapsule(SerialPort sp)
    {
        timer1.Enabled = false;

        string headerStart = "";
        string headerEnd = "";
        List<Int32> newCoordinates = new List<Int32>();

        headerStart = sp.ReadLine();

        if (headerStart == "START")
        {               
            for (int i = 0; i < 3; i++)
            {
                Int32 coords = sp.ReadByte();
                newCoordinates.Add(coords);
            }

            tbRead.AppendText("X: " + newCoordinates[0].ToString() + " ");
            tbRead.AppendText("Y: " + newCoordinates[1].ToString() + " ");
            tbRead.AppendText("Z: " + newCoordinates[2].ToString() + Environment.NewLine);

            headerEnd = sp.ReadLine();
            newCoordinates.Clear();                
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        readCapsule(spCapsule);            
        Application.DoEvents();
        spCapsule.DiscardInBuffer();
        timer1.Enabled = true;
    }

我的微控制器代码基本上是递增 3 个变量并将它们发送到 START 和 END 标头之间。我知道还有其他行正在执行,所以吞吐量不会是 9600,但我认为我经历的延迟太长了,无法从微控制器方面贡献出来。微控制器代码如下。我正在使用 Atmega328p。我已经在超级终端上验证了传入数据的速度比我使用 C# 代码读取的速度快得多:

while (1) {

    counter++; val1 = val1 + 3; val2 = val2 + 3; val3 = val3 + 3; 

    if(counter >= 100) {

        counter = 0;
        val1 = 1; val2 = 2; val3 = 3;

        }

    transmitUart0('S'); transmitUart0('T'); transmitUart0('A'); transmitUart0('R'); transmitUart0('T');transmitUart0(0x0A);
    transmitUart0(val1);
    transmitUart0(val2);
    transmitUart0(val3);
    transmitUart0('E'); transmitUart0('N'); transmitUart0('D'); transmitUart0(0x0A);

    _delay_ms(10);

}

标签: c#.netserial-portuartserial-communication

解决方案


您应该尝试一次处理所有缓冲区数据。因此,与其逐字节或逐行读取,不如订阅事件 SerialPort.DataReceived 并立即处理整个块。

请参阅此示例:https ://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.datareceived?view=netframework-4.8

private static void DataReceivedHandler(
                    object sender,
                    SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    Console.WriteLine("Data Received:");
    Console.Write(indata);
    // Use BeginInvoke for synchonization!
}

有关使用 BeginInvoke,请参阅此其他线程


推荐阅读