Datenverlust beim Auslesen des Eingangsbuffers (Serielle Schnittstelle)

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von picoflop.

    Datenverlust beim Auslesen des Eingangsbuffers (Serielle Schnittstelle)

    Morgen,

    unzwar habe ich folgendes Problem:
    Für ein Projekt wird eine Serielle Schnittstelle benötigt, diese Funktioniert auch soweit.
    Ich erhalte über diese in einem Abstand von jeweils 2 Sekunden Daten.
    Das Problem ist jedoch, wenn ich versuche via

    VB.NET-Quellcode

    1. SerialPort1.ReadExisting
    die Daten auszulesen, ist es in diesem Moment nicht mehr möglich, Daten in den Buffer zu schreiben, und somit fehlt dann ein teil der Daten die eig. Mitempfangen werden sollten.

    Also es sieht wie folgt aus momentan:

    VB.NET-Quellcode

    1. Public Sub SerialPort1_DataReceived(ByVal sender As System.Object, _
    2. ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    3. inputData = SerialPort1.ReadExisting
    4. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    5. End Sub


    Es kann beim Dateneingang jedoch auch sein, das ununterbrochen Daten eingehen, das bedeutet ohne "2 Sekunden abstand" sondern das ca. alle 230ms etwas kommt, kann auch mal schneller gehen, auch mal Langsamer.
    Jedoch wenn ich jetzt Probiere die Daten auszulesen während Daten eingehen, fehlt immer ein teil der Zeichenkette die ich eigentlich Empfangen sollte. Die größte des Eingangsbuffers der Seriellen Schnittstelle ist hierbei auf 8192Bytes gestellt und die Baudrate auf 2400. Nun meine frage: Wie wickle ich das ganze nun so ab, das er Synchron Daten lesen kann (-> Die Serielle Schnittstelle) und diese in den Eingangsbuffer schreiben kann, während ich via

    VB.NET-Quellcode

    1. SerialPort1.ReadExisting
    auf den Eingangsbuffer zugreife?

    Momentan funktioniert es nur so, das ich entweder auf den Eingangsbuffer zugreife ODER das die Serielle Schnittstelle grade reinschreibt.
    Jedoch ist das ein Schwerwiegendes Problem im Aktuellen Projekt was unbedingt behoben bzw. umgangen werden muss, jedoch fällt mir keine Lösung zu dem Problem ein...

    Ich wäre über einige Ideen Ansätze echt erfreut!

    Mit Freundlichen Grüßen,
    Neoner
    Pack mal das Auslesen der Daten selbst in die invoke-te Prozedur. :!: :!: :!:
    Hier mal ein Beispiel, was läuft (andere Invoke-Syntax, sollte kein Problem sein):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    2. If (TextBox2.InvokeRequired) Then
    3. ' Aufruf aus anderem Thread
    4. Dim d As New ReceiveTextInvoke(AddressOf ReceiveText)
    5. TextBox2.Invoke(d)
    6. Return
    7. End If
    8. ReceiveText()
    9. End Sub
    10. Private Sub ReceiveText()
    11. Dim ToRead As Integer = SerialPort1.BytesToRead
    12. If ToRead > 0 Then
    13. 'Neu empfangene Zeichen an die Empfangspuffer anhängen
    14. Dim Buffer(ToRead - 1) As Byte
    15. SerialPort1.Read(Buffer, 0, ToRead)
    16. TextBox2.Text &= _Encoding.GetString(Buffer)
    17. End If
    18. 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!
    Danke ersteinmal fürs Antworten, @RodFromGermany

    Das Problem das ich habe und (leider) nicht lösen kann, vllt. bedingt durch die morgentliche Müdigkeit ( :rolleyes: ) ist folgendes:
    Fehler auf Zeile 91: Der Typ ReceiveTextInvoke ist nicht definiert.

    VB.NET-Quellcode

    1. Dim d As New ReceiveTextInvoke(AddressOf ReceiveText)


    Ich habe aktuell auch keine möglichkeit gefunden das Problem zu umgehen, und wollte auch nicht wirklich viel an deinem Code verändern.
    Kannst du mir grade sagen, wie ich das umgehen kann bzw. beheben kann? Ich habe mich schon bereits etwas erkundigt aber noch nichts finden können.
    Das ist für Dich nicht wichtig.
    Du hast eine Prozedur, die das Event auffängt: SerialPort1_DataReceived() und Du hast eine Prozedur, die vom Invoke aufgerufen wird: DoUpdate()
    Teile den effektiven Code von mir auf Deine beiden Routinen auf. :thumbsup:
    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!
    Warum überhaupt ReadExisting()? Steht doch schon in MSDN dass da Murks rauskommen kann ...
    ->
    The SerialPort class buffers data, but the stream object contained in the SerialPort.BaseStream property does not. Therefore, the SerialPort object and the stream object might differ on the number of bytes that are available to read. When bytes are buffered to the SerialPort object, the BytesToRead property includes these bytes in its value; however, these bytes might not be accessible to the stream contained in the BaseStream property.


    Warum nicht:
    p.Read(buf, 0, p.BytesToRead)

    picoflop schrieb:

    Warum nicht:
    p.Read(buf, 0, p.BytesToRead)
    weil wir uns nicht richtig Informiert haben, ich versuche grade von ReadExisting auf Read umzusteigen.
    Jedoch erhalte ich beim Debuggen der Anwendung (Windows CE 6.0, .NET Compact Framework 3.5) immer eine NullReferenzeException beim Dateneingang, als Hinweis steht dort "Buffer cannot be 0". Wie umgehe ich das?

    Der Bisherige Code in dem Bereich:

    VB.NET-Quellcode

    1. If SerialPort1.BytesToRead() > 0 Then
    2. inputData = SerialPort1.Read(Buffer, 0, SerialPort1.BytesToRead()) ' -> Fehlerhafte Zeile
    3. sp_text = inputData
    4. SerialPort1.DiscardInBuffer()
    5. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    6. End If


    Buffer ist wie folgt Definiert:

    VB.NET-Quellcode

    1. Public Buffer As Byte()