Laden...

[erledigt] SerialPort Klasse unter Win7: Beim zweiten Mal werden keine Daten mehr empfangen

Erstellt von Daniel83 vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.268 Views
D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 12 Jahren
[erledigt] SerialPort Klasse unter Win7: Beim zweiten Mal werden keine Daten mehr empfangen

Hallo Allerseits,

ich habe ein Problem mit einem meiner Programme beim ausführen unter Win7 (32 und 64 Bit).
Unter Win XP tut es was es soll.

Das Problem hängt mit einem von mir verwendeten SerialPort zusammen. Hardware technisch verwende ich einen USB Converter.
Aus verschiedenen Stellen des Programms greife ich nach ein ander auf dieses Gerät zu. Deshalb öffne ich die Verbindung, mache meine Übertragungen und schließe es wieder.

Nun die Fehlerbeschreibung: Wenn ich das erste mal eine Verbindung herstelle, d.h. USB eingesteckt, Serialport geöffnet, senden, empfangen, schließen, Funktion Ende, funktioniert das ganze tadellos. Aber bereits beim nächsten Verwenden wird nichts mehr empfangen. Senden funktioniert weiterhin. Mit einem anderen Rechner lese ich die Daten auf dem Bus mit, es findet eigentlich eine saubere Kommunikation statt. Aber wie gesagt, es wird nichts empfangen.

Getestet habe ich zusätzlich mit einem anderen .Net bassierten Programm, welches zum Mitschreiben der Busaktivität dient. Hier ist das Verhalten identisch. Wird die Verbindung geschlossen, und wieder geöffnet, wird nicht Empfangen.

Durch entfernen des USB-Steckers und wieder hineinstecken kann das Problem gelöst werden, bis das nächste mal der Serialport geschlossen wird.

Was ich bisher versucht habe, ist dass ich mich nicht wie vorher darauf verlassen habe, dass die Instanz der Serialportklasse am ende der Funktion zerstört wird, sondern ich habe sie "von Hand'" Disposed. Dies hat leider nichts gebracht.

Gibt es hier bekannte Schwierigkeiten? Muss ich noch mehr "von Hand" aufräumen? Oder vermutet ihr ein Treiber Problem?

Die Treiber Problematik möchte ich eigentlich ausschließen, da ein C++ Programm ohne Probleme mit diesem Gerät arbeitet.

Gruß Daniel

edit: Es werden keine Exceptions geworfen. Da ich auf eine Antwort warte, erkennt das Programm selbst, dass nicht geantwortet wurde. Ich habe außerdem ein kleines tool geschrieben, um das Event verhalten zu Testen, dieses Verhält sich gleich.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 12 Jahren

Ich möchte euch noch ein wenig Code zur Verfügung stellen. Ich habe die Funktion ein wenig gekürzt, aber hoffentlich alles relevate Dringelassen.

private bool SendeEinenEingang(  )
        {
            DateTime aktuell = new DateTime();
            TimeSpan timeOut = new TimeSpan(3500000);//=>350ms

            //Erstellen einer neuen SerialPort Instanz
            SerialPort port = ErstellePort( portname );

           

            if ( port != null )
            {
                //Lese Eingang aus
                int eingang = /*hier wird die Anzahl ermittelt*/;

                //Erzeugen der fortlaufenden Nummer für den Eingang, real 1-10, 19-28
                if ( eingang > 10 )
                {
                    eingang = eingang - 8;
                }

                //Erzeugen eines schreibe Puffers, fülle mit Daten
                byte[] ausgangsPuffer = new byte[ 6 ];
                ausgangsPuffer[ 0 ] = busAdresse;
                ausgangsPuffer[ 1 ] = Convert.ToByte( eingang - 1 );
                ausgangsPuffer[ 2 ] =/*weitere Daten*/;

                /* Noch mehr Daten*/
                for(...)
                {
                    try
                    {
                        //Öffnen des SerialPorts
                        port.Open();

                        string[] ports = System.IO.Ports.SerialPort.GetPortNames();
                        bool vorhanden = false;
                        for (int i = 0; i < ports.Length; i++)
                        {
                            if (ports[i] == portname)
                                vorhanden = true;
                        }
                        if (!vorhanden)
                        {
                            return false;
                        }

                        if (port.IsOpen)
                        {
                            //Senden des Protokolls
                            port.Write(ausgangsPuffer, 0, ausgangsPuffer.Length);

                            int zaehler = 0;

                            //Hohle aktuelle Systemzeit für Timeout
                            aktuell = DateTime.Now;

                            //Warte auf genug Daten oder Timeout
                            while (!(port.BytesToRead >= bytesToRead)
                                        && ((aktuell + timeOut) > DateTime.Now))
                            { zaehler++; }

                            //Es liegen genug Daten im SerialPort Puffer
                            if ((port.BytesToRead == bytesToRead)
                                   || (port.BytesToRead > 12))
                            {
                                //Erstellen eines Eingangspuffers
                                byte[] eingangsPuffer = new byte[bytesToRead];

                                //Einlesen der empfangenen Daten
                                port.Read(eingangsPuffer, 0, eingangsPuffer.Length);

                                //Schließen des SerialPorts
                                port.Close();

                                //Festlegen ob ein Offset nötig ist, wenn ja wie groß
                                int offset = 0;
                                if (eingangsPuffer[0] != 0xBD)
                                    offset = 6;

                                //Prüfen ob die Antwort gültig ist, sost Enden
                                if (!IstKorrekteAntwort(eingangsPuffer,
                                                                ausgangsPuffer, offset))
                                {
                                    //Schließe SerialPort
                                    port.Close();
                                    //Schließe Progress Formular, aktiviere MainForm
                                    fortschrittsUebertragungsForm.Schließen(false, ref hauptForm);
                                    //Öffne Fehlermeldung
                                    ErrorMessage fehlerForm = new ErrorMessage();
                                    fehlerForm.ZeigeFehlerDialog("Fehler",
                                        "Bei der Übertragung kam es zu Komplikationen",
                                        "es wurde nicht geantwortet", true);

                                    return false;
                                }
                            }

                            else
                            {
                                //Schließe SerialPort
                                port.Close();
                                //Schließe Progress Formular, aktiviere MainForm
                                fortschrittsUebertragungsForm.Schließen(false, ref hauptForm);
                                //Öffne Fehlermeldung
                                ErrorMessage fehlerForm = new ErrorMessage();
                                fehlerForm.ZeigeFehlerDialog("Fehler",
                                    "Bei der Übertragung kam es zu Komplikationen",
                                     "es wurde nicht geantwortet", true);

                                return false;
                            }
                        
                            //Zeige den Fortschritt an
                            fortschrittsUebertragungsForm.NaechsterSchritt
                                (/*Fortschritts Handling*/);
                        }
                        else   //if ( port.IsOpen )
                        {
                            istErfolgreich = false;
                        }
                    }
                    catch (Exception e)
                    {
                        if (e is System.UnauthorizedAccessException || e is System.InvalidOperationException || e is System.IO.IOException)
                        {
                            if (e is System.InvalidOperationException)
                            {
                                //Schließe SerialPort
                                port.Close();
                            }
                            //Schließe Progress Formular, aktiviere MainForm
                            fortschrittsUebertragungsForm.Schließen(false, ref hauptForm);
                            //Öffne Fehlermeldung
                            ErrorMessage fehlerForm = new ErrorMessage();
                            fehlerForm.ZeigeFehlerDialog("Fehler",
                                "Bei der Übertragung kam es zu Komplikationen",
                                "Die USB Verbindung wurde unterbrochen. bitte überprüfen sie "
                                + "den Anschluss der Schnittstelle", true);

                            return false;
                        }
                    }    
                   
                } //for ( ...)
                port.Dispose();
                return true;
            }   //if ( port != null )
            else
            {
                return false;
            }
        }
D
201 Beiträge seit 2007
vor 12 Jahren

Hallo,

Gibt es hier bekannte Schwierigkeiten? Muss ich noch mehr "von
Hand" aufräumen? Oder vermutet ihr ein Treiber Problem?

Ich vermute eher ein Problem mit dem Treiber, denn bei mir funktioniert das mehrmalige schließen und wieder öffnen des Ports ohne Probleme unter Win7 (64Bit) und ich habe ebenfalls einen USB/Serial Converter (von FTDI).

Hast du denn einen OnBoard-Port verfügbar mit dem du testen kannst, oder einen anderen Wandler?

Gruß

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 12 Jahren

Ich habe ein anderes Programm, welches auf diese Hardware zugreift. Dieses ist in C++ geschrieben und läuft ohne Probleme, ich weiß jedoch nicht, ob dieser den SerialPort mehrfach oder nur einmal Öffnet.

Dem Treiber werde ich mich nochmal annehmen. bzw. mal eine andere Hardware Testen.

U
1.688 Beiträge seit 2007
vor 12 Jahren

Hallo,

benutze einen Sniffer wie "Portmon" (Portmon für Windows 3.02) und vergleiche Öffnen, Datentransfer und Schließen des Ports.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 12 Jahren

Danke für die Hilfe.

Unser Lieferant hat die Treibersoftware umgestellt. Mit einem älteren Treiber bin ich unter der 32 Bit Version klar gekommen. Für 64 Bit habe ich aktuell keine Treiber, da muss ich mich drum kümmern.

Portmon ist leider unter Win7 wohl nicht lauffähig und wird anscheinend von Microsoft seit 2006 nicht mehr weiterentwickelt.

Gruß Daniel