我通过串口定期收到一些数据,以便绘制它并做更多的事情。为了达到这个目的,我将数据从微控制器发送到我的计算机,并带有一个标题,用于指定每个数据包的长度。
除了最后一个细节之外,我让程序运行并且工作正常。当标题指定长度时,我的程序将不会停止,直到达到该字节数。因此,如果由于某种原因,错过了一个数据包的某些数据,程序会等待并开始下一个数据包...然后开始真正的问题。从那一刻起,每一次都失败了。
我想过每隔0.9秒就会上升一次Timer(包裹每秒钟一次),他们会给出一个命令以便回来等待并重置变量。但是我不知道该怎么做,我试过但是跑步时我得到了错误。由于IndCom(参见下一个代码)在某些函数和错误的重要位置重置,因为“索引越界”出现了。
我附上我的代码(没有计时器)
private void routineRx(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
int BytesWaiting;
do
{
BytesWaiting = this.serialPort.BytesToRead;
//Copy it to the BuffCom
while (BytesWaiting > 0)
{
BuffCom[IndCom] = (byte)this.serialPort.ReadByte();
IndCom = IndCom + 1;
BytesWaiting = BytesWaiting - 1;
}
} while (IndCom < HeaderLength);
//I have to read until I got the whole Header which gives the info about the current packet
PacketLength = getIntInfo(BuffCom,4);
while (IndCom < PacketLength)
{
BytesWaiting = this.serialPort.BytesToRead;
//Copy it to the BuffCom
while (BytesWaiting > 0)
{
BuffCom[IndCom] = (byte)this.serialPort.ReadByte();
IndCom = IndCom + 1;
BytesWaiting = BytesWaiting - 1;
}
}
//If we have a packet--> check if it is valid and, if so, what kind of packet is
this.Invoke(new EventHandler(checkPacket));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
我是面向对象编程和c#的新手,所以请高兴,请!非常感谢你
答案 0 :(得分:1)
您可能会使用Stopwatch.
const long COM_TIMEOUT = 500;
Stopwatch spw = new Stopwatch();
spw.Restart();
while (IndCom < PacketLength)
{
//read byte, do stuff
if (spw.ElapsedMilliseconds > COM_TIMEOUT) break; //etc
}
在开始时重新启动秒表并检查每个循环中的时间,然后在超时命中时突破(并清理)。如果你只想要几个字节,900毫秒可能太多了。交通流量非常快 - 如果你没有立即得到整个东西,它可能不会来。
我喜欢在通信协议中使用终止字符(如[CR]等)。这允许您阅读,直到找到终止字符,然后停止。这可以防止读入下一个命令。即使您不想使用终止字符,也可以将代码更改为以下内容:
while (IndCom < PacketLength)
{
if (serialPort.BytesToRead > 0)
{
BuffCom[IndCom] = (byte)this.serialPort.ReadByte();
IndCom++;
}
}
它允许您在达到数据包大小时停止,在缓冲区中留下任何剩余的字符用于下一轮(即:下一个命令)。您也可以在上面添加秒表超时。
关于终止字符的另一个好处是你不必事先知道数据包应该有多长时间 - 你只需阅读直到你到达终止字符,然后一旦你有了处理/解析整个字符它。它使您的两步端口读入一步式端口读取。