【发布时间】:2019-03-27 07:39:12
【问题描述】:
我从串口读取数据并在一个单独的类中解析它。然而,数据被错误地解析,一些样本被重复,而另一些则丢失了。
这是一个解析数据包的例子。它从 packetIndex 开始(应该从 1 开始并递增)。您可以看到 packetIdx 如何重复,以及其他一些值如何重复。我认为这是由于多线程造成的,但我不确定如何解决。
2 -124558.985180734 -67934.4168823262 -164223.049786454 -163322.386243628
2 -124619.580759952 -67962.535376851 -164191.757344217 -163305.68949052
3 -124685.719571795 -67995.8394760894 -164191.042088394 -163303.119039907
5 -124801.747477263 -68045.7062179692 -164195.288919841 -163299.140429394
6 -124801.747477263 -68045.7062179692 -164221.105184687 -163297.46404856
6 -124832.8387538 -68041.9287731563 -164214.936103217 -163294.983004926
这是我应该收到的:
1 -124558.985180734 -67934.4168823262 -164223.049786454 -163322.386243628
2 -124619.580759952 -67962.535376851 -164191.757344217 -163305.68949052
3 -124685.719571795 -67995.8394760894 -164191.042088394 -163303.119039907
4 -124801.747477263 -68045.7062179692 -164195.288919841 -163299.140429394
...
这是 SerialPort_DataReceived
public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
lock (_lock)
{
byte[] buffer = new byte[_serialPort1.BytesToRead];
_serialPort1.Read(buffer, 0, buffer.Length);
for (int i = 0; i < buffer.Length; i++)
{
//Parse data
double[] samplesAtTimeT = DataParserObj.interpretBinaryStream(buffer[i]);
//Add data to BlockingCollection when parsed
if (samplesAtTimeT != null)
_bqBufferTimerSeriesData.Add(samplesAtTimeT);
}
}
}
以及解析数据的类:
public class DataParser
{
private int packetSampleCounter = 0;
private int localByteCounter = 0;
private int packetState = 0;
private byte[] tmpBuffer = new byte[3];
private double[] ParsedData = new double[5]; //[0] packetIdx (0-255), [1-4] signal
public double[] interpretBinaryStream(byte actbyte)
{
bool returnDataFlag = false;
switch (packetState)
{
case 0: // end packet indicator
if (actbyte == 0xC0)
packetState++;
break;
case 1: // start packet indicator
if (actbyte == 0xA0)
packetState++;
else
packetState = 0;
break;
case 2: // packet Index
packetSampleCounter = 0;
ParsedData[packetSampleCounter] = actbyte;
packetSampleCounter++;
localByteCounter = 0;
packetState++;
break;
case 3: //channel data (4 channels x 3byte/channel)
// 3 bytes
tmpBuffer[localByteCounter] = actbyte;
localByteCounter++;
if (localByteCounter == 3)
{
ParsedData[packetSampleCounter] = Bit24ToInt32(tmpBuffer);
if (packetSampleCounter == 5)
packetState++; //move to next state, end of packet
else
localByteCounter = 0;
}
break;
case 4: // end packet
if (actbyte == 0xC0)
{
returnDataFlag = true;
packetState = 1;
}
else
packetState = 0;
break;
default:
packetState = 0;
break;
}
if (returnDataFlag)
return ParsedData;
else
return null;
}
}
【问题讨论】:
-
if (actbyte == 0xA0) {packetState++},但初始值为零?所以下一次,你又要打案例 1 了?这甚至正确吗?我认为 DataParser 是需要单元测试的类的一个很好的例子!
-
@Odrai True,packetState 在初始化时应该为 1。这只会影响第一次迭代,对于其余的迭代 packetState 在情况 1 中应该已经是 1。
-
if (actbyte = 0xC0),缺少一个等号?请更新您的帖子并使用大括号。
-
是的,在我的代码中是正确的。返回 0 的 packetState 是要重新同步,而不是 1 是要重新同步。
-
@AlexeiLevenkov:
DataReceived在工作线程上被调用,所以这个问题绝对涉及多线程。在假设告诉 OP 如何改进他的问题之前,请检查您是否知道您在说什么。
标签: c# multithreading serial-port