Forum: PC-Programmierung Problem mit SerialPort Read Event C#


von Pier S. (bigpier)


Lesenswert?

Hallo Freunde,
habe schon wieder ein Problem wo ich keinen Rat weiß!
Ich habefolgenden Code in in meinem Read Event stehen!
1
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
2
        {
3
            byte[] array = new byte[100];
4
            serialPort1.Read(array, 0, 100);
5
            PrintStart(array);
6
        }

Aber ob ich nun 10 Byte  oder 30 Byte an mein Program sende (Serielle)
ich empfange laut Debugger immer zuerst 7 Und danach gleich nochmal den 
rest der gesendeten Byts !!
Was mach ich Falsch ????

Danke für Eure Hilfe


Peter

von Oliver R. (superberti)


Lesenswert?

Du machst nix falsch. Die Stückelung, in der die Events ausgelöst 
werden, hängt von der Hardware, den Treibern, vom .NET-Framework und der 
Größe der ganzen Puffer dazwischen ab. Also nicht vorhersehbar.
Wichtig ist nur, dass alle Daten ankommen, zusammensetzen musst Du sie 
selbst.

Gruß,

von Arc N. (arc)


Lesenswert?

Oliver R. schrieb:
> Du machst nix falsch. Die Stückelung, in der die Events ausgelöst
> werden, hängt von der Hardware, den Treibern, vom .NET-Framework und der
> Größe der ganzen Puffer dazwischen ab. Also nicht vorhersehbar.

Fast, man kann einstellen (ReceivedBytesThreshold) wie viele Bytes 
mindestens angekommen sein müssen, bevor DataReceived ausgelöst wird.

> Wichtig ist nur, dass alle Daten ankommen, zusammensetzen musst Du sie
> selbst.
>
> Gruß,

von Pier S. (bigpier)


Lesenswert?

Danke für Eure Antworten auch wenn ich zugeben muß mir wäre lieber 
gewesen ich hätte einen Fehler gemacht !!!

Dann werd ich mir gedanken machen wie ich mein Problem löse!!

Danke Gruß

Peter

von Hannes (Gast)


Lesenswert?

hi, geht mir genauso. mir wäre es am liebsten, wenn nach jedem 
empfangenen byte eine art interrupt ausgelöst werden würde. wer mal die 
serielle schnittstelle in visual basic 6.0 angesprochen hat, und dann 
auf .net umgestiegen ist wird mich verstehen. in vb 6.0 war es 
wesentlich einfacher die daten zu empfangen. ich bleibe weiterhin daran, 
mich mit mittlerweile .net 3.5 anzufreunden und die schnittstelle 
vernüftig zum laufen zu bekommen. gerade wenn man mit dem compact 
framework zu tun hat. im normalen .net framework kann man ja immer noch 
das gute alte ocx steuerelement von vb einbinden und damit arbeiten.

mfg hannes

von Pier S. (bigpier)


Lesenswert?

Ja ich glaub ich habe eine lösung bin grad beim testen!!

von Pier S. (bigpier)


Lesenswert?

So scheint zu funktioniren
1
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
2
        {
3
            byte[] array = new byte[100];
4
            int i=0;
5
            do
6
            {
7
                array[i] = (byte)serialPort1.ReadByte();
8
                i++;
9
            }
10
            while ((i != 80)&&(tick!=100));
11
            PrintStart(array);
12
        }
Wenn jemand eine bessere lösung hat ich bin immer Neugirig !!

Gruß
Peter

von Oliver R. (superberti)


Lesenswert?

Hi,

ihr müßt mal grundsätzlich unterscheiden zwischen eventgesteuertem 
Empfang der seriellen Daten und (blockierendem) Lesen mit Timeout.
Oftmals ist das Lesen mit Timeout die einfachere und auch zweckmäßigere 
Variante, aber genau das wird mit der SerialPort-Klasse gerade NICHT 
unterstützt (zumindest bis .NET2.0).
Das Windows-API kann das natürlich alles und ich habe mir seinerzeit 
tatsächlich eine Klasse extra dafür geschrieben. Macht aber nicht 
wirklich Spaß den ganzen Win32-API-Kram zu kapseln, man bekommt 
ziemliche Probleme mit der Abbildung der alten API-Structs (z.B. der DCB 
als gepackte Struktur) in .NET.
Alternativ kann man natürlich eine State-Machine entwerfen, die in dem 
Empfangsevent die Daten zwischenspeichert und erst ab einer bestimmten 
Gesamtmenge irgendetwas auslöst. Scheint mir hier einfacher und 
zweckmäßiger.

Gruß,

von Pier S. (bigpier)


Lesenswert?

Oliver R.
Was sagst du zum obigen Code ???

Gruß
Peter

von Oliver R. (superberti)


Lesenswert?

Hi,

obigen Code halte ich für sehr problematisch, da der Event (wie Du ja 
schon festgestellt hast) mehr als einmal pro Sendung aufgerufen wird. Du 
liest aber jedesmal SYNCHRON eine bestimmte Anzahl an Bytes, spätestens 
beim zweiten Event gibt's nix mehr zu Lesen.
Die Alternative habe ich ja schon geschrieben: In den Events so lange 
die Daten sammeln, bis Du alle Deine Bytes zusammen hast. Z.B.

Member-Vars:
private byte[] array=new byte[1024];
private int TotalRead=0;

private void serialPort1_DataReceived(object sender, 
System.IO.Ports.SerialDataReceivedEventArgs e)
{
  TotalRead+=serialPort1.Read(array, TotalRead, 100);
  if (TotalRead>=AnzahlMeinerBytesDieIchLesenWill)
  {
    PrintStart(array);
    // Falls Rest vorhanden an den Anfang von Array kopieren
    // TotalRead=Restgröße
  }
}

ODER Du verwendest gar keine Events und liest einfach Byte für Byte mit 
SerialPort.ReadByte() und setzt das ReadTimeout entsprechend. Nicht sehr 
effizient aber eventuell für Deine Zwecke vollkommen ausreichend.

Gruß,

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.