Serielle Schnittstelle liest nicht alle Werte

  • VB.NET

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

    Serielle Schnittstelle liest nicht alle Werte

    Hi,

    ich habe eine Verbindung zu einen Mikrocontroller mit einer RS232 Verbindung. Generell klappt die Verbindung, schicke ich nur viele, ca. 80 Strings (z.B.: "83|00|22|44") auf einmal holt er sich die irgendwie nicht alle ab. Er bleibt mittendrin stehen. Wenn ich jetzt was zum Mikrocontroller sende, empfängt die Serielle Schnittstelle wieder 5 Strings von denen die vorher "vergessen" wurden. Das geht dann immer so weiter... Ich habe seit neuem ein Seriell auf Ethernet Konverter Konverter, vermutlich liegt es daran. Die Einstellungen des Gerätes habe ich in den Anhang gepackt!
    Dazu sagen muss ich noch, dass wenn ich die Werte mal mit einem Terminal Programm sende und auch empfange, geht alles wunderbar. Die Einstellungen des Terminals habe ich auch nach unten gepackt.

    Wodran kann das wohl liegen?

    Code im Anhang...

    VB.NET-Quellcode

    1. Public Class Form_Homevision
    2. Dim SerialInput As String = ""
    3. Private Sub Form_Homevision_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    4. Try
    5. SerialPort1.PortName = Form_Settings.TB_Com.Text
    6. SerialPort1.BaudRate = 9600
    7. SerialPort1.Parity = IO.Ports.Parity.None
    8. SerialPort1.DataBits = 8
    9. SerialPort1.StopBits = IO.Ports.StopBits.One
    10. SerialPort1.Handshake = IO.Ports.Handshake.None
    11. SerialPort1.RtsEnable = True
    12. SerialPort1.Open()
    13. Catch ex As Exception
    14. Form_Settings.Label2.Text = "Verbindung unterbrochen"
    15. End Try
    16. If SerialPort1.IsOpen Then
    17. Form_Settings.Label2.Text = "Verbindung hergestellt"
    18. SerialPort1.DiscardInBuffer()
    19. SerialPort1.DiscardOutBuffer()
    20. SerialPort1.Write("11|22|33|44" + Chr(13))
    21. End If
    22. End Sub
    23. '//Daten empfangen von der seriellen Schnittstelle
    24. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    25. Try
    26. If SerialPort1.IsOpen Then
    27. SerialInput = SerialPort1.ReadLine()
    28. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    29. End If
    30. Catch ex As Exception
    31. End Try
    32. End Sub
    33. Public Sub DoUpdate()
    34. ' Dim b As String
    35. ' ListBox füllen
    36. If StopAufzeichnung = False Then
    37. Form_Settings.ListBox1.Items.Insert(0, "Recv: " & SerialInput & " - " & TimeOfDay & " - " & Today)
    38. End If
    39. If SerialInput.Contains("|") = True Then
    40. AuswSerialInp(SerialInput)
    41. End If
    42. End Sub
    43. Public Sub AuswSerialInp(ByVal sInput As String)
    44. Try
    45. ' String in Array packen
    46. Dim sPraefix() As String = {0, 0, 0, 0}
    47. Dim iPraefix() As Integer = {0, 0, 0, 0}
    48. ' auf "|" splitten
    49. sPraefix = sInput.Split(CChar("|")) 'erster Seperator
    50. ' Integer Wert umwandeln
    51. iPraefix(0) = CInt(sPraefix(0))
    52. iPraefix(1) = CInt(sPraefix(1))
    53. iPraefix(2) = CInt(sPraefix(2))
    54. iPraefix(3) = CInt(sPraefix(3))
    55. '##############################################
    56. '##############################################
    57. 'Status vom Mikro
    58. '##############################################
    59. '##############################################
    60. Select Case iPraefix(0)
    61. '79-Heizung ist ein
    62. Case 79
    63. '##############################################
    64. ' Raum
    65. '##############################################
    66. Select Case iPraefix(1)
    67. Case 1
    68. '##############################################
    69. '##############################################
    70. Select Case iPraefix(2)
    71. '##############################################
    72. Case 1
    73. Select Case iPraefix(3)
    74. ' Aus
    75. Case 0
    76. ...
    77. ...
    78. ...
    79. ...




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

    1. Schmeiß das Try-Catch-Zeugs raus, Du willst doch Fehler finden, nicht aber verschleiern.
    2. lies alle verfügbaren Zeichen, nicht nur die nächste Zeile:

    VB.NET-Quellcode

    1. Dim ToRead As Integer = SerialPort1.BytesToRead
    2. If ToRead > 0 Then
    3. Dim Buffer(ToRead - 1) As Byte
    4. SerialPort1.Read(Buffer, 0, ToRead)
    5. ' was mit Buffer tun
    6. End If
    3. Werte alle empfangenen Zeichen aus, nicht nur dann, wenn ein "|" drin enthalten ist.
    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 weiss leider nicht wie ich das wo einfügen soll?!?!?

    VB.NET-Quellcode

    1. '//Daten empfangen von der seriellen Schnittstelle
    2. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    3. Try
    4. If SerialPort1.IsOpen Then
    5. SerialInput = SerialPort1.ReadLine()
    6. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    7. End If
    8. Catch ex As Exception
    9. End Try
    10. End Sub
    11. Public Sub DoUpdate()
    12. ' Dim b As String
    13. ' ListBox füllen
    14. If StopAufzeichnung = False Then
    15. Form_Settings.ListBox1.Items.Insert(0, "Recv: " & SerialInput & " - " & TimeOfDay & " - " & Today)
    16. End If
    17. If SerialInput.Contains("|") = True Then
    18. AuswSerialInp(SerialInput)
    19. End If
    20. End Sub

    Alex0815 schrieb:

    Ich weiss leider nicht wie ich das wo einfügen soll
    So:
    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. Me.Invoke(Sub() ReceiveText())
    3. End Sub
    4. Private Sub ReceiveText()
    5. Dim ToRead As Integer = SerialPort1.BytesToRead
    6. If ToRead > 0 Then
    7. Dim Buffer(ToRead - 1) As Byte
    8. SerialPort1.Read(Buffer, 0, ToRead)
    9. ' was mit Buffer tun
    10. End If
    11. 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!
    Mit dem ReadByte komme ich irgendwie nicht klar... Ich brauche ja den kompletten string bis zum CR

    Ich habe es jetzt mal so ausgetetst: (s.unten) Dabei wird jedoch nur die Erste Zeile angezeigt, dann garnichts mehr? Wodran kann das liegen? Ich brauche immer eine Zeile bis zum "\r" die Zeile sieht z.B. so aus 11|22|33|44

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.IO.Ports
    3. Imports System.Threading
    4. Public Class Form1
    5. Dim eineZeile As String
    6. Dim s As String = ""
    7. Dim SerialInput As String = ""
    8. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    9. SerialPort1.PortName = "COM4"
    10. SerialPort1.BaudRate = 9600
    11. SerialPort1.Parity = IO.Ports.Parity.None
    12. SerialPort1.DataBits = 8
    13. SerialPort1.StopBits = IO.Ports.StopBits.One
    14. SerialPort1.Handshake = IO.Ports.Handshake.None
    15. SerialPort1.RtsEnable = True
    16. SerialPort1.DtrEnable = True
    17. SerialPort1.NewLine = vbCr
    18. SerialPort1.Open()
    19. If SerialPort1.IsOpen Then
    20. Label1.Text = "...verbunden"
    21. SerialPort1.Write("11|22|33|44" + Chr(13))
    22. Else
    23. Label1.Text = "...getrennt"
    24. End If
    25. End Sub
    26. 'Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    27. ' SerialInput = SerialPort1.ReadLine()
    28. ' Me.Invoke(New EventHandler(AddressOf DoUpdate))
    29. 'End Sub
    30. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    31. Dim pos As Integer
    32. Dim posmemm As Integer
    33. '' Daten an SerialInput dranhängen, statt SerialInput zu überschreiben
    34. SerialInput = SerialInput + SerialPort1.ReadExisting()
    35. 'SerialInput += SerialPort1.ReadLine()
    36. pos = SerialInput.IndexOf(vbCr)
    37. If (pos >= 0) Then
    38. eineZeile = SerialInput.Substring(0, pos)
    39. posmemm = pos
    40. 'verarbeite meineDaten
    41. SerialInput = SerialInput.Substring(pos, SerialInput.Length - pos)
    42. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    43. End If
    44. End Sub
    45. Public Sub DoUpdate()
    46. ListBox1.Items.Insert(0, "Recv: " & eineZeile)
    47. TextBox2.Text = ""
    48. TextBox2.Text = SerialInput
    49. TextBox1.Text = TextBox1.Text + 1
    50. End Sub
    51. Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
    52. SerialPort1.Write(TextBox5.Text & Convert.ToChar(13) & Chr(13))
    53. End Sub
    54. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    55. ListBox1.Items.Clear()
    56. TextBox1.Text = 0
    57. TextBox2.Text = ""
    58. SerialInput = ""
    59. End Sub
    60. Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    61. If SerialPort1.IsOpen = True Then
    62. SerialPort1.Close()
    63. End If
    64. Me.Close()
    65. End Sub
    66. Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
    67. SerialPort1.Close()
    68. End Sub
    69. Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
    70. If Not SerialPort1.IsOpen Then
    71. SerialPort1.Open()
    72. End If
    73. End Sub
    74. End Class



    Das ist der Code der auf dem Mikrocontroller testhalber gesendet wird:

    VB.NET-Quellcode

    1. usart_write_str0("start\r");
    2. for( uint16_t i = 1; i < 4; i++ )
    3. for( uint16_t j = 2; j < 4; j++ )
    4. for( uint16_t k = 1; k < 4; k++ )
    5. for( uint16_t l = 2; l < 4; l++ )
    6. {
    7. sprintf( str, "%02d|%02d|%02d|%02d\r", i, j, k, l );
    8. usart_write_str0(str);
    9. }
    10. usart_write_str0("ende\r");



    So sieht die Anzeige dann aus:

    Alex0815 schrieb:

    Ich brauche ja den kompletten string bis zum CR
    Was passiert mit dem eingelesenen Text nach dem CR?
    Nimm die Initialisierung aus der Form_Load raus. Wenn dort Exceptions kommen (nicht alle) bekommst Du nix mit und bemerkst es so nicht.
    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!
    Also ich brauche jeden String der zwischen zwei CR steht, der allererste hat natürlcih keinen CR als erstes...
    So wird gesendet:

    VB.NET-Quellcode

    1. 11|22|33|44\r55|66|77|88\r99|10|11|12\r


    so brauche ich dann den String in einer Datei die ich dann weiter bearbeite:
    11|22|33|44

    dann bein näcshten mal diesen String
    55|66|77|88
    dann:
    99|10|11|12
    und so weiter:


    Du meinst also,

    VB.NET-Quellcode

    1. SerialPort1.PortName = "COM4"
    2. SerialPort1.BaudRate = 9600
    3. SerialPort1.Parity = IO.Ports.Parity.None
    4. SerialPort1.DataBits = 8
    5. SerialPort1.StopBits = IO.Ports.StopBits.One
    6. SerialPort1.Handshake = IO.Ports.Handshake.None
    7. SerialPort1.RtsEnable = True
    8. SerialPort1.DtrEnable = True


    entfernen

    und im Load Object nur

    VB.NET-Quellcode

    1. SerialPort1.NewLine = vbCr
    2. SerialPort1.Open()



    stehen lassen, webei das NewLine auch noch weg kann, das kommt noch aus der Zeit als ich es mit ReadLine versucht habe...

    Alex0815 schrieb:

    Du meinst also,
    Ich meine also, dass im Form_Load gar kein solch Code stehen sollte.
    Und dann solltest Du immer den gesamten verfügbaren Text lesen, den kannst Du dann ja am Zeilenende splitten und hast Deine Zeilen in einem Array.
    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!

    skyscater schrieb:

    Hatte mal das selbe Problem:
    klick mich
    Wenn du meine letzte kryptische Antwort nicht entziffern kannst, sag bescheid, dann erklär ichs dir und such villeicht noch den Codeabschnitt dazu heraus.
    mfg.skyscater


    Hi, ja ich glaube ich habe das gleiche Problem... Bei mir läuft es im Terminal auch 100%tig...
    Ich denke auch, dass ich den String erst mit ReadExisting sammeln muss, und dann an eine Sub übergebe wo ich sie mir dann noch in die einzelne Strings zerteile sobald ich ein "\r" erkenne.

    Im Grunde macht das aber eigentlich ja schon:

    VB.NET-Quellcode

    1. SerialInput = SerialInput + SerialPort1.ReadExisting()
    2. 'SerialInput += SerialPort1.ReadLine()
    3. pos = SerialInput.IndexOf(vbCr)
    4. If (pos >= 0) Then
    5. eineZeile = SerialInput.Substring(0, pos)
    6. 'verarbeite meineDaten
    7. SerialInput = SerialInput.Substring(pos, SerialInput.Length - pos)
    8. Me.Invoke(New EventHandler(AddressOf DoUpdate))
    9. End If



    Was hast du für ein Trennzeichen? Wie hast du das dann gelöst?

    Alex0815 schrieb:

    Im Grunde macht das aber eigentlich ja schon:
    Probier mal dies:
    DataReceived

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    2. Me.Invoke(Sub() ReceiveText())
    3. End Sub
    4. Private Sub ReceiveText()
    5. Dim ToRead As Integer = SerialPort1.BytesToRead
    6. If ToRead > 0 Then
    7. 'Neu empfangene Zeichen an die Empfangspuffer anhängen
    8. Dim Buffer(ToRead - 1) As Byte
    9. SerialPort1.Read(Buffer, 0, ToRead)
    10. TextBox1.Text &= System.Text.Encoding.Default.GetString(Buffer)
    11. End If
    12. 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!
    Hi, so hatte ich es auch schon ausprobiert, nur ich brauche den String immer bis zum CR in einer Zeile so wie beim Terminal:



    In der Form sieht es so aus:


    VB.NET-Quellcode

    1. Private Sub ReceiveText()
    2. Dim ToRead As Integer = SerialPort1.BytesToRead
    3. If ToRead > 0 Then
    4. 'Neu empfangene Zeichen an die Empfangspuffer anhängen
    5. Dim Buffer(ToRead - 1) As Byte
    6. SerialPort1.Read(Buffer, 0, ToRead)
    7. TextBox2.Text &= System.Text.Encoding.Default.GetString(Buffer)
    8. ListBox1.Items.Insert(0, "Recv: " & ByteArrayToString(Buffer))
    9. End If
    10. End Sub

    Alex0815 schrieb:

    nur ich brauche den String immer bis zum CR in einer Zeile

    VB.NET-Quellcode

    1. Dim text2() = text1.Split(Environment.NewLine)
    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!