【问题标题】:Stop to wait for a packet from serial port停止等待来自串口的数据包
【发布时间】:2012-11-26 22:43:08
【问题描述】:

我通过串行端口定期接收一些数据,以便绘制它并做更多的事情。为了达到这个目的,我将数据从我的微控制器发送到我的计算机,并带有一个标头,它指定了每个数据包的长度。

除了最后一个细节外,我的程序运行良好且运行良好。当标头指定长度时,我的程序在达到该字节数之前不会停止。因此,如果由于某种原因,丢失了一个数据包中的某些数据,程序将等待并获取下一个数据包的开头......然后开始真正的问题。从那一刻起,一切都失败了。

我想过每 0.9 秒增加一个计时器(包每秒来一次),它会发出命令以返回等待并重置变量。但我不知道该怎么做,我试过但在运行时出现错误。由于 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# 方面的新手,所以请宽容!非常感谢你

【问题讨论】:

  • ** 因此,如果由于某种原因丢失了一个数据包中的某些数据**:您可能想在开始规避之前解决问题?为什么数据丢失? µC 没有发送它,或者您的应用出于某种原因丢弃了它?
  • 如果我是真的,那是因为我在强迫这种情况,发送错误的数据包(指定的长度比真实的长)。我从来没有错过一个数据包或一个字节。但这是实现GPRS应用的第一步,丢失数据的概率会增加。我首先通过串口测试程序,但我需要一个强大的程序,能够面对这类问题

标签: c# timer serial-port


【解决方案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
}

在开始时重新启动秒表并检查每个 while 循环中的时间,如果超时则中断(并清理)。即使您只期望几个字节,900 毫秒也可能太多了。 Com 流量非常快 - 如果您没有立即获得全部内容,它可能不会出现。

我喜欢在通信协议(如 [CR] 等)中使用终止字符。这使您可以阅读直到找到终止字符,然后停止。这可以防止读入下一个命令。即使您不想使用终止字符,也可以将代码更改为以下内容:

 while (IndCom < PacketLength)
 {
     if (serialPort.BytesToRead > 0) 
     {
         BuffCom[IndCom] = (byte)this.serialPort.ReadByte();
         IndCom++;             
     }
  }

它允许您在达到数据包大小时停止,将所有剩余字符留在缓冲区中以供下一轮通过(即:下一个命令)。您也可以在上面添加秒表超时。

关于终止字符的另一个好处是您不必提前知道数据包应该多长时间 - 您只需阅读直到到达终止字符,然后在获得后处理/解析整个内容它。它使您的两步端口读入一步端口读。

【讨论】:

  • 我已经尝试使用秒表并且它可以工作(我必须补充一点,不仅需要在经过时间时休息,还可以重置 IndCom 和其他变量),但效果很好 :) 谢谢非常J...
  • 我也在尝试做同样的事情,已经发布了一个问题here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多