[英]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.