我最近实施了一个小程序,它读取来自传感器的数据并将其绘制成图表。
数据以5个字节为单位,大约每500μs(波特率:500000)。大约3000个块组成一个完整的线。因此总传输时间约为1.5秒。
当我看到实时图时,我注意到显示的内容与当前测量的内容之间存在严重的延迟。调查,这一切都归结为:
SerialPort.ReadLine();
比传输线多约0.5秒。因此每行读取大约需要2秒。有趣的是,没有数据丢失,每次读取新行时,数据都会略微落后。这对用户来说非常恼火,所以我不能这样离开。
我已经实现了自己的变体,它显示了大约1.5秒的一致时间,并且没有出现延迟。我并不为我的实现感到自豪(或多或少地轮询BaseStream),我想知道是否有办法加速ReadLine
类的SerialPort
函数。随着我的实现,我也得到了一些损坏的行,并且还没有找到确切的问题。
我已尝试将ReadTimeout
更改为1600,但刚刚生成TimeoutException
。虽然数据到了。
对于为什么它很慢或解决方法的任何解释都表示赞赏。
作为旁注:我在一个只有SerialPort.ReadLine()的控制台应用程序上尝试了这个,结果是一样的,所以我排除了影响SerialPort
的我自己的应用程序
我不确定这是否相关,但我的实现如下:
LineSplitter lineSplitter = new LineSplitter();
async Task<string> SerialReadLineAsync(SerialPort serialPort)
{
byte[] buffer = new byte[5];
string ret = string.Empty;
while (true)
{
try
{
int bytesRead = await serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
byte[] line = lineSplitter.OnIncomingBinaryBlock(this, buffer, bytesRead);
if (null != line)
{
return Encoding.ASCII.GetString(line).TrimEnd('\r', '\n');
}
}
catch
{
return string.Empty;
}
}
}
LineSplitter如下:
class LineSplitter
{
// based on: http://www.sparxeng.com/blog/software/reading-lines-serial-port
public byte Delimiter = (byte)'\n';
byte[] leftover;
public byte[] OnIncomingBinaryBlock(object sender, byte[] buffer, int bytesInBuffer)
{
leftover = ConcatArray(leftover, buffer, 0, bytesInBuffer);
int newLineIndex = Array.IndexOf(leftover, Delimiter);
if (newLineIndex >= 0)
{
byte[] result = new byte[newLineIndex+1];
Array.Copy(leftover, result, result.Length);
byte[] newLeftover = new byte[leftover.Length - result.Length];
Array.Copy(leftover, newLineIndex + 1, newLeftover, 0, newLeftover.Length);
leftover = newLeftover;
return result;
}
return null;
}
static byte[] ConcatArray(byte[] head, byte[] tail, int tailOffset, int tailCount)
{
byte[] result;
if (head == null)
{
result = new byte[tailCount];
Array.Copy(tail, tailOffset, result, 0, tailCount);
}
else
{
result = new byte[head.Length + tailCount];
head.CopyTo(result, 0);
Array.Copy(tail, tailOffset, result, head.Length, tailCount);
}
return result;
}
}
答案 0 :(得分:-1)
我在2008年遇到了与GPS模块交谈的问题。基本上阻塞功能是片状的,解决方案是使用APM。
以下是另一个Stack Overflow答案中的血腥细节:How to do robust SerialPort programming with .NET / C#?