Hallo zusammen, ich würde gerne in Visual Studio (C#) eine Software erstellen die über die Serielle Schnittstelle (RS485/ModBus) nach einem Klick auf den entsprechenden Button im sekundentakt Daten vom Slave abfragt und ausgibt. Hier komme ich nicht weiter. Ich habe es mit einem Timerevent probiert aber dann kann ich nichts mehr in dem Programm machen (noch nicht einmal schließen). Die Abfrage und die Ausgabe ist kein Problem. Das einzige Problem das ich habe ist dies jede Sekunde zu machen und ich trotzdem noch das Programm bedienen kann. Ich hoffe ihr könnt mir da weiter helfen.
Nimm einen BackgroundWorker und starte den bei Klick auf den Button und öffne in der DoWork des BackgroundWorkers den SerialPort und lese da im Sekundentakt raus. Wenn SerialPort.Read...-Funktionen blockieren wirkt es sich dann nicht direkt auf die Oberfläche aus, weil es dann unabhängig dazu parallel ausgeführt wird. Vom BackgroundWorker aus z.B. via dessen .ReportProgress() für die UI relevante Infos zurück ans UI übermitteln (z.B. um was vom SerialPort empfangenes in einer Textbox hinzuzufügen) (Aktuell hängt vermutlich der Code in deinem Timer-Event, weil z.B. eine dort aufgerufene .Read-Methode des SerialPort-Objekts blockiert, weil sie auf Daten wartet)
a) serielle Schnittstellen haben beinen Puffer (in den Systemeinstellungen konfigurierbar), da muss man nicht auf jedes einzelne Zeichen warten oder Angst haben, etwas zu verpassen (sofern man nicht allzulange wartet). Dieser Puffer ist üblicherweise irgendwas zwischen 32Byte und 4k groß ... b) ich kenne zwar speziell C# nicht, aber in C++ gibts die Funktion Serial.available(). Die liefert die Anzahl der Zeichen im Puffer bzw. ein true/false, je nachdem, ob etwas da ist - damit wäre ein Polling recht schnell zu erledigen. Sollte mit C# auch machbar sein. c) das Abfragen, Auslesen und Verarbeiten kann man auch in einen Thread packen, dann sollte der Rest der App oder zumindest die GUI problemlos weiterlaufen (nennt man "Nebenläufigkeit") d) man kann mit dem Empfang der seriellen Schnittstelle auch einen Interrupt verknüpfen, dann muss man auch nicht pollen e) in Javascript gibts "Promises", so eine Art scharf gemachter Einmal-Thread, derauf ein Ereignis (meist die Antwort auf einen AJAX-Request) wartet. Sollte es das in C# nicht auch irgendwie geben?
Frank E. schrieb: > b) ich kenne zwar speziell C# nicht, aber in C++ gibts die Funktion > Serial.available(). Die liefert die Anzahl der Zeichen im Puffer bzw. > ein true/false, je nachdem, ob etwas da ist - damit wäre ein Polling > recht schnell zu erledigen. Sollte mit C# auch machbar sein. Es gibt in .net SerialPort.BytesToRead. Jedoch sollte man in folgende Informationen beachten: https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport Das .BytesToRead eher schlecht funktioniert habe ich auch schon erfahren müssen. Vom DataRecieved Event ganz zu schweigen. Hardware mit USB-Uart IC's (z.b. FT232 oder ähnlich) haben bei mir mit dem .Net SerialPort mehr Probleme bereitet(insbesondere ein USB-Rs485 Adapter mit Profilic IC), wie das benutzen der USB Schnittstelle von ARM Controllern. Bei Lesen von Daten kommen diese oft mit Verzögerung, falsch oder garnicht an. Das senden von Daten funktionierte jedoch mit dem .Net SerialPort. Da die selbe Hardware mit Programmen die nicht in .Net geschrieben sind einwandfrei funktioniert, kann ich die im Link gennanten Probleme bestätigen.
DataReceivedHandler ist auch noch ein Stichwort das mit den bereits genannten Mitteln helfen kann
:
Bearbeitet durch User
Christian B. schrieb: > Das .BytesToRead eher schlecht funktioniert habe ich auch schon erfahren > müssen. Vom DataRecieved Event ganz zu schweigen. Unsinn. Benutze ich seit Jahrzehnten und funktioniert ganz hervorragend. Und zwar genau in dieser Kombination. Sprich: Im Eventhandler wird mit BytesToRead erfragt, wieviel zu lesen sind und genau diese Zahl wird dann auch gelesen. Man muss sich halt nur im Klaren darüber sein, dass der Eventhandler nicht im Kontext des GUI-Threads läuft und die entsprechenden Maßnahmen treffen, wenn man die Daten in eben jenem benötigt...
Es gibt da schon diverse Fallstricke, je nachdem wie man die Daten ausliest. z.B. (aus der Doku zu ReadExisting): "The SerialPort class buffers data, but the stream object contained in the SerialPort.BaseStream property does not. Therefore, the SerialPort object and the stream object might differ on the number of bytes that are available to read. When bytes are buffered to the SerialPort object, the BytesToRead property includes these bytes in its value; however, these bytes might not be accessible to the stream contained in the BaseStream property." je nachdem wie man dann ausliest kann man da schon leicht ungewollt den Thread blockieren. Ich nehme immer einen BackgroundWorker/Thread und lese da einfach in Schleife via .Read() (Byte-Variante) aus. Das funktioniert bislang immer zuverlässig.
Christian B. schrieb: > Bei Lesen von Daten kommen diese oft mit Verzögerung, Das ist korrekt. Christian B. schrieb: > falsch oder garnicht an. Das ist mir neu.
bluppdidupp schrieb: > Ich nehme immer einen BackgroundWorker/Thread Kann man machen, ist aber überflüssig, da der SerialPort selber einen Thread für das Lesen erzeugt (übrigens auch schon unnötigerweise, denn er benutzt selber wiederum das asynchrone File-API, was seinerseits auch bereits einen Lesethread erzeugt). Du sattelst also auf bereits zwei Threads nochmal einen drauf... Zwei der drei sind eigentlich schlicht über, ganz sicher aber der dritte...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.