2014-11-03 15 views
1

我正在從串行儀器獲取數據以繪製圖表。數據流爲230 kbps,串行流水線少於50%,數據到達大約100 kbps,實際上並沒有真正變化,速率或數量。使用我的串行接收方法發生數據錯誤

在同一臺計算機上使用了像Teraterm這樣的串行終端程序;我可以捕獲數據並證明數據的來源以及測試接收方法都很好,並且我看不到捕獲數據的錯誤。

我正在開發的Windows窗體應用程序丟失數據。我已經從接收,捕獲(並行),解析和繪圖,直到接收和捕獲。並且發現我仍然看到捕獲中丟失的數據。

我不是一個經驗豐富的Windows人員,因此可能不知道有更好的方法來完成相同的功能。以下是我正在執行的接收操作:

我正在使用System.IO.Ports.SerialPort類。 我通過修改.DataReceived事件:

+= new SerialDataReceivedEventHandler(comPort_DataReceive); 

然後我調用open()方法。

注意:我可能在這裏做了一些不正確的事情,我從來沒有在任何時候用 - =清除.DataReceived事件,而是每次打開時都會再次添加事件。儘管如此,即使我只與港口談過一次,也會出現這些問題。

這是我的數據接收函數的代碼。 RxString是一個字符串。

private void comPort_DataReceive(object sender, SerialDataReceivedEventArgs e) 
    { 
     RxString = comPort.ReadExisting(); 
     this.Invoke(new EventHandler(ParseData)); 
    } 

    private void ParseData(object sender, EventArgs e) 
    { 
     // Save to capture file, if capture is enabled 
     if ((WriteToFileEnabled == true) && (WriteToFileName != null)) 
     { 
      writeFileHandle.Write(RxString); 
     } 
     return; 
     // Previously would parse and plot data 
    } 

那麼,在這種情況下,人們如何執行接收而不會丟失它?

請按照下列問題進行操作:串行接收的緩衝區有多大,或者如果我有一個相當敏感的應用程序,我需要擔心這個問題嗎?流量控制無關緊要,遠程設備無論發送什麼內容都將發送數據,因此取決於我的計算機採取這些數據並對其進行處理或忽略。但是,如何知道我是否丟失了數據或經驗豐富的錯誤和內容? (我問最後一個沒有在SerialPort類結構上搜索太多,對不起。)

+0

您如何確定數據正在丟失?數據丟失是否存在任何模式? – 2014-11-03 20:05:33

+0

230kbps對串行端口來說非常快速...如果您處於電子噪聲環境中或正在使用粘連電纜,您可能很容易遇到數據損壞。如果發送設備允許,嘗試減小到9600baud,並確保一切工作在加速之前。奇偶校驗錯誤會引發異常。如果您在協議中沒有使用奇偶校驗,並且您沒有使用握手協議,那麼確實無法保證您獲得了所有數據或正確獲取了數據。 – 2014-11-03 20:40:00

+0

Invoke()調用非常麻煩,UI線程需要一段時間才能響應。特別是如果你「解析並繪製」,那肯定會是一個嚴重的消防軟管問題。當你調用Close()時,也很容易死鎖你的程序。通過實現SerialPort.ErrorReceived事件來檢測溢出錯誤。在調用BeginInvoke()之前收集數據,確保您的UI線程能夠跟上。 – 2014-11-04 13:15:04

回答

3

讓我們假設你的設備發送長度爲85個字節的消息。 DataReceive事件處理程序可能會或可能不會觸發一次以接收這85個字節。由於它可能會觸發不止一次,您的代碼必須解決這個問題。 DataReceive事件處理程序應該讀取可用的字節並將它們附加到稍後處理的緩衝區中。

此外,SerialPort類提出的事件中只有一個可以一次執行。在這個例子中,假設處理程序必須啓動三次才能接收85個字節。在處理第一部分時,另外兩部分不能執行。如果在處理第一部分其他事件時需要PinChanged或ErrorReceived,它們也不能執行。

我的第一次使用SerialPort類的兩個經驗是9600 bps終端和1 Mbps藍牙設備。對於速度較慢的產品而言,效果並不理想,但當我想出如何讓速度更快時,速度較慢的產品可能會使用相同的方法。

我的方法:

  1. 打開串口之前,我開始在做一個循環中運行其他兩個後臺線程。第一個(Receive)從串口讀取所有可用的字節,將它們添加到緩衝區,並在每次讀取時發送第二個線程。第二個(協議)確定是否有完整的消息到達,是否有字節到字符串轉換,更新UI等。根據應用程序,我可能會啓動第三個處理錯誤和引腳更改的線程。所有這些線程都受Threading AutoResetEvent限制。

  2. 我的DataReceive事件處理程序中有一行,在AutoResetEvent上設置了一個限制接收的Set。

一個VB的例子可以在這裏找到SerialPort Methodology。自採用這種方法以來,我沒有遇到任何似乎困擾其他SerialPort用戶的問題,並且以高達2Mbps的速度成功使用了它。

+0

謝謝,我會看看這個例子,並期望它可以沿着正確的方向來幫助我。鑑於今天的其他活動,我的猜測是,我需要一天左右的時間才能解決這個問題並做一些實驗,但如果最終解決或導致進一步的問題,我會發布後續行動。 – rtm 2014-11-04 19:05:33

+0

利用線程將接收入口與接收解析分開,並進一步從數據表示的策略是解決方案的正確方向。 – rtm 2014-11-06 15:47:46

相關問題