2017-01-26 5 views
0

Ich habe ein seltsames Dilemma, wenn es um den seriellen Port geht. Ich sende eine Reihe von Befehlen an ein Gerät mit einem Mikrocontroller und bekomme Antworten zurück. Ziemlich typisches Zeug. Wie auch immer, ich stoße auf ein Problem, bei dem, wenn ich einen Befehl sende, der DataReceived Event Handler antwortet, aber das Problem ist, dass ich nicht alle Daten von ihm zurückbekomme. Daher wird der DataReceived Event Handler viermal aufgerufen.C# - SerialPort Receive erhält nicht alle Daten auf einmal

Anstatt also so etwas wie diese zu bekommen:

0 - 2:16:38 PM: 126 23 100 69 0 0 99 3 225 2 203 2 174 2 179 2 125 93 3 15 3 
0 0 0 15 255 0 214 12 105 15 33 15 33 15 13 15 54 15 39 5 68 4 197 5 199 5 57 
5 0 0 0 134 225 
1 - 2:16:38 PM: 126 23 100 69 0 0 99 3 226 2 203 2 174 2 179 2 125 93 3 16 3 
0 0 0 15 255 0 224 12 105 15 23 15 33 15 2 15 74 15 39 5 58 4 197 5 198 5 57 
5 0 0 0 65 163 
2 - 2:16:38 PM: 126 23 100 69 0 0 99 3 226 2 202 2 174 2 178 2 125 93 3 15 3 
0 0 0 15 255 0 214 12 95 15 23 15 33 15 23 15 105 15 39 5 58 4 197 5 198 5 57 
5 0 0 0 63 128 

Der Code wie folgt endet (nicht exakt, sondern ein Beispiel zu geben):

0 - 2:16:38 PM: 126 23 100 69 0 0 99 3 225 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 - 2:16:38 PM: 2 203 2 174 2 179 2 125 93 3 15 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0    
0 - 2:16:38 PM: 15 255 0 214 12 105 15 33 15 33 15 13 15 54 0 0 0 0 0 0 0 0 0 
0 - 2:16:38 PM: 15 39 5 68 4 197 5 199 5 57 5 0 0 0 134 225 0 0 0 0 0 0 0 0 0 

Wenn die erste Datenleitung 4 Ereignis Anrufe nimmt anstelle von 1. Ich gehe davon aus, dass der Mikrocontroller immer noch Daten aussendet, da ich alle meine Schreibdaten auf einmal sende. Aber ich hoffe, dass es eine Möglichkeit gibt, es zu kontrollieren, damit ich nicht alle diese Ereignisaufrufe bekomme (weil ich es vorziehe, das Byte-Array in ein einzelnes Array anstelle von Blöcken zu bekommen).

Dies ist alles von Visual Studio 2010 programmiert, aber ich kann 2013 in die Hände bekommen, wenn es sein muss. Hier ist der Beispielcode ich verwenden, um ähnliche Ergebnisse zu oben (ich bin mir bewusst, über die Datei Stream schließt nicht, wenn sie mit dieser Arbeit, aber ich bin nur mit dem Hauptcode als Beispiel):

namespace SerialCommunicationsTest 
{ 
    class Program 
    { 
     static UInt64 count = 0; 
     static SerialPort port; 
     static System.IO.StreamWriter file; 
     static void Main(string[] args) 
     { 
      file = new System.IO.StreamWriter(@"C:\Users\li\Desktop\Serial.txt"); 
      port = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One); 
      port.Handshake = Handshake.None; 
      port.Open(); 

      port.ReadTimeout = 400; 
      port.WriteTimeout = 400; 
      byte[] output = { 0x7E, 0x64, 0x17, 0x01, 0x45, 0x40, 0xFA, 0x7E }; 
      port.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived); 
      /* Loop, send message, and have event handler handler handle incoming event */ 
      while (count < UInt64.MaxValue) 
      { 
       port.Write(output, 0, output.Length); 
      } 

      return; 
     } 
     static void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 

      SerialPort port = (SerialPort)sender; 
      byte[] test = new byte[256]; 

      try 
      { 
       string data2 = ""; 
       port.Read(test, 0, 256); 
       for (int i = 0; i < 60; i++) 
       { 
        data2 += test[i] + " "; 
       } 
       string writeOut = count + " - " + DateTime.Now.ToString("h:mm:ss tt") + ": " + data2; 
       Console.WriteLine(writeOut); 
       file.WriteLine(writeOut); 
       count++; 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.StackTrace); 
      } 

     } 
    } 
} 
+2

Dies ist das erwartete Verhalten oder 'Read' die Funktion gibt einen Grund, einen' int'. –

+0

Gibt es eine Möglichkeit, die gesamte Antwort zurück zu erhalten, ohne dass mehrere DataReceived Event Calls bearbeitet werden müssen: Oder muss ich eine Art Terminierungssequenz erstellen? – ThatGuyNo

+1

Sie müssen Nachrichtenfragmente selbst wieder zusammensetzen. –

Antwort

1

Es ist Ihre Verantwortung, mehrere Leseaufrufe zu einer einzigen "Nachricht" zusammenzustellen. Wenn Sie die feste Nachrichtenlänge kennen, können Sie Read immer wieder aufrufen, bis Sie alle Bytes gelesen haben, um eine byte[] zu füllen, dann übergeben Sie dieses Array an die anderen Funktionen.

const int MessageSize = 256; 
    byte[] test = new byte[MessageSize]; 
    int offset = 0; 


    static void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 

     SerialPort port = (SerialPort)sender; 
     try 
     { 
      offset += port.Read(test, offset, MessageSize - offset); 

      if(offset == MessageSize) 
      { 
       string data2 = ""; 
       for (int i = 0; i < 60; i++) 
       { 
        data2 += test[i] + " "; 
       } 
       string writeOut = count + " - " + DateTime.Now.ToString("h:mm:ss tt") + ": " + data2; 
       Console.WriteLine(writeOut); 
       file.WriteLine(writeOut); 
       count++; 
       offset = 0; 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.StackTrace); 
     } 

    } 
+0

Wie wäre es im Falle einer nicht festen Nachrichtengröße Antwort? Die Nachricht wird von zwei Bytes von 0x7e gebündelt. Also muss ich annehmen, dass ich den Code bekommen kann, um diese zweite 0x7e zu sehen, dann höre die Übertragung auf? – ThatGuyNo

+0

Ja, das System heißt "Message Framing", [normalerweise werden Sie Tutorials für TCP/IP sehen] (http://blog.stephencleary.com/2009/04/message-framing.html) aber serielle hat die Genau dieselben Einschränkungen und das Folgen eines TCP/IP-Tutorals erhalten Sie die Informationen, die Sie benötigen. –

+0

Tun Sie dies nicht, Sie haben mehrere 'DataReceived'-Handler, die gleichzeitig um die Fragmente kämpfen, und eine Race-Bedingung, wenn Sie sie zum Puffer hinzufügen. Komplette Katastrophe. –

0

Try this:

List<byte> dataBuffer = new List<byte>(); 
byte[] tempBuff; 
var bytesReaded = pt.Read(inBuff, 0, inBuffSize); 
while (bytesReaded > 0) 
{ 
    tempBuff = new byte[bytesReaded]; 
    Array.Copy(inBuff, tempBuff, bytesReaded); 
    dataBuffer.AddRange(tempBuff); 
    bytesReaded = pt.Read(inBuff, 0, inBuffSize); 
} 
Verwandte Themen