Hallo. Ich bin gerade am Umsetzen eines alten Projektes von RS232 auf USB. Verwende dafür einen STM32 mit USB FS. Bisher wurde Windows-seitig immer auf eine Nachricht von der RS232 gepolled. Ich frag mich jetzt, ob man dies eleganter (z.B. per Windows Message) lösen kann. (Btw Win32, kein .Net.) Viele Dank Pepe.
:
Verschoben durch User
Das hängt wohl stark davon ab, über welchen Treiber du gehst. Das WinUSB-API für den WinUSB-Treiber unterstützt asynchrone Kommunikation ("Overlapped I/O"). Über libusb kann man das aber leider nicht nutzen; hier kann man sich mit Multithreading behelfen.
Die aktuelle Lösung ist Thread-basiert. Die will ich ja eigentlich nicht mehr. Overlapped I/O hab ich mir schon angesehen. Aber die Beschreibung hat mich eher abgeschreckt. Außerdem geht dies eigentlich nicht in die Richtung, die ich suche. Meine "normale" Kommunikation an mein USB Gerät kann synchron erfolgen. Der PC schickt einen Befehl raus, das Gerät antwortet sofort (<5ms). Dann passiert vielleicht für einige Sekunden erstmal wieder nichts vom PC aus. In dieser Zeit kann es aber vorkommen, dass das Gerät eine Message schickt (weil irgendwas eingetreten ist). In der aktuellen Lösung wird ständig gepolled, damit ich diese Ereignisse sofort mitbekomme. Also eigentlich bräuchte nur ein Event/Message/CallBack, dass mir mitteilt, dass was angekommen ist. Da erscheint mir - wenn ich es richtig verstanden habe - Overlapped I/O nicht das Richtige. Oder liege ich da falsch?
Pepe schrieb: > Da erscheint mir - wenn ich es > richtig verstanden habe - Overlapped I/O nicht das Richtige. Genauso funktioniert das aber unter Windows. Normale Win32-C-Programme kennen erstmal keine "Callbacks", "Events" oder "Messages". Stattdessen brauchst du in der main()-Funktion eine main-Schleife, die das Win32-API wiederholt nach eingetretenen Ereignissen abfragt; das geht über die WaitForMultipleObjects-Funktion. Diese kehrt zurück, sobald etwas passiert ist. Dies gilt z.B. für GUI-Ereignisse (Mausklicks, Fenster geschlossen), kann aber auch für I/O genutzt werden, indem man eben Overlapped I/O nutzt, sodass die Funktion auch zurückkehrt, wenn z.B. per USB Daten ausgetauscht wurden. Frameworks wie MFC kapseln das und rufen dir nach der Rückkehr direkt eine Funktion ("Callback") auf, was die Sache vereinfacht, aber das Grundprinzip nicht verändert. Wie behandelt deine Anwendung denn bisher asynchrone Ereignisse/Callbacks? Höchstwahrscheinlich sowieso (indirekt) über WaitForMultipleObjects. Das ganze ist aber wie gesagt stark vom bis jetzt nicht genannten Treiber abhängig.
Nicht über WaitForMultipleObjects. Sondern über ClearCommError wird abgefragt, ob Zeichen im Puffer stehen. Ansonsten bekomme ich die eingehenden Zeichen erst mit dem nächsten ausgehenden Befehl mit. Und das gefällt mir eben nicht. Ich hatte auf ein Event wie WM_DEVICECHANGE gehofft. Einfach in den EventHandler reinhängen und drauf reagieren. Dann werde ich wohl erstmal meinen Thread so umbauen, dass ich auch zwischen den Befehlen nach Zeichen im Puffer polle.
Pepe schrieb: > Ansonsten bekomme ich die > eingehenden Zeichen erst mit dem nächsten ausgehenden Befehl mit. Und > das gefällt mir eben nicht. Heißt das du wartest überhaupt nie? Dann musst du sowieso umbauen. Pepe schrieb: > Ich hatte auf ein Event wie WM_DEVICECHANGE gehofft. Einfach in den > EventHandler reinhängen und drauf reagieren. Fast genauso kannst du es machen. Du musst halt statt GetMessage dann (Msg)MsgWaitForMultipleObjects aufrufen.
Letzten Endes wartet mein Thread auf die Antwort. Aber in dem Thread werden noch andere Themen behandelt (z.B. weitere IOs). Also möchte ich keine blockierende Lösung mit WaitFor... Ich wollte eine elegantere Lösung finden.
Pepe schrieb: > Ich wollte eine elegantere Lösung finden. Wie stellst du dir das denn genau vor? Willst du nicht-blockierend abfragen ob schon was angekommen ist? Ein hypothetisches Äquivalent zu WM_DEVICECHANGE könntest du ja so auch nicht nutzen, denn dafür musst du mit GetMessage blockierend warten, oder ständig PeekMessage aufrufen. Am Elegantesten ist es eigentlich, auf alle I/O-Dinge per WaitForMultipleObjects zu warten. Wenn irgendwas fertig ist, reagierst du direkt darauf. So hast du nur diesen einzigen blockierenden Aufruf, der sich in einer Schleife befindet.
:
Bearbeitet durch User
Pepe schrieb: > Aber in dem Thread werden noch andere Themen behandelt (z.B. weitere > IOs). Also möchte ich keine blockierende Lösung mit WaitFor... Deswegen gibt es ja WaitForMultipleObjects. Das blockiert nicht, sondern kann auf diverse Events gleichzeitig warten, und man bekommt 'raus, welches Event eingetrudelt ist, um darauf passend reagieren zu können.
Rufus Τ. F. schrieb: > Deswegen gibt es ja WaitForMultipleObjects. Und WaitForSingleObjectEx/WaitForMultipleObjectsEx. In Verbindung mit I/O completion routines ist das dann auch eher einfach zu programmieren. Wenn man das Waitobject nicht noch für etwas anderes braucht, kann man dann acuh ganz darauf verzichten und SleepEx benutzen.
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.