Komme mit RS-232 nicht klar

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von rogerberglen.

    Komme mit RS-232 nicht klar

    Hört sich jetzt blöd an, aber ich habe jetzt schon sehr viel ausprobiert und bekomme das mit der RS-232 nicht hin.
    Ich habe per RS-232 selbstgebaute Hardware angeschlossen. Diese wird mit einem alten Quick-Basic Programm gesteuert.
    Wenn ich unter Quick-Basic folgendes schreibe: OPEN "COM1:9600,N,8,1" FOR RANDOM AS #1 PRINT#1, CHR$(&H1A);CHR$(&H55), zur Erklärung: der Code 1A ist eine Testroutine in meiner Hardware, dann wird schön der nachfolgende Wert auf einem LCD-Display dargestellt, in diesem Fall der Wert &H55.
    Wenn ich nun in VB2008 Folgendes schreibe:
    Me.SerialPort1.BaudRate = 9600
    Me.SerialPort1.Parity = IO.Ports.Parity.None
    Me.SerialPort1.DataBits = 8
    Me.SerialPort1.StopBits = IO.Ports.StopBits.One

    Dim ByteSend() As Byte = {26, 85}

    Me.SerialPort1.Open

    Me.SerialPort1.Write(ByteSend, 0, 2)

    Dann tut sich da absolut überhaupt nichts!! Das sollte doch so gehen? Oder geht es unter VB2008 komplett anders?
    Wie empfange ich dann mit VB2008 Bytes von der RS-232?
    Unter Quick-Basic habe ich da In$ = Input$(1, #1) geschrieben.

    *Topic verschoben*

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Mit VB2008 habe ich es zwar noch nicht probiert.
    Aber folgendes würde ich an deiner Stelle noch testen:

    Du solltest noch angeben, welchen Port du überhaupt ansprechen willst.
    Es heißt ja nicht, dass Me.SerialPort1 tatsächlich COM1 ist.

    Weiterhin machst du keine Angaben über den Handshake.
    Wenn das eine Gerät auf eine Rückmeldung wartet und das andere sendet diese nicht
    dann wird auch nichts passieren.

    Weiterhin würde ich die Bytes erst mal mit kleinen Pausen schicken.
    Manche Geräte vertragen so schnelle Bytefolgen nicht (falls du tatsächlich keinen Handshake
    verwendet hast)

    Dann besorgst du dir einen einfachen Schnittstellentester, ich meine die
    mit den Leuchtdioden. Da siehst du wenigstens ob bei deinen Bytes die du
    sendest irgend etwas auf blinkt.
    Also ich habe jetzt schon alles Mögliche versucht. Ohne Erfolg. Wenn ich statt meiner Hardware einen zweiten PC mit Hyperterminal starte, dann sehe ich die Bytes als Zeichen dargestellt. Ich habe es mit verschiedenen Einstellungen in den Handshake-Signalen versucht. Nichts, null und gar nichts. Auch wenn ich mit dem zweiten PC Daten in die Gegenrichtung sende zeigt mir zwar die Abfrage SerialPort1.BytesTo Read die Anzahl an, aber ich bekomme diese nicht ausgelesen.
    In der Auslesezeile gibt es immer eine Null-Reference Ausnahme. Warum weis ich nicht:

    Me.SerialPort1.PortName = "COM1"
    Me.SerialPort1.Handshake = IO.Ports.Handshake.RequestToSend
    Me.SerialPort1.BaudRate = 9600
    Me.SerialPort1.Parity = IO.Ports.Parity.None
    Me.SerialPort1.DataBits = 8
    Me.SerialPort1.StopBits = IO.Ports.StopBits.One

    Dim ByteSend() As Byte = {26, 55}
    Dim ByteRead() As Byte = Nothing


    Me.SerialPort1.Open

    Me.SerialPort1.Write(ByteSend, 0, 2)


    X = Me.SerialPort1.BytesToRead

    Me.SerialPort1.Read(ByteRead, 0, X)

    Was macht denn VB2008 um Himmels Willen anders an den Signalen als Quick-Basic mit dem es ja funktioniert?
    Das ist doch schon mal ein Erfolg, da du doch in deinem ersten Mail behauptet hattest,
    dass beim Senden überhaupt nichts passiert. Jetzt schreibst du, dass du die Daten am anderen
    PC empfangen kannst.
    Verwendest du eigentlich Ereignis gesteuerten Datenempfang an deinem PC?
    Das solltest du auf jeden Fall machen. Dann kannst du auch noch die Errorcodes
    auslesen und andere Steuerleitungen überwachen.
    Wenn du immer nur pollst, also immer mal selbst schaust, ob Daten angekommen sind,
    das ist etwas mühsam und fehlerlastig.

    Hast du einen Inputbuffer angelegt?

    Am Anfang würde ich beide Geräte ohne Handshake betreiben, dann wird
    die Schnittstelle auch nicht hängenbleiben. Kannst ja eventuell noch einen
    Timeout einbauen, damit das Warten rechtzeitig abgebrochen wird.

    RS232 ist nun mal ziemlich komplex, da kann man viel falsch machen.
    Falls ich hier irgend etwas schreibe, das es bei VB2008 nicht mehr gibt, dann
    liegt es eben daran, dass ich bisher nur mit VB6 die RS232 programmiert hatte.
    Natürlich muß am Ende der beiden Bytes noch ein Semikolon hin. Aber mit VB2008 funktioníert das Ganze trotzdem überhaupt nicht!! Das Empfangsgerät reagiert einfach mal gar nicht.
    Wie gesagt bei Quick-Basic OPEN "COM1:9600,N,8,1" FOR RANDOM AS #1; PRINT#1, CHR$(&H1A); CHR$(&H55); und das Empfangsgerät zeigt schön den Wert 55Hex auf dem Display an.

    Me.SerialPort1.PortName = "COM1"
    Me.SerialPort1.Handshake = IO.Ports.Handshake.None
    Me.SerialPort1.BaudRate = 9600
    Me.SerialPort1.Parity = IO.Ports.Parity.None
    Me.SerialPort1.DataBits = 8
    Me.SerialPort1.StopBits = IO.Ports.StopBits.One


    Me.SerialPort1.Open

    Me.SerialPort1.Write(Chr(&H1A) + Chr(&H55))


    Warum funktioniert das so nicht?!?!?!?
    Bei Quick-Basic klappt das doch auch so. Ich glaub ich werde langsam mürbe! Denn da mache ich jetzt schon seit 3 Tagen daran herum nur mal um lumpige 2 Byte zu versenden.
    das kanns doch nicht sein, daß das so kompliziert ist. Wie ist das dann erst mit dem Einlesen von irgendwelchen Bytes oder gar ganzen Arrays?
    Da braucht man dann einen Doktortitel dazu.
    Gibt es denn keine einfache klare Beschreibung wie das Ganze zuverlässig funktioniert??
    Mit folgendem Code funktioniert jetzt das Senden. Meine Hardware reagiert korrekt auf die gesendeten Befehle.

    Me.SerialPort1.PortName = "COM1" 'Name der RS-232 festlegen.
    Me.SerialPort1.Handshake = IO.Ports.Handshake.None 'Kein Handshaking
    Me.SerialPort1.BaudRate = 9600 'Übertragungsrate
    Me.SerialPort1.Parity = IO.Ports.Parity.None 'Keine Paritätsprüfung
    Me.SerialPort1.DataBits = 8 '8 Datenbits
    Me.SerialPort1.StopBits = IO.Ports.StopBits.One '1 Stoppbit
    Me.SerialPort1.RtsEnable = True 'RTS-Signal aktivieren
    Me.SerialPort1.DtrEnable = True 'DTR-Signal aktivieren
    Me.SerialPort1.ReceivedBytesThreshold = 1 'Empfang bei 1 Byte auslösen.

    Me.SerialPort1.Open 'Seriellen Port mit den Einstellungen
    'öffnen.
    Me.SerialPort1.Write(Chr(&H1A) + Chr(&H55)) 'Zum Test LED-Muster auf dem MLT aus-
    'geben.
    X = Me.SerialPort1.BytesToRead

    In X wird jetzt auch 1 Byte angezeigt. Aber wie wird jetzt das DataReceived-Ereignis ausgelöst? Die Hardware quittiert das gesendete Zeichen ohne CrLf.
    Ich finde es schon schwierig hier Ferndiagnosen zu stellen.
    An das Writeline hatte ich auch schon gedacht, aber wenn es mit Write auch schon geht ist ja ok.
    Wieso brauchst du jetzt doch die Steuerleitungen obwohl du Handshake ausgeschaltet hast?
    Ist das ein Bug in der Schittstelle. Ich weiß natürlich auch nicht, welche Kabel du überhaupt
    angeschlossen hast.
    Was jetzt, wird kein DataReceived ausgelöst, wenn das Gerät zum PC sendet?
    Ich müsste jetzt nachschauen, wird das Ereignis bei den Anzahl Bytes ausgelöst,
    die man bei Threshold eingestellt hatte?
    Irgendwie erinnere ich mich auch daran, dass man mit Flush die Puffer leeren sollte,
    um nicht alten Schrott, der noch drin ist auszulesen.

    Schon beinahe fertig mit meiner Lösung

    So, nachdem ich gestern auf dem Volksfest in Stuttgart war habe ich mich gestern Abend nochmals an mein Problem gesetzt. Ich kann jetzt inzwischen einen Befehl zu meinem "MLT-System" senden und auch ein ganzes Byte-Array empfangen. Das zeige ich zum Test in einer List-Box an.
    Nun möchte ich aber das Senden und den Empfang als universelle Function bzw. Sub in mein Projekt einbauen. Mir fehlt jetzt nur noch eine Lösung wie ich ein empfangenes Byte-Array auch wieder als Byte-Array zurückgebe. Ich kenne mich mit den Tread-Geschichten nicht gut aus und verstehe auch von der jetzt abgeschriebenen Routine nicht viel.
    Hier mein bisheriger Code:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Delegate Sub lstBoxCallback(ByVal Bef() As Byte)
    3. Private Shared ByteIn() As Byte
    4. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    5. Me.SerialPort1.PortName = "COM1" 'Name der RS-232 festlegen.
    6. Me.SerialPort1.Handshake = IO.Ports.Handshake.None 'Kein Handshaking
    7. Me.SerialPort1.BaudRate = 9600 'Übertragungsrate
    8. Me.SerialPort1.Parity = IO.Ports.Parity.None 'Keine Paritätsprüfung
    9. Me.SerialPort1.DataBits = 8 '8 Datenbits
    10. Me.SerialPort1.StopBits = IO.Ports.StopBits.One '1 Stoppbit
    11. Me.SerialPort1.RtsEnable = True 'RTS-Signal aktivieren
    12. Me.SerialPort1.DtrEnable = True 'DTR-Signal aktivieren
    13. Me.SerialPort1.Open 'Seriellen Port mit den Einstellungen
    14. 'öffnen.
    15. 'Me.SerialPort1.Write(Chr(&H1A) & Chr(&H55)) 'Zum Test LED-Muster auf dem MLT aus-
    16. 'geben. Danach Befehlstabelle aus dem
    17. Me.SerialPort1.Write(Chr(&H14)) 'MLT-System ausgeben lassen.
    18. End Sub
    19. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    20. '!!ACHTUNG!! Weiterer Tread <<<<<
    21. Dim ByteIn(Me.SerialPort1.BytesToRead - 1) As Byte 'Byte-Array einrichten anhand der An-
    22. 'zahl der empfangenen Bytes. Die em-
    23. Me.SerialPort1.Read(ByteIn, 0, Me.SerialPort1.BytesToRead) 'pfangenen Bytes in das Byte-Array
    24. 'schreiben. Byte-Array in anderen Tread
    25. Me.Liste(ByteIn) 'übergeben.
    26. End Sub
    27. Private Sub Liste(ByVal Bef() As Byte)
    28. If Me.lstBef.InvokeRequired Then 'Sollte ein CallBack notwendig sein,
    29. Dim d As New lstBoxCallback(AddressOf Liste) 'diesen dann aufrufen. Per Invoke dann
    30. Me.Invoke(d, New Object() {Bef}) 'das Byte-Array an den Haupttread über-
    31. Else 'geben.
    32. For A As Integer = 0 To Bef.Length - 1 'Sonst das Byte-Array in ein List-Feld
    33. Me.lstBef.Items.Add(Hex(Bef(A))) 'schreiben und in Hex-Werte wandeln.
    34. Next
    35. End If
    36. lstBef.Sorted = True 'List-Feld sortiert anzeigen.
    37. End Sub
    38. End Class


    Anstatt mit der For-Next Schleife ein List-Feld zu füllen möchte ich ein Array mit den empfangenen Bytes zurückgeben.