Forum: PC-Programmierung C# Serieller Port - Data Receive Event


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Naj H. (janiiix3)


Bewertung
0 lesenswert
nicht lesenswert
Nabend,

ich habe folgendes Problem.
Wenn ich mit einer Baudrate ( vom Mikrocontroller aus ) von 9600 an 
meinen Rechner sende, feuert ja direkt das entsprechende Event.
Nun habe ich sehr viel Zeit damit vebracht und herauszufinden wieso 
manchmal überhaupt "keine" Daten empfangen werden.

Wenn ich in dem Event eine Wartezeit einbaue ( WAR NUR ZUM TESTEN ) von 
10 ms läuft alles wunderbar.
Sobald ich die Baudrate vom Mikrocontroller höher setze, läuft es auch 
stabiler..

Was kann ich besser machen, damit auch bei niedrigen Baudraten meine 
Packete erkannt werden?
1
        int length              = 0;
2
        uint bytesToReceive     = 0;
3
        byte[] buffer    = new byte[250];
4
5
        private void Client_DataReceived(object sender, SerialDataReceivedEventArgs e)
6
        {
7
            /* Wenn ich hier 10ms warte, läuft es ohne Probleme..
8
               Die Daten sind dann ja auch schon alle im Eingangspuffer */
9
10
            /*  Empfangene Daten abholen
11
            */
12
            try
13
            {
14
                length += Client.Read( buffer , length , 100 );
15
            }catch{}
16
17
            /*  Kommando Start Parsen
18
             *  Rückgabewert: - 1 = Kein Start gefunden..
19
            */
20
21
            int index = parser.ParseStart(buffer);
22
            if (index != -1)
23
            {
24
                /*  Anzahl der zu empfangenen Bytes auslesen
25
                    * HIER WIRD NOCH KEIN CRC BERECHNET!
26
                    * Es könnten Übertragungsfehler nicht erkannt werden..
27
                */
28
                bytesToReceive = buffer[index + (byte)Cmd.Communication_Header_Enum.CMD_HEADER_LENGHT];
29
            }
30
31
            /*  Wurden alle Bytes empfangen?
32
                *  Wenn nicht, direkt wieder raus hier!
33
            */
34
            if (length < bytesToReceive)
35
            {
36
                return;
37
            }
38
            else
39
            {
40
                length = 0;
41
                bytesToReceive = 0;
42
            }
43
44
            /*  Kommando untersuchen..
45
            */
46
            parser.Parse( ref buffer, ref parser.CommandoParsed );
47
        }

von bluppdidupp (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde in DataReceived nur .ReadExisting() benutzen und ansonsten 
eher selbst einen Thread/BackgroundWorker verwenden und dort direkt mit 
.Read() arbeiten und DataReceived nicht nutzen.

von Kalle O. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Okay. Wieso?

von bluppdidupp (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die SerialPort-Klasse hat intern eine eigene Schleife, über die sie via 
WaitCommEvent auf Ereignisse/Daten wartet und löst dann u.a. 
DataReceived über einen ThreadPool aus.
Zumindest früher konnte es passieren, dass die SerialPort-Klasse z.B. 2 
direkt hintereinander DataReceived auslöst, beim ersten wären z.B. 10 
Bytes verfügbar, beim zweiten 30 Bytes.
Liest man im ersten nun maximal 300 Bytes aus, kann man dort ggf. direkt 
40 Bytes einlesen, dann wird im zweiten DataReceived .Read() erstmal 
hängen, weil es auf neue Daten wartet.
Ich meine mit .ReadExisting oder .Read mit .BytesToRead konnte das man 
da Probleme verhindern.
(Kann das aber auch völlig im Kopf haben - Ich habe lange nichts mit der 
SerialPort-Klasse gemacht)
Mit eigenem Thread/BackgroundWorker und Verzicht auf Nutzung von 
DataReceived hatte ich nie Probleme.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.