簡體   English   中英

通過C#中的串行端口進行高速串行通信

[英]High speed serial communication over serial port in C#

我正在使用Visual Studio2019。我正在通過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#代碼上,您通過逐字節讀取字節在處理中引入了巨大的開銷。

減少這種開銷的解決方案顯然是不要一一讀取字節。 只需擺脫for循環,在檢測到標頭之后sp.ReadLine()執行第二個sp.ReadLine() ,使用獲得的字節存儲坐標並丟棄其余部分。

如果這種方法不能解決您的問題,請嘗試解決它:一口氣閱讀更多命令並進行處理。 在這一點上,我想可能更容易改變微控制器的工作方式。

編輯:現在您已經包含了更多詳細信息,並且您已經意識到,我上面的評論並沒有真正的幫助。 )首先,已知ReadLine()非常慢,例如,請參見此處

如果您計算出數字,那么您嘗試做的並不是那么苛刻。 所以解決方案可能是使用任何其他方法,我建議嘗試使用BaseStream在CR之間實現您自己的讀取方式(類似於上面鏈接的問題所建議的方式)。

否則,您可以嘗試DataReceived事件

最后,請注意,當您說:

計時器間隔設置為10毫秒,但是即使我將其更改為1毫秒,也沒有任何區別...

指的是您的微控制器上的延遲。 反過來看,如果您希望在PC上讀取數據時看到更好的性能,則需要增加而不是減少此延遲(否則,您發送的數據甚至超過了您可以處理的數量)。 但是,如果ReadLines()這么慢,我懷疑您可以利用它來提高性能,除非您願意每3或4秒讀取一次數據樣本。

您應該嘗試一次處理所有緩沖區數據。 因此,訂閱事件SerialPort.DataReceived並立即處理整個塊,而不是逐字節或逐行讀取。

請參見以下示例: https : //docs.microsoft.com/zh-cn/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的信息, 請參見此其他線程

根據反饋,我對代碼進行了一些更改。 延遲是相同的。 請參見下面的代碼:

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

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

        headerStart = sp.ReadLine();
        tbRead.AppendText(headerStart + Environment.NewLine);

}


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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM