Problem mit SerialPort Read Event C#

#1452862
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
#1453068
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ß,
#1453100
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ß,
Gast #1453405
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
#1453455
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
#1453509
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ß,
#1453547
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ß,

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren