none
SerialPort , Übertragung unvollständig, ohne .NET klappt es aber RRS feed

  • Frage

  • Hallo,

    ich habe ein merkwürdiges Problem beim Auslesen aus einer seriellen Schnittstelle. Ich verwende Visual Studio 2010 Ultimate mit .NET 4. Mein Rechner ist aktuell und leistungsfähig.  Mit bestimmten Endgeräten kommt es zu Übertragungslücken. Der Fehler ist reproduzierbar und immer gleich. Ich benutze einen COM-USB-Adapter. Bei einem bestimmten Gerät kommen viel zu wenig Bytes an. Ich habe den Port folgendermaßen konfiguriert:

     

     po = New SerialPort("COM4", 4800, Parity.None, 8, 1)
    
        po.ReadTimeout = 2000
        po.Handshake = Handshake.None
        po.ReceivedBytesThreshold = 38
        po.ReadBufferSize = 100
        po.DiscardNull = False
    

    Die Einstellungen sind auch alle korrekt, und funktionieren bei anderen Geräten einwandfrei. Auch mit anderen Programmen, die kein .NET benutzen klappt es immer.

    Ich benutze den Port folgendermaßen:

    po.DiscardInBuffer()
          po.Write(bytes, 0, 10)
          System.Threading.Thread.Sleep(250)
          Dim result(38) As Byte
          po.Read(result, 0, 38)
    

    Auch ein Verlängern der Wartezeit ändert nichts. Die Daten kommen immer verstümmelt an.

    Ich kann mir das wirklich nicht erklären und bin für jede Hilfe dankbar.

     

    Viele Grüße

    Montag, 4. April 2011 14:24

Antworten

  • Hallo

    Dein Programm funktioniert einwandfrei....

    Die sreenshots:

     

    Remote Computer:

    Kein Fehler Vorhanden

     

    schöne Grüße Ellen

     

    Imports System.IO.Ports
    
    
    Module Module1
    
      Sub Main()
        Dim mySerialPort As New SerialPort("COM4")
    
        mySerialPort.BaudRate = 4800
        mySerialPort.Parity = Parity.None
        mySerialPort.StopBits = StopBits.One
        mySerialPort.DataBits = 8
        mySerialPort.Handshake = Handshake.None
        mySerialPort.ReceivedBytesThreshold = 38
        AddHandler mySerialPort.DataReceived, AddressOf DataReceviedHandler
    
        mySerialPort.Open()
        Dim bytes() As Byte = New Byte() {0, 0, 0, 0, 98, 0, 0, 232, 227, 5}
        mySerialPort.Write(bytes, 0, 10)
        Console.WriteLine("Press any key to continue...")
        Console.WriteLine()
        Console.ReadKey()
    
        mySerialPort.Close()
      End Sub
    
      Private Sub DataReceviedHandler(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
        Dim sp As SerialPort = CType(sender, SerialPort)
        Dim indata As String = sp.ReadExisting()
        Console.WriteLine("Data Received:")
        Console.Write(indata)
      End Sub
    
    
    
    End Module
    
    

    Ich benutze/ I'm using VB2008 & VB2010
    Freitag, 29. April 2011 21:00

Alle Antworten

  • Hallo rfalk,

    Nur mal zum Verständnis vorab. Pollst du gegen die Schnittstelle in einem separaten Thread?

     

    Viele Grüße
    Holger M. Rößler


    Montag, 4. April 2011 16:55
  • Nein. Ich habe dafür keinen eigenen Thread. War bisher auch nie nötig.
    Montag, 4. April 2011 17:59
  • Hallo rfalk.

    Das bedeutet du gehst über das DataReceived Event?!?!

    Achja, was mich etwas stutzig macht ist, dass es lt. deiner Fehlerbeschreibung nur mit "bestimmten Endgeräten" zu Problemen kommt. Dass heisst dass mit diesem Code andere Endgeräte funktionieren?

    Schildere bitte das mal etwas genauer, sonst muss ich meine Hellseherkugel aus dem Schrank holen. ;)

    Vielen Dank.

    Viele Grüße
    Holger M. Rößler

     

    Montag, 4. April 2011 18:17
  • Okay ich schilder es mal etwas genauer:

     

    Konfiguration: Gerät an Bus-Master A an meinem USB-Anschluss

    Test unter Linux: 38 Bytes Antwort, einwandfrei

    Test unter Windows 7 mit Tool: 38 Bytes Antwort, einwandfrei

    Test mit altem VB 6.0 Programm: 38 Bytes Antwort, einwandfrei

    Mein Code: 38 Bytes Antwort, einwandfrei

     

    Konfiguration: Gerät an Bus-Master B an meinem USB-Anschluss

    Test unter Linux: 38 Bytes Antwort, einwandfrei

    Test unter Windows 7 mit Tool: 38 Bytes Antwort, einwandfrei

    Test mit altem VB 6.0 Programm: 38 Bytes Antwort, einwandfrei

    Mein Code: 16 Bytes Antwort (und zwar immer genau 16, aber die sind bis dahin auch alle richtig), fehlerhaft

    Ich nutze auch das Event nicht, der relevante Code steht dort schon. Mehr habe ich nicht gemacht. Ich kann bis jetzt nur festhalten: Meine Anfrage kommt vollständig und richtig beim Gerät an, sonst würde es gar nicht antworten. Eine Mutmaßung von mir ist, dass die Antwort auch physikalisch nicht auf meinem Rechner ankommt, wenn der Fehler aufritt. Der Adapter blinkt auch weniger, wenn ich das richtig beobachte. Das macht die Sache für mich noch kurioser.

    Update: Ich habe es jetzt mit folgendem Code nochmal probiert, wieder gleiches Ergebnis. Es kommen nur 16 oder manchmal 17 Bytes an.

    Imports System
    Imports System.IO.Ports
    
    Class PortDataReceived
      Public Shared Sub Main()
        Dim mySerialPort As New SerialPort("COM4")
    
        mySerialPort.BaudRate = 4800
        mySerialPort.Parity = Parity.None
        mySerialPort.StopBits = StopBits.One
        mySerialPort.DataBits = 8
        mySerialPort.Handshake = Handshake.None
        mySerialPort.ReceivedBytesThreshold = 38
        AddHandler mySerialPort.DataReceived, AddressOf DataReceviedHandler
    
        mySerialPort.Open()
        Dim bytes() As Byte = New Byte() {0, 0, 0, 0, 98, 0, 0, 232, 227, 5}
        mySerialPort.Write(bytes, 0, 10)
        Console.WriteLine("Press any key to continue...")
        Console.WriteLine()
        Console.ReadKey()
       
        mySerialPort.Close()
      End Sub
    
      Private Shared Sub DataReceviedHandler(
                ByVal sender As Object,
                ByVal e As SerialDataReceivedEventArgs)
        Dim sp As SerialPort = CType(sender, SerialPort)
        Dim indata As String = sp.ReadExisting()
        Console.WriteLine("Data Received:")
        Console.Write(indata)
      End Sub
    End Class


    Montag, 4. April 2011 20:19
  • hi,

    Je nach OS kannst du dir mit PortMon die Kommunikation auf serielleler Ebene anschauen und vergleichen:

    http://technet.microsoft.com/de-de/sysinternals/bb896644


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Dienstag, 5. April 2011 09:01
  • Hallo,

    Portmon ist unter meinem Windows 7 nicht lauffähig. Ich habe stattdessen 232Analyzer benutzt.

    http://www.232analyzer.com/232default.htm

    Ergebnis: Alles funktioniert und kommt an. Nach spätestens 250 ms sind die gewünschten 38 Byte da.

    Mit meinem Code leider immer noch nicht.


    Dienstag, 5. April 2011 09:57
  • Hallo,

    versuche die Ausgabe doch mal in einem "nebenbei" Thread zu machen ()BeginInvoke). Bei mir in c# sieht das so aus:

          
       
        string test2;
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            test2 = serialPort1.ReadLine();
            
          this.BeginInvoke(new EventHandler(DoUpdate));
        }
    
        private void DoUpdate(object s, EventArgs e)
        {
            label2.Text = test2;  
        }
    
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
          //Schließen der seriellen Schnittstelle
          serialPort1.Close();
        }
    
    ...bei mir hatte es so geklappt.

    Dienstag, 5. April 2011 11:07
  • Werden sie auch von deinem Programm gelesen? Setze mal den Threshold runter:
     mySerialPort.ReceivedBytesThreshold = 1

    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Dienstag, 5. April 2011 11:23
  • @Stefan Hoffmann

     

    Leider kein Effekt. Immer noch das gleiche. Jetzt wird das Event dreimal ausgelöst. jeweils mit 6, 7 oder 5 neuen Bytes pro Event. Da bin ich dann wieder bei meinen 16-18 Bytes.

    Dienstag, 5. April 2011 11:45
  •  Private Shared Sub DataReceviedHandler(
          ByVal sender As Object,
          ByVal e As SerialDataReceivedEventArgs)
      Dim sp As SerialPort = CType(sender, SerialPort)
      Dim indata As String = sp.ReadExisting()
      Console.WriteLine("Data Received:")
      Console.Write(indata)
     End Sub
    
    

     

    Hallo, ich gehe mal an den Code.

    Mach mal bevor Du sp.ReadExisting ausführst das hier

    Dim buf as Integer = sp.BytesToRead

    Damit erhälst Du die tatsächlich im Buffer aufgelaufene Byteanzahl. Ich gehe davon aus die berträgt 38, denn

    das datareceived Event wird erst ausgelöst wenn 38 bytes im Buffer stehen. Das legst fest mit dem threshold = 38

    Versuch mal

    schöne Grüße Ellen

     

     


    Ich benutze/ I'm using VB2008 & VB2010
    Freitag, 29. April 2011 12:58
  • Hallo

    Dein Programm funktioniert einwandfrei....

    Die sreenshots:

     

    Remote Computer:

    Kein Fehler Vorhanden

     

    schöne Grüße Ellen

     

    Imports System.IO.Ports
    
    
    Module Module1
    
      Sub Main()
        Dim mySerialPort As New SerialPort("COM4")
    
        mySerialPort.BaudRate = 4800
        mySerialPort.Parity = Parity.None
        mySerialPort.StopBits = StopBits.One
        mySerialPort.DataBits = 8
        mySerialPort.Handshake = Handshake.None
        mySerialPort.ReceivedBytesThreshold = 38
        AddHandler mySerialPort.DataReceived, AddressOf DataReceviedHandler
    
        mySerialPort.Open()
        Dim bytes() As Byte = New Byte() {0, 0, 0, 0, 98, 0, 0, 232, 227, 5}
        mySerialPort.Write(bytes, 0, 10)
        Console.WriteLine("Press any key to continue...")
        Console.WriteLine()
        Console.ReadKey()
    
        mySerialPort.Close()
      End Sub
    
      Private Sub DataReceviedHandler(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
        Dim sp As SerialPort = CType(sender, SerialPort)
        Dim indata As String = sp.ReadExisting()
        Console.WriteLine("Data Received:")
        Console.Write(indata)
      End Sub
    
    
    
    End Module
    
    

    Ich benutze/ I'm using VB2008 & VB2010
    Freitag, 29. April 2011 21:00