Eventgesteuerter Datenempfang über die COM Schnittstelle

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Eventgesteuerter Datenempfang über die COM Schnittstelle

    Hallo Leute!

    Da mir in jedem meiner Fragen gesagt wird "VB.NET" ist eine Eventgesteuerte Programmiersprache, habe ich mir das auch zu Herzen genommen.

    In meiner VB6 Anwendung habe ich per Timer die serielle Schnittstelle abgefragt (ob da Daten anliegen).

    In VB2012 würde ich das gerne in folgender Art lösen (falls das möglich ist):

    Im Form-Load den Com-Port öffnen

    Sobald Daten an der Seriellen Schnittstelle reinkommen soll eine Prozedur aufgerufen werden, wo die Daten dann einfach abgefragt und ausgegeben werden.
    Es handelt sich um Kellnerschlösser, welche beim Auflegen des Schlüssels einfach eine beliebig lange Zeichenkette übergeben (meist mit ENTER am Ende).
    Diese möchte ich einfach nur auslesen.

    Ich habe mir das schon mal angesehen: msdn.microsoft.com/en-us/libra…ialport.datareceived.aspx
    Aber irgendwie funktioniert das nicht. Das Ereignis wird nicht "angesprungen".

    Gibt es da einen wirklich kurzen Code für sowas?

    Ich habs so versucht, geht aber irgendwie nicht:

    VB.NET-Quellcode

    1. Imports System.IO.Ports
    2. Public Class frm_hauptform
    3. Public Event DataReceived As SerialDataReceivedEventHandler
    4. Public Kellnerschloss_SerialPort As New SerialPort("COM4")
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. Kellnerschloss_SerialPort.BaudRate = 9600
    7. Kellnerschloss_SerialPort.Parity = Parity.None
    8. Kellnerschloss_SerialPort.StopBits = StopBits.One
    9. Kellnerschloss_SerialPort.DataBits = 8
    10. Kellnerschloss_SerialPort.Handshake = Handshake.None
    11. AddHandler Kellnerschloss_SerialPort.DataReceived, AddressOf DatenEmpfangKellnerschloss
    12. Kellnerschloss_SerialPort.Open()
    13. End Sub
    14. Private Sub DatenEmpfangKellnerschloss(sender As Object, e As SerialDataReceivedEventArgs)
    15. Dim sp As SerialPort = CType(sender, SerialPort)
    16. Dim indata As String = sp.ReadExisting()
    17. MessageBox.Show("Data Received: " + indata)
    18. End Sub
    19. .. Close natürlich beim Beenden ...
    20. End Class


    LG Roland
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Habe gerade versucht das SerialPort Steuerelement auf die Form zu ziehen und so aufzurufen.
    Das einzige Event das aufgerufen wird ist "Dispose", wenn ich mit portname.close den Port schließe.
    Alle anderen Events, besonders das DataReceived wird gar nicht angesprungen.
    Was mache ich falsch?

    VB.NET-Quellcode

    1. ... Anfang Form Load ...
    2. SerialPort1.BaudRate = 9600
    3. SerialPort1.DataBits = 8
    4. SerialPort1.StopBits = IO.Ports.StopBits.One
    5. Me.SerialPort1.Parity = IO.Ports.Parity.None
    6. SerialPort1.PortName = "COM4"
    7. SerialPort1.ReceivedBytesThreshold = 1
    8. Try
    9. SerialPort1.Open()
    10. Catch
    11. MsgBox("Fehler beim Öffnen des COM-Ports")
    12. End Try
    13. ... Ende Form Load ...
    14. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    15. MsgBox("DataReceived")
    16. End Sub
    17. Private Sub SerialPort1_Disposed(sender As Object, e As EventArgs) Handles SerialPort1.Disposed
    18. MsgBox("Disposed")
    19. End Sub
    20. Private Sub SerialPort1_ErrorReceived(sender As Object, e As IO.Ports.SerialErrorReceivedEventArgs) Handles SerialPort1.ErrorReceived
    21. MsgBox("ErrorReceived")
    22. End Sub
    23. Private Sub SerialPort1_PinChanged(sender As Object, e As IO.Ports.SerialPinChangedEventArgs) Handles SerialPort1.PinChanged
    24. MsgBox("PinChanged")
    25. End Sub
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Was mache ich falsch?
    Ist COM4 ühaupt vorhanden?
    Dieses Snippet listet Dir alle vorhandenen Ports auf.

    VB.NET-Quellcode

    1. Dim txt = ""
    2. For Each port In IO.Ports.SerialPort.GetPortNames
    3. txt += port & Environment.NewLine
    4. Next
    5. MessageBox.Show(txt)
    Und: Nimm mal das Try / Catch raus, denn Du willst doch Fehler finden, nicht aber verschleiern.
    Sind die Initialisierungsdaten richtig?
    Wenn Du nix sendest (eine Anfrage z.B.) kannst Du auch nix empfangen.
    Woher soll die Gegenstelle wissen, dass Du was von ihr wilst?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, Port existiert und die Parameter sind auch korrekt und kann auch über die "alte" Routine in VB6 ausgelesen werden. Also auch das Kellnerschloss sendet Daten.

    Wenn ich das Kellnerschloss (USB zu RS232) ausstecke (also wenn COM4 dann nicht mehr verfügbar ist), dann erhalte ich ja die Fehlermeldung.

    Das mit dem parallelem Thread habe ich bereits gelesen - ist für die weitere Verarbeitung wichtig. Aber trotzdem sollte bei DataReceived was kommen oder?

    Werde das morgen nochmals Schritt für Schritt ducharbeiten.

    Wenn Du nix sendest (eine Anfrage z.B.) kannst Du auch nix empfangen.

    Woher soll die Gegenstelle wissen, dass Du was von ihr wilst?
    Das Kellnerschloss sendet Daten sobald ein Schlüssel aufgelegt wurde. Ein Abfragesignal ist nicht notwendig.

    In VB6 frage ich das per Timer ab. Hier der Code dazu:

    VB.NET-Quellcode

    1. If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
    2. schluesselcode = MSComm1.Input


    (Die Port-Parameter wurden bereits in den ActiveX Eigenschaften vordefiniert)
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    Ein Abfragesignal ist nicht notwendig.
    Sendet das Gerät quasi permanent?
    Überprüf das bitte mit dem PortMonitor.
    Mach Dir zunächst eine separate Testanwendung, in der Du ausschließlich dieses Problem untersuchst.
    Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo Leute!

    Ich bin verzweifelt und komme nicht weiter.

    Ich kann und kann vom COM4 unter VB2012 keine Zeichen empfangen.
    Habe auch den geposteten MSDN Quellcode 1:1 in eine neue Anwendung gepackt - da tut sich auch gar nichs.

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.IO.Ports
    3. Class PortDataReceived
    4. Public Shared Sub Main()
    5. Dim mySerialPort As New SerialPort("COM4")
    6. mySerialPort.BaudRate = 9600
    7. mySerialPort.Parity = Parity.None
    8. mySerialPort.StopBits = StopBits.One
    9. mySerialPort.DataBits = 8
    10. mySerialPort.Handshake = Handshake.None
    11. AddHandler mySerialPort.DataReceived, AddressOf DataReceivedHandler
    12. mySerialPort.Open()
    13. Console.WriteLine("Press any key to continue...")
    14. Console.WriteLine()
    15. Console.ReadKey()
    16. mySerialPort.Close()
    17. End Sub
    18. Private Shared Sub DataReceivedHandler(
    19. sender As Object,
    20. e As SerialDataReceivedEventArgs)
    21. Dim sp As SerialPort = CType(sender, SerialPort)
    22. Dim indata As String = sp.ReadExisting()
    23. Console.WriteLine("Data Received:")
    24. Console.Write(indata)
    25. End Sub
    26. End Class



    In VB6 funktioniert die Abfrage über COM4 in einer Timer-Schleife einwandfrei.

    VB.NET-Quellcode

    1. ... Form Load: MSComm1.PortOpen = True
    2. Public Sub Timer1_Timer()
    3. temp1$ = ""
    4. temp1$ = MSComm1.Input
    5. Text1.Text = temp1$
    6. End sub
    7. ... Form Unload: If MSComm1.PortOpen = True Then MSComm1.PortOpen = False


    Ich weis nicht woran es liegt.

    Ich habe auch schon den Serial Port Monitor (neue Version) heruntergeladen. Auch dieser erkennt an COM4 keine Daten.
    Dass die Daten aber auf COM 4 reinkommen ist Tatsache, sonst würde unter VB6 nichts ausgelesen werden können.

    Zu meinem Systeme: Windows 7 64 Bit.
    Vielleicht hilt diese Info?
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    Ich weis nicht woran es liegt.
    Mach mal eine WinForm-Anwendung, nichtr aber eine Console.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe das Problem gefunden.
    Der Eigenschaftswert DtrEnable musste auf True gesetzt werden.

    Nun habe ich nur noch eine letzte Frage, um ganz sicher zu gehen.

    In meiner Software frage ich auch die Tastatureingaben ab.

    Gibt der User über die Tastatur sein Passwort ein und drückt anschliesend die Enter-Taste,
    dann wird über die keyUp Funktion der Form eine Routine aufgerufen

    VB.NET-Quellcode

    1. Private Sub frm_hauptform_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress


    welche dann das Passwort abgleicht und die Anzeigen entsprechend ausgibt.

    Wenn ich nun über einen Kellnerschlüssel über die COM-Schnittstelle per Event das Passwort erhalte,
    dann bekomme ich einen Threadfehler, wenn ich direkt über die SerialPort1_DataReceived andere Funktionen aufrufe.

    Daher habe ich mir folgendes gedacht, was soweit auch zu funktionieren scheint.

    Sobald der Schlüssel aufgelegt wurde und über die COM-Schnittstelle per SerialPort1_DataReceived empfangen wurde, wird der Schlüsselcode (das Passwort) in den internen Tastenpuffer (String) geschrieben. Anschließend wird die Funktion SendKeys.SendWait("{ENTER}") geschickt und das Event, welches normalerweise nur für die Tastaturabfragen zuständig ist, übernimmt die weitere Arbeit.

    Ist das so ok oder gibt es da durch das SendKeys.SendWait("{ENTER}") irgendwelche Rekursionen?

    LG Roland
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    Threadfehler
    Das Zauberwort heißt Invoke, probier es mal so:

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    2. Dim answer = Me.SerialPort1.ReadExisting
    3. Me.Invoke(Sub() Test(answer))
    4. End Sub
    5. Private Sub Test(ByVal answer As String)
    6. MessageBox.Show(answer)
    7. ' hier was mit dem String tun
    8. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    dive26 schrieb:

    In meiner Software frage ich auch die Tastatureingaben ab.
    dassis wieder prozedural gedacht

    Gibt der User über die Tastatur sein Passwort ein und drückt anschliesend die Enter-Taste,
    dann wird über die keyUp Funktion der Form eine Routine aufgerufen

    VB.NET-Quellcode

    1. Private Sub frm_hauptform_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
    ähm jagut - dassis eine Sub. aber differenziert betrachtet solltemandas besser als EventHandler bezeichnen.
    Vor allem gibt es keine KeyUp-Funktion, sondern KeyUp ist ein Event.
    Und der CodeSniüüüet zeigt auch ein Event, aber ein anneres, nämlich das KeyPress-Event
    Alles über Events (falls man dir damit noch nicht auf die Nerven ging.)
    Danke, ich habe dank Eurer Hilfe alles zusammen was Tastatureingaben und RS232 Eingaben betrifft. Morgen gehe ich Digital Persona Fingerprint Anmeldung an ... :D
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    ich habe dank Eurer Hilfe alles zusammen ...
    Ich wünsche Dir von Herzen, dass es so ist. :thumbup:
    Bis zu Deinem nächsten Thread. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!