2010-11-20 2 views
2

Ich möchte Bytes über serielle senden und empfangen. Mein Empfänger sollte die Bytes asynchron erhalten. Ich habe das kleine Beispiel unten geschrieben, das scheinbar funktioniert, aber es hinterlässt ein ungeklärtes Gefühl.SerialPort-Klasse und DataReceived-Ereignis ... Bytes abrufen. Benutze ReadLine oder ReadExisting? Irgendwelche Beispiele?

  1. Sollte ich wirklich WriteLine, ReadLine verwenden? Wie es jetzt geschrieben ist, ist es möglich, dass der Code in der Ereignisbehandlungsroutine m_port_DataReceived für jedes einzelne Byte aufgerufen wird? Das war mein Verständnis der Veranstaltung "DataReceived"; vielleicht liege ich falsch. Blockiert ReadLine, bis ein Zeilenende-Zeichen angezeigt wird?

  2. Sollte ich irgendwie das Konstrukt "if (e.EventType == SerialData.Eof)" im Event-Handler verwenden? Sie können sehen, ich habe es auskommentiert. Ich habe es versucht und konnte es nicht zur Arbeit bringen. Wann würde man eine SerialData.Eof erwarten? Meine Idee war, dass ich warten konnte, bis alle Bytes vorhanden waren, bevor ich "ReadExisting" anrief. Die "if" -Anweisung wurde jedoch nie als wahr bewertet. Erzwinge, dass der Code zu ReadExisting weitergeleitet wird, hat jedoch alle Bytes korrekt gelesen.

  3. Im Allgemeinen, was ist der beste Weg, meinen Code einzurichten, um Bytes zu empfangen, die über die serielle Schnittstelle kommen? Der Absender sendet alle 125 ms kleine Bytes, sendet jedoch keine Sonderzeichen. Die Byte-Pakete sind zeitlich auseinander, so dass ich glaube, dass es kein Problem gibt, Pakete miteinander zu mischen. Mehr das Problem ist, "sobald Sie ein Byte sehen, lesen Sie alles, solange Sie eine sehr kurze Zeit warten, werden Sie alles bekommen". Angesichts dieses Szenarios gibt es einen bevorzugten Weg?

Vielen Dank im Voraus, Dave

public class SerialPortController 
{ 
    SerialPort m_port; 

    public SerialPortController(bool server) 
    { 


     if (server) 
     { 
      m_port = new SerialPort("COM4"); 
      m_port.BaudRate = 115200; 
      m_port.Open(); 
      byte[] sillyBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      string output_string = encoding.GetString(sillyBytes); 
      m_port.WriteLine(output_string); 
      //m_port.Write(sillyBytes, 0, 8);     
     } 
     else 
     { 
      m_port = new SerialPort("COM5"); 
     m_port.DataReceived += new SerialDataReceivedEventHandler(m_port_DataReceived); 
      m_port.BaudRate = 115200; 
      m_port.Open(); 
     } 
     int character = Console.Read(); 
    } 

    void m_port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     //if (e.EventType == SerialData.Eof) 
     { 
      // string answer = m_port.ReadExisting(); 
      string answer = m_port.ReadLine(); 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      byte[] byte_answer = encoding.GetBytes(answer); 

     } 
    } 
} 
+0

Unter der Annahme, dass die Eigenschaft ReceivedBytesThreshold = 1, (was der Standard ist, und es scheint nicht, dass Sie es geändert haben), dann ist die DataReceivedEvent wird ausgelöst, wenn es mindestens 1 Byte zu empfangen. Es kann mehr geben. Dies ist * nicht * dasselbe wie das Ereignis, das für * jedes * empfangene Byte ausgelöst wird. Es bedeutet, dass wenn es feuert, es mindestens 1 Byte gibt. – Andy

+0

Der Ansatz, den ich immer ohne Problem verwendet habe, besteht darin, die Daten als Bytearray zu lesen, wenn der DataRcvd-Handler ausgelöst wird. Ich schiebe diesen Puffer von Byte-Array in eine Warteschlange. Wenn ich die Daten brauche, teile ich sie wieder zusammen und benutze sie/konvertiere sie ... Abhängig von der Anwendung mache ich einen der folgenden Schritte: 1 - Der DataRcvd-Handler löst ein Ereignis im UI-Thread aus; 2 - Verwenden Sie einen Timer; 3 - Der DataRcvd-Handler ruft eine Methode im UI-Thread auf. – dbasnett

Antwort

2

und wurde leider Beispiel bei MSDN die einfache Verwendung dieser zeigt.

Und es verwendet ReadExisting anstelle von ReadLine.

Auch aus der Dokumentation:

Das DataReceived Ereignis garantiert nicht empfangen wird für jedes Byte erhöht werden. Verwenden Sie die BytesToRead-Eigenschaft, um zu bestimmen, wie viel Daten im Puffer noch gelesen werden müssen.

private static void DataReceviedHandler(
        object sender, 
        SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    string indata = sp.ReadExisting(); 
    Console.WriteLine("Data Received:"); 
    Console.Write(indata); 
} 
+0

Danke, das hat es aufgeräumt! – Dave

+0

Ich habe dies getan, aber der Handler reagiert nicht gut. Für jeden Datenempfang erkennt es nur etwa 1 von 10 empfangenen Daten. Weißt du, warum? –

+0

@ConradC Nicht sicher .. aber Sie sagen, dass Ihr Ereignis auf Trigger 1/10 mal, und wenn Sie das ReadExisting lesen, fehlen Ihnen Daten? Könnte es sein, dass du einen zu kleinen Puffer hast? http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readbuffersize(v=vs.110).aspx –

Verwandte Themen