簡體   English   中英

SerialPort類問題

[英]SerialPort Class issues

我試圖讓串口接收正確的消息時遇到很多問題。 它不斷截斷消息。 這是我的代碼,我將嘗試在代碼之后詳細說明。

public SerialComms(SerialPort sp)
{
   this.sp = sp;
   this.sp.Open();
   this.sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

   do
   {
      Console.WriteLine("port open waiting message");
      Console.ReadKey();
   } while(!_terminate);

   this.sp.Close();
}

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   string dataReceived;
   StringComparer strComp = StringComparer.OrdinalIgnoreCase;
   SerialPort sp = (SerialPort)sender;
   int i = sp.BytesToRead;
   byte[] _byte = new byte[i];
   char[] _char = new char[i];
   sp.read(_byte, 0, i);
   dataReceived = Encoding.UTF8.GetString(_byte);
   //dataReceived = new string(_char);
   //dataReceived = sp.ReadExisting();

   if (strComp.Equals("00000000000000"), dataReceived))
      _terminate = true;

   Console.WriteLine(dataReceived);
}

現在我有一個測試項目,我們用它來測試生產中使用傳統軟件的串行com-我知道這樣運行正常。 我已經將一個串行監視器連接到端口,並且通過傳輸發送的消息沒有任何問題。 當我第一次發送消息如012345678901234時,它通常會很好,在接收端,顯示器顯示它通過; 但是,當它打印到控制台時,它會在第一條消息后被截斷。 我在端口監視器和控制台輸出上附加了消息的屏幕截圖(顯示的笑臉和心臟是正在轉換的前綴字節 - 為什么它是一個心臟和笑臉我不知道)

好的,所以我不能發布圖片,因為我沒有足夠的聲譽這樣做。 我將在下面的控制台中寫出輸出的內容(在這種情況下由於某種原因它也截斷了第一條消息:()

在串口監視器上,正在傳輸的消息如下(我發送了三次,每次消息發送之間有幾秒的延遲時間):
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234。
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234。
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234。

在控制台上我收到以下內容(☺和♥字符是02和03,它們是STX和ETX消息,是我們傳輸的標准信息):
☺123456
78901234♥

123
456
7890
123
4♥

123
456
7890
123
4♥

這個問題讓我發瘋! 請幫忙! 遺產是使用過時的MSCommLib,我們正在轉向.Net 4

這在任何通信協議中都是正常和常見的。 網絡上的TCP也具有此屬性。 字節作為流傳輸 ,而不是數據包。 因此,當您的DataReceived事件處理程序觸發時,您只知道您有一些可用的字節。 在處理之前,您需要將接收字節組合成完整的響應。

這需要一個協議 ,一種識別你得到完整響應的方法。 你有一個,那些STX和ETX字節告訴你。 特別是ETX,STX是一種過濾掉連接設備時可能獲得的噪聲字節的方法。

一個非常簡單的方法是將NewLine屬性設置為(char)3並調用ReadLine()。

更好的方法是過濾STX幫助您消除的噪音,同時避免死鎖情況:

private const int MaxResponse = 42;
private const int STX = 2;
private const int ETX = 3;
private byte[MaxResponse] response;
private int responseLength;

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   var sp = (SerialPort)sender;
   int cnt = sp.BytesToReceive;
   for (int ix = 0; ix < cnt; ++ix) {
       byte b = (byte)sp.ReadByte();
       if (responseLength == 0 && b != STX) continue;
       if (b != ETX) response[responseLength++] = b;
       else {
           var str = Encoding.ASCII.GetString(response, 0, responseLength);
           HandleResponse(str);
           responseLength = 0;
       }
   }
}

並編寫HandleResponse()方法來處理您收到的數據。

可能有兩個問題的組合。

首先,使用流時常見的錯誤是因為你從Read請求i字節並不意味着Read實際上會讀取那么多字節,這不太可能是你的問題,但是你應該知道它, 看看這個問題的答案是什么正確的模式

第二個問題是流是流,而不是消息。 它不知道您發送了☺12345678901234♥ ,它只知道它在上一次檢查和現在之間收到了☺123456 ,它應該向用戶報告該信息。

您需要修改您的讀取代碼以保持緩沖數據,直到它收到下一個然后獲取整個緩沖的字節數組並將其發送給用戶。 這就是沿線發送的全部原因,它允許接收器能夠檢測到它何時到達消息的開頭或結尾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM