Datenempfang über die Serielle Schittstelle hängt sich immer wieder auf

  • VB6

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

    Datenempfang über die Serielle Schittstelle hängt sich immer wieder auf

    Hallo,
    ich lasse Daten eines AVR Prozessors über die serielle Schnittstelle einlesen.
    Das Programm hierzu habe ich in VB6 geschrieben.
    Nun kommt es aber leider immer mal wieder vor dass sich das Empfangen der Daten aus irgent einem Grund aufhängt.
    Senden ist dann aber weiterhin möglich.
    Hat jemand ne Erklärung dafür, bzw. wie kann ich den Com Port reseten ohne jedes mal das Programm neu starten zu müssen?

    Hier mein Programmausschnitt:

    Visual Basic-Quellcode

    1. Private Sub MSComm1_OnComm()
    2. On Error GoTo Fehlerliste
    3. Select Case MSComm1.CommEvent
    4. Case comOverrun: MsgBox "Datenverlust!"
    5. Case comRxOver: MsgBox "Datenverlust!"
    6. Case comEvReceive: Me.Text1 = Me.Text1 + MSComm1.Input
    7. Case comEventBreak: MsgBox " 1001 Es wurde ein Anhaltesignal (Break-Signal) empfangen."
    8. Case comEventFrame: MsgBox " 1004 Datenblockfehler (Framing Error). Die Hardware hat einen Datenblockfehler entdeckt."
    9. Case comEventRxParity: MsgBox " 1009 Paritätsfehler (Parity Error). Die Hardware hat einen Paritätsfehler entdeckt."
    10. Case comEventTxFull: MsgBox " 1010 Sendepuffer voll (Transmit Buffer Full). Bei dem Versuch, ein Zeichen in die Warteschlange aufzunehmen, wurde festgestellt, daß der Sendepuffer voll war."
    11. Case comEventDCB: MsgBox "1011 Unerwarteter Fehler beim Abrufen des Device Control Block (DCB) für den Anschluß. "
    12. End Select
    13. Debug.Print MSComm1.Input
    14. vari1ende = InStr(Me.Text1, "#")
    15. If vari1ende > 20 Then
    16. Haus.ComEingang = Me.Text2
    17. Me.Text2 = Left(Me.Text1, vari1ende)
    18. Me.Protokoll1 = Time & " - " & Me.Text2 & Me.Protokoll1
    Es hängt sich normal nicht auf. Das Receive-Ereignis wird nicht zuverlässig angesprungen, wenn der Puffer noch nicht voll ist.
    Am zuverlässigsten läuft es bei mir, wenn ich regelmäßig die Größe des Empfangspuffers (MSCommX.InBufferCount) abfrage und wenn größer 0 die Daten manuell einlese und wenn ein chr(13) kommt auswerte.
    Gruß
    Peterfido

    Keine Unterstützung per PN!
    Hier mal das noch unaufgeräumte Grundgerüst inkl Fehlerabfangen und automatischer Suche nach dem richtigen Port:

    Visual Basic-Quellcode

    1. Private Sub PortAuf()
    2. Dim X As Integer
    3. If MSComm1.PortOpen Then MSComm1.PortOpen = False
    4. With MSComm1
    5. .Settings = "19200,n,8,1"
    6. .InBufferSize = 256
    7. .DTREnable = False
    8. .RTSEnable = False
    9. End With
    10. On Error Resume Next
    11. For X = 1 To 16
    12. Err.Clear
    13. MSComm1.CommPort = X
    14. MSComm1.PortOpen = True
    15. If Err.Number = 0 Then
    16. If isStoppuhr Then
    17. lblFehler.Caption = "Stopuhr an COM" & X
    18. For i = 0 To 3
    19. Command1(i).Enabled = True
    20. Next i
    21. log_Oeffnen
    22. mnuVerbindung.Caption = "Trennen"
    23. tmrEmpfang.Enabled = True
    24. On Error GoTo 0
    25. Exit Sub
    26. End If
    27. End If
    28. MSComm1.PortOpen = False
    29. Next X
    30. lblFehler.Caption = "Stopuhr nicht gefunden"
    31. On Error GoTo 0
    32. End Sub
    33. Private Function isStoppuhr() As Boolean
    34. Dim lZeit As Long
    35. Dim s As String
    36. MSComm1.Output = "0"
    37. lZeit = Timer + 1
    38. Do While Timer < lZeit
    39. Loop
    40. If MSComm1.InBufferCount > 0 Then
    41. s = MSComm1.Input
    42. If Left$(s, 7) = "Stopuhr" Then
    43. isStoppuhr = True
    44. End If
    45. End If
    46. End Function
    47. Private Sub PortZu()
    48. Dim sText As String
    49. Dim lZeit As Long
    50. tmrEmpfang.Enabled = False
    51. On Error Resume Next
    52. For i = 0 To 3
    53. Command1(i).Enabled = False
    54. Next i
    55. On Error Resume Next
    56. If MSComm1.PortOpen = False Then Exit Sub
    57. MSComm1.RTSEnable = False
    58. lZeit = Timer + 2
    59. Do While Timer < lZeit
    60. Loop
    61. sText = MSComm1.Input
    62. MSComm1.PortOpen = False
    63. mnuVerbindung.Caption = "Verbinden"
    64. Close F
    65. Err.Clear
    66. On Error GoTo 0
    67. End Sub
    68. Private Sub Form_Load()
    69. PortAuf
    70. End Sub
    71. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    72. PortZu
    73. End Sub
    74. Private Sub tmrEmpfang_Timer()
    75. Dim Anzahl As Long
    76. Dim i As Integer
    77. Dim s As String
    78. On Error GoTo Fehler
    79. Anzahl = MSComm1.InBufferCount
    80. If Anzahl > 0 Or Len(Eingang) > 0 Then
    81. s = MSComm1.Input
    82. Eingang = Eingang & s
    83. i = InStr(1, Eingang, Chr$(13))
    84. If i > 0 Then
    85. Eingang1 = Left$(Eingang, i)
    86. Eingang1 = Replace(Eingang1, Chr$(10), "")
    87. Eingang1 = Replace(Eingang1, Chr$(13), "")
    88. If Len(Eingang) > i + 1 Then
    89. Eingang = Mid$(Eingang, i + 1)
    90. Else
    91. Eingang = ""
    92. End If
    93. Auswerten
    94. End If
    95. End If
    96. On Error GoTo 0
    97. Exit Sub
    98. Fehler:
    99. lblFehler.Caption = Err.Description
    100. Err.Clear
    101. PortZu
    102. On Error GoTo 0
    103. End Sub


    Das Auswerten lasse ich mal weg, da werden Zeiten und so formatiert und eine Log-Datei geschrieben.
    Im Prinzip z.B. den Inhalt in einer Listbox anzeigen.

    Visual Basic-Quellcode

    1. private sub Auswerten()
    2. list1.additem eingang1
    3. end sub


    Edit: Kleinen Fehler behoben.
    Gruß
    Peterfido

    Keine Unterstützung per PN!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „peterfido“ ()

    Hallo,

    vielen Dank für deine Unterstützung.
    Leider bin ich an diesem Wochenende noch nicht zum ausprobieren gekommen.
    Ich werde es vermutlich auch erst nächstes WE schaffen.

    Ich schreibe mir übrigens auch gerade ein Programm welches am Ende eines CAN Busses Temperaturen und Schalter abfragt bzw. Steuert.
    Klappt soweit ganz gut aber mir fällt immer was neues an...

    Viele Grüße
    Tobias

    elkokiller schrieb:

    mir fällt immer was neues an...

    Kenn ich... :D

    Meines ist ein Projekt für den Sportclub eines Kollegen. Da kommen an die Laufbahn Lichtschranken, welche ihr Signal an einen kleinen AtTiny2313 schicken. Dieser stoppt die Zeiten und sendet die Ergebnisse zum Laptop.

    Die Anfrage des Kollegen war übrigens eine hier im Board schon öfter gestellte. Er wollte die Lichtschranken direkt an den Com-Port anschließen...
    Gruß
    Peterfido

    Keine Unterstützung per PN!
    Hallo peterfido
    ich habe mir das Programm jetzt mal angesehen.
    Wäre es dir möglich mir das dazugehörige Formular zur Verfügung zu stellen.
    Da hier Timer und Buttons angesprochen werden würde mir das Formular den Durchblick doch erheblich erleichtern

    Danke!

    Grüße
    Tobias
    tmrEmpfang ist ein einfacher Timer mit Interval auf 60.
    Die Buttons kannst Du weglassen. Diese senden Zahlen an den Mikrocontroller.
    Da steht im Prinzip

    Visual Basic-Quellcode

    1. MSCOMM1.OUTPUT ="1"


    oder so drin.
    lblFehler und lblStatus waren 2 Label am unteren Rand, welche ich in der Zwischenzeit durch eine Statusbar ersetzt habe.
    mnuVerbindung ist ein Menüpunkt, welcher manuell die Verbindung aufbaut oder trennt.

    Die Funktion IsStopuhr ist für die automatische Suche nach dem richtigen Port. Wenn da kein Mikrocontroller oder
    PC dranhängt, welcher nach einer empfangenen "0" seine Kennung sendet, wo "Stopuhr" am Anfang drin vorkommt, stört sie nur.

    Mein Code war eher als Stütze gedacht und muss natürlich an die jeweiligen Bedürfnisse angepasst werden. Verbindungsaufbau und zuverlässiger Empfang
    sind aber drin.
    Gruß
    Peterfido

    Keine Unterstützung per PN!
    Hi,
    ich bin jetzt drann den Code an mich anzupassen.
    Kannst du mir sagen wie dur "Eingang" definiert hast?

    z.b. If Anzahl > 0 Or Len(Eingang) > 0 Then

    Nach meinem Verständnis müsstest du doch irgentwo den Port selbst abfragen z.B.

    comEvReceive: eingang = eingang + MSComm1.Input

    Leider funktionirt das hier nicht.
    Hast du eine Idee?