Hallo,
ich verwende VB2008.net und möchte Daten vom SerialPort abfragen.
Leider hängt es und VB zeigt mir keinen Fehler an.
Die Komponente SerialPort habe ich auf der Oberfläche.
Kurzbeschreibung:
Wenn im SerialCom der Wert 1 vorhanden ist, soll Bild 1 auf der
Oberfläche angezeigt werden, bei Wert 2 wieder ausgeblendet und Bild 2
sichtbar werden. Der Wechsel findet alle ~5 - 10 Sekunden statt - im
WindowsTerminal kann ich die Werte empfangen (Com4).
Würde mich freuen, wenn sich jemand mein Code ansehen könnte
schon mal Danke
Micha
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
2
While (Daten > 4)
3
Daten = SerialPort1.ReadExisting
4
End While
5
End Sub
Vielleicht hängt's auch hier? Er sollte in dem EventHandler nur soviele
Daten lesen, wie auch wirklich da sind. Und nicht einfach immer weiter,
bis da zufällig mal was kleinergleich 4 rüber kommt.
Allgemein hast du da recht viele Schleifen drin, die schnell mal
unendlich lang werkeln. Wenn das unbedingt sein muss (nein, muss es
nie), dann bau da mal ein Application.DoEvents rein. Aber vermeide die
Schleifen lieber gleich.
Wie Lasse S. bereits schrieb, das mit dem
While (Daten > 4)
ist schlecht, "Sub SerialPort1_DataReceived" ist ja zumindest vom
Verständnis her eine Art Interruptroutine, die gibts zwar unter VB wie
Sand am Meer, aber in diesem Fall ist sie ja noch an eine echte externe
Hardware, nämlich den seriellen Port gebunden und solche Routinen sollte
man möglichst schnell abarbeiten und wieder verlassen, bevor sie erneut
aufgerufen werden.
Aber genau das macht "While (Daten > 4)" nicht, (was passiert z.B. wenn
gerade nur ein einziges Byte den "DataReceived"-Event ausgelöst hat?).
Du solltest die "SerialPort.BytesToRead"-Eigenschaft checken um
festzustellen wieviele Bytes sich gerade im Empfangspuffer des seriellen
Ports befinden wenn "DataReceived" ausgelöst wird.
Nachtrag: In der Regel wird "DataReceived" bereits nach einem
empfangenen Byte ausgelöst, muss aber nicht so sein, je nachdem was das
Betriebsystem gerade macht können es auch mal zwei, drei oder noch mehr
Bytes sein.
Hab den Code nun etwas verändert und siehe da es funktioniert.
Ich hatte noch einen weiteren Fehler und zwar wurde der SerialPort nicht
abgefragt.
Hier die abgeänderte Version:
Schön, dass es funktioniert. Übung macht den Meister. Nett gemeint! Aber
das ist leider noch lange nicht!
Zumindest vom reinen Ansatz her sogar noch schlechter als dein erster
Entwurf, weil du jetzt nur noch eine Schleife und keine Events mehr zum
Auslesen des seriellen Ports verwendest. Dein Programm hängt praktisch
in der "Loop Until Verbindung = 0"-Schleife fest und ohne
"Application.DoEvents()" würde vermutlich gar nichts mehr gehen, ganz
schlechter Stil!
Zudem ist gar nicht festgelegt was passieren soll, wenn
"SerialPort1.ReadExisting" zufällig mal mehr als 1 Byte liefert.
Dann bau lieber wieder alles in das "SerialPort1_DataReceived"-Event
ein. Im Prinzip ist es doch ganz einfach: "SerialPort1_DataReceived"
wird automatisch aufgerufen wenn der serielle Port etwas empfangen hat,
dann schaut man mit ....
Ok, ich gebs ja zu, es ist dann doch nicht ganz so einfach, wie es auf
den ersten Blick in die VS2008 Dokumentation ausschaut. Ich hab das
gestern einfach mal selber ausprobiert, das hat dann zwar auch gleich
irgendwie so funktioniert, wie ich mir das vorgestellt habe, aber halt
nur irgendwie. Unschöne Warnungen wegen "Threadübergreifender Zugriffe
auf eine Form" und eine ganz üble Exception beim Beenden des Programms
haut einem der VS2008 Compiler um die Ohren wenn man die Sache im
VB6-Stil angeht. Microsoft hat da für den Gelegenheits-VB-Programmierer
inzwischen doch ein paar Fußangeln ausgelegt.
Trotzdem, eines der wenigen schönen Beispiele für die Verwendung des
seriellen Ports unter VB2005/2008, ist hier zu finden:
http://www.activevb.de/tipps/vbnettipps/tipp0071.html
Schön deshalb, weil es in sehr kompakter Form:
- zeigt wie man das serielle Port-Control dynamisch erzeugt
- zeigt wie man die verfügbaren COM-Ports auflistet
- zeigt wie man nicht nur das "DataReceived"-Event behandelt sondern
auch alle anderen die mit dem COM-Port zu tun haben.
- auch die, inzwischen zum Leidwesen und Unverständnis vieler
VB-Gelegenheitsprogrammierer, notwendige "Thread-sichere"-Programmierung
am Beispiel einer Textausgabe, nicht unterschlägt
- scheinbar alles soweit richtig macht, dass es den Anwender auch nicht
mit der, recht häufig diskutierten "Der E/A-Vorgang wurde wegen eines
Threadendes oder einer Anwendungsanforderung abgebrochen."-Fehlermeldung
bzw. einer "System.IO.IOException" nerven muss.
Nach Durchsicht dieses Beispiels kann man dann vermutlich auch den Kauf
dieses Buches verzichten:
http://home.comcast.net/~hardandsoftware/books2.htm
Obwohl der Mann ja durchaus einiges von der Sache zu verstehen scheint,
seine "DesktopSerialIO.dll" hat jedenfalls in einem ersten Test schon
mal funktioniert:
http://home.comcast.net/~hardandsoftware/DesktopSerialIO.htm
Albrecht H. schrieb:
> Zudem ist gar nicht festgelegt was passieren soll, wenn> "SerialPort1.ReadExisting" zufällig mal mehr als 1 Byte liefert.
Naja, zufällig wird ja nichts versendet, denn mehr versende ich mit dem
Mikrocontroller nicht.
Mit dem anderen hast du schon Recht, jedoch kamen nur noch die Besagten
Thread Fehler und ich musste es so lösen.
Deinen Tipp werde ich mir noch ansehen, leider hab ich nicht mehr viel
Zeit am Code zu basteln
Micha schrieb:
> Albrecht H. schrieb:>> Zudem ist gar nicht festgelegt was passieren soll, wenn>> "SerialPort1.ReadExisting" zufällig mal mehr als 1 Byte liefert.>> Naja, zufällig wird ja nichts versendet, denn mehr versende ich mit dem> Mikrocontroller nicht.>> Mit dem anderen hast du schon Recht, jedoch kamen nur noch die Besagten> Thread Fehler und ich musste es so lösen.
Verständlich. Aber wenns nur mal so zum testen oder schnell vorführen
ist, lässt sich die Sache mit den "IllegalCrossThreadCalls" auch einfach
abschalten, dazu einfach folgende Zeile unterhalb von "Private Sub
Form1_Load ..." einfügen, dann verhält sich das Programm so als wäre es
unter VB2003 kompiliert worden, da gabs das noch nicht:
Control.CheckForIllegalCrossThreadCalls = False
und im verlinkten Beispiel wird ja dann gezeigt wie es richtig geht.
> Deinen Tipp werde ich mir noch ansehen, leider hab ich nicht mehr viel> Zeit am Code zu basteln
Albrecht H. schrieb:
> lässt sich die Sache mit den "IllegalCrossThreadCalls" auch einfach> abschalten
Naja, auch irgendwie dirty. Dann lieber einen delegaten anlegen, der den
GUI Thread handelt.
Noch einfacher
Schicke vom Controller nur 1 Byte als ByteBefehl.
Diesen auswerten und deine Ampeln schalten.
P.S. das DataReceived Ereignis kann eingestellt werden, nach wieviel
Byte es Auslöst.