2012-11-26 79 views
2

我通過串行端口定期接收一些數據,以便繪製它並做更多的工作。爲了達到這個目的,我將數據從我的微控制器發送到我的電腦,並帶有一個標題,它指定了每個數據包的長度。停止等待來自串行端口的數據包

我有程序運行和工作完美,除了最後一個細節。當標題指定長度時,我的程序不會停止,直到它達到該字節量。因此,如果出於某種原因,某個數據包的某些數據丟失了,程序就會等待並開始下一個數據包......然後開始真正的問題。從那一刻起,每一次都失敗了。

我曾想過每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

**因此,如果出於某種原因,某個數據包中的某些數據錯過了**:在開始規避它之前,您可能想要解決該問題?爲什麼數據缺失? μC不會發送它,或者您的應用程序由於某種原因而丟棄它? – igrimpe

+0

如果我是真的,那是因爲我強迫這種情況發送錯誤的數據包(指定的長度比實際長)。我從來沒有錯過一個數據包或單個字節。但這是實施GPRS應用的第一步,丟失數據的可能性會增加。 我正在通過串行端口測試程序,但我需要一個強大的程序,能夠面對這種問題 – Ger

回答

0

什麼你可能做的是使用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循環,然後爆發(和清理),如果超時命中。如果你只需要幾個字節,那麼900ms可能太多了。 Com交通速度非常快 - 如果你沒有立即得到整個事情,它可能不會來。

我喜歡在通信協議中使用終止字符(如[CR]等)。這允許您閱讀,直到找到終止字符,然後停止。這可以防止讀入下一個命令。即使你不想使用終止字符,改變你的代碼是這樣的:

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

它允許你停止,當你達到你的數據包大小,留下剩餘的字符緩衝區,爲下一輪通過(即:下一個命令)。您也可以在上面添加秒錶超時。

關於終止字符的另一個好處是,您不必事先知道數據包應該多長時間 - 您只是閱讀,直到您到達終止字符,然後處理/解析整個事情得到它了。它使您的兩步端口讀入一步式端口讀取。

+0

我試過用秒錶,它的工作原理(我不得不補充說, timeelapsed是必要的,也重新設置IndCom和其他變量),但它很好地工作:) 非常感謝你J ... – Ger