我正在使用Visual Studio2019。我正在通过uart /串行端口将数据从微控制器发送到PC,我想在PC端读取数据。
波特率是9600。我正在使用以下代码。但是,它非常慢。我需要能够以非常高的速度读取代码(与我使用的波特率相当)。
目前,我每秒收到2-3个数据包。计时器间隔设置为10毫秒,但是即使将其更改为1毫秒,也没有任何区别。我不知道我在做什么错。帮助将不胜感激。
关于, 萨尔曼(Salman)
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);
}
答案 0 :(得分:1)
我们不知道您的微控制器在做什么,但是在您的C#代码上,通过逐个读取字节来给处理过程带来巨大的负担。
显然,减少这种开销的解决方案是不要一一读取字节。只需摆脱for
循环,在检测到标头之后立即执行第二次sp.ReadLine()
,使用获得的字节存储坐标,然后丢弃其余的字节。
如果这种方法不能解决您的问题,请尝试解决它:一口气阅读更多命令并进行处理。在这一点上,我猜想改变微控制器的工作方式可能会更容易。
编辑:既然您已经包含了更多详细信息,并且您已经意识到,我上面的评论并没有真正的帮助。
)
首先,已知ReadLine()
的运行速度很慢,例如参见here。
如果要计算出数字,您要尝试做的并不是那么苛刻。因此解决方案可能是使用任何其他方法,我建议尝试使用BaseStream
在CR之间实现您自己的阅读方式(类似于上面链接的问题所建议的方式)。
否则,您可以尝试DataReceived
event。
最后,请注意,当您说:
计时器间隔设置为10毫秒,但是即使我将其更改为1毫秒,也没有区别...
是指微控制器上的延迟。反过来看,如果您想在PC上读取数据获得更好的性能,则需要增加而不是减少此延迟(否则,您发送的数据量甚至超出了您的处理能力) )。但是,如果ReadLines()
这么慢,我怀疑您可以利用它来提高性能,除非您愿意每3或4秒读取一个数据样本。
答案 1 :(得分:1)
您应该尝试一次处理所有缓冲区数据。因此,订阅事件SerialPort.DataReceived并立即处理整个块,而不是逐字节或逐行读取。
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,see this other thread。
答案 2 :(得分:0)
根据反馈,我对代码进行了一些更改。延迟是相同的。请参见下面的代码:
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;
}