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


von Jan H. (janiiix3)


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)


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)


Lesenswert?

Okay. Wieso?

von bluppdidupp (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.