2010-06-01 2 views
5

Ich habe einen SerialDataReceivedEventHandler mit einem formularbasierten Programm in VS2008 Express eingerichtet. Meine serielle Schnittstelle eingerichtet ist, wie folgt:C# .Net Serial DataReceived Ereignisantwort zu langsam für High-Rate-Daten

115200, 8N1

DTR und RTS aktiviert

ReceivedBytesThreshold = 1

Ich habe ein Gerät, mit denen ich in einem BlueTooth bin eine Schnittstelle, USB-Seriell . Hyper Terminal empfängt die Daten bei jeder Datenrate in Ordnung. Die Daten werden regelmäßig in 22 Byte langen Paketen gesendet. Dieses Gerät verfügt über eine einstellbare Rate, mit der Daten gesendet werden. Bei niedrigen Datenraten, 10-20 Hz, funktioniert der folgende Code sehr gut, keine Probleme. Wenn ich jedoch die Datenrate nach 25 Hz erhöhe, fängt es an, mehrere Pakete bei einem Anruf zu empfangen. Was ich damit meine, ist, dass es für jedes eingehende Paket einen Ereignisauslöser geben sollte. Bei höheren Ausgaberaten habe ich die Puffergröße (Befehl BytesToRead) sofort beim Aufruf des Ereignisses getestet und es liegen dann mehrere Pakete im Puffer vor. Ich denke, dass das Ereignis langsam ausgelöst wird und bis es den Code erreicht, haben mehr Pakete den Puffer getroffen. Ein Test, den ich mache, ist, wie oft das Ereignis pro Sekunde ausgelöst wird. Bei 10Hz bekomme ich 10 Event Trigger, super. Bei 100Hz bekomme ich so etwas wie 40 Event Trigger, nicht gut. Mein Ziel für die Datenrate ist 100 Hz ist akzeptabel, 200 Hz bevorzugt und 300 Hz optimal. Dies sollte funktionieren, weil selbst bei 300 Hz, das sind nur 52800 Bit/s, weniger als die Hälfte der eingestellten 115200 Baudrate. Alles, was ich über schaue?

public Form1() 
    { 
     InitializeComponent(); 
     serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);    
    } 


    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     this.Invoke(new EventHandler(Display_Results)); 
    } 


    private void Display_Results(object s, EventArgs e) 
    { 
     serialPort1.Read(IMU, 0, serial_Port1.BytesToRead); 
    } 

Antwort

3

Warum rufen Sie() den Aufruf von DisplayResults auf?

Dies wird es auf die MessageLoop, eine unnötige Verzögerung schieben.

Es wäre besser, wenn DataReceived() Daten in eine (threadsichere) Warteschlange für entkoppelte Verarbeitung schob.

Ich denke auch, dass Sie Probleme mit geteilten Paketen haben könnten.

+0

Ich habe versucht, den Invoke() - Aufruf zu entfernen und die Daten direkt im DataReceived() - Ereignis mit den gleichen Ergebnissen zu lesen. Tut mir leid, ein wenig naiv zu sein, aber könnten Sie mir mehr darüber erzählen, wie Sie die Warteschlange machen und warum das schneller geht. Danke für die Hilfe. – Matthew

1

Sie konnte versuchen ReceivedBytesThreshold = 22 Einstellung, die im Falle führen wird gefeuert, wenn es mindestens 22 Bytes zu lesen sind. Beachten Sie, dass es mindestens 22. Es kann mehr sein.

Ich denke nicht, dass ich das persönlich tun würde, denn was passiert, wenn sich Ihre Paketgröße in der Zukunft ändert, zum Beispiel auf 12 Bytes? Sie würden mit 12 Bytes im Puffer enden, aber das Ereignis überhaupt nicht auslösen.

Viel besser, lassen Sie es auf 1 gesetzt, die das Ereignis ausgelöst wird, wenn mindestens 1 Byte verfügbar ist. Dann push alle empfangenen Bytes in eine Liste oder eine Warteschlange, wie Henk bereits gepostet hat.

Beachten Sie, dass das DataReceivedEvent keine Kenntnis darüber hat, was Sie für ein Datenpaket halten. Es wird nur ausgelöst, wenn Bytes verfügbar sind. Es ist Aufgabe des Entwicklers, diese Bytes zu einer sinnvollen Nachricht oder einem Paket zusammenzufassen.

4

Haben Sie versucht, die Zeitverzögerung auf dem USB-Seriell-Konverter zu justieren? Ich hatte das gleiche Problem mit einem FTDI USB zu Seriell Konverter. Ich benutze ein Oszilloskop, um meine IN- und OUT-Daten von dem Gerät zu sehen, und ich konnte sehen, dass der Computer immer langsam reagierte. Standardmäßig ist die Zeitverzögerung auf dem Gerät auf 16 ms eingestellt. Ich habe es auf 2 ms geändert und es macht einen großen Unterschied. Gehen Sie im Gerätemanager zu Ihrem USB Serial Converter und ändern Sie in den erweiterten Einstellungen die Latenzzeit auf 2 ms. Es sollte funktionieren.Versuch es.

+1

Irgendeine Idee, warum eine "16ms" -Latenz in Hunderte von Millisekunden zwischen Bündeln von empfangenen Daten übersetzt? – supercat

0

Das Problem liegt in der empfangenen Datenhandler.

Ich lief einen separaten Thread mit einer while(true) Schleife und serial.ReadLine(), alles funktioniert perfekt.

using System.Threading; 

Thread readThread = new Thread(Read); 
readThread.Start(); 

Hoffe jemand anderes muss nicht 3 Stunden damit verbringen, dies zu beheben.