Forum: PC-Programmierung STM32&USB: WinAPI


von Pepe (Gast)


Lesenswert?

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
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Pepe (Gast)


Lesenswert?

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?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Pepe (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Pepe (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von guest (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.