Hallo,
ich bin dabei, mit C# eine Anwendung zu schreiben, die via Serial Port
(FT232R) mit einem externen Gerät kommuniziert. Interessant ist nur die
Richtung Gerät -> PC, weil da ordentlich Daten übertragen werden. Zur
Zeit benutze ich die .NET SerialPort Klasse mit den Einstellungen 256000
Baud, 8N1 und arbeite mit DataReceived_Event wie folgt:
1
public void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
Folgende Probleme haben sich ergeben, bei denen ich nicht weiterkomme:
Ich habe festgestellt, dass das Event während der Kommunikation immer
wieder auch dann gefeuert wird, wenn gar keine Daten im Puffer sind
(Bytes2Read = 0), so etwa jedes 2-3 Mal ist das der Fall. Kann das mit
dem FTDI chip zutun haben? Das größere Problem habe ich aber mit dem
Handshake.
Ich habe Handshake mit
1
sp.Handshake = Handshake.RequestToSend;
eingestellt.
Aber selbst wenn ich einen Pufferüberlauf erzwinge (Event abmelden)
wird RTS nicht gesetzt. Manuell kann ich sie mit
1
sp.EnableRTS = wert;
setzten. Woran liegt das?
Müsste ich hier die FTDI D2XX.dll benutzen?
Grüße, Alex
Das kann ich ja mal testen. Allerdings sagt die MSDN dazu:
Eof - Das Dateiendezeichen wurde empfangen und im Eingabepuffer
platziert.
BytesToRead ist aber 0.
Damit kann ich aber eigentlich auch leben. Mein eigentliches Problem ist
das oben beschriebene Handshake. Vielleicht hat ja dazu noch jemand eine
Idee.
Grüße, Alex
kann es ein das du das Event 2 registriert hast? Dann würde beim 2.Event
keine Daten mehr vorhanden sein.
Ich habe auch schon einiges mit FT232R und C# gemacht, mir ist das noch
nie aufgefallen das nach einen Event keine Daten gekommen sein.
Mittlerweile nehme ich kaum noch den Event, ich verwende einen eigenen
Thread und mache ein normales Read, da hat man das Timeout gleich unter
Kontrolle.
Hallo Peter,
danke für die Antwort. Das Event ist definitiv nur einmal registriert.
Ich hab ein klieines Testprogramm geschrieben, das nur ein paar Zeilen
Code enthält.
Fällt dir zu der Handskake-Problematik noch was ein? Bin auch kurz
davor, den Port mit einem Timer zu pollen. Wie realisierst du das mit
dem Extra-Thread, auch als Timer?
Grüße, Alex
Alexander H. schrieb:> Fällt dir zu der Handskake-Problematik noch was ein?
nein, habe ich noch nie verwendet.
> Bin auch kurz> davor, den Port mit einem Timer zu pollen.
für was willst du den pollen?
> Wie realisierst du das mit> dem Extra-Thread, auch als Timer?
nein, read blockiert ja bis Daten da sind, oder ein Timeout auftritt.
Alexander H. schrieb:> Eof - Das Dateiendezeichen wurde empfangen und im Eingabepuffer> platziert.>> BytesToRead ist aber 0.
Das ist das normale Verhalten. Das EOF-DataReceived wird einfach
unmittelbar nach einem Chars-DataReceived Event ausgelöst, womit man das
EOF-Char dann schon weggelesen hat. Das EOF-DataReceived ist quasi nur
eine Art "Marker" und kann völlig ignoriert werden.
>Aber selbst wenn ich einen Pufferüberlauf erzwinge (Event abmelden)>wird RTS nicht gesetzt. Manuell kann ich sie mit
Wie lange testest du das denn? Beachtet werden muss noch dass auch der
Treiber ggf. noch ordentlich Daten puffern kann und "schick mir erstmal
nichts mehr" dadurch ggf. erst sehr spät kommen kann.
Oder gehen schon Daten verloren?
Guten Morgen,
ich sende kilobyteweise Daten. Im Moment arbeite ich nur mit einem
kleinen Testprogramm, um den Problemen mit dem SerialPort auf die Spur
zu kommen und das Handshake auf die Reihe zu bekommen. Da gehen keine
Daten verloren. In der eingentlichen Anwendung gehen dann Daten
verloren, wenn sie auf einem alten Rechner (Single-Core, XP) läuft. Auf
einem etwas schnelleren Rechner passiert nichts.
Zum Handshake habe ich folgendes probiert: Handshake für den Port auf
RTS gesetzt, kein Event aboniert und den Port mit Daten geflutet. Da
hätte, wenn es denn geht, irgendwann die RTS-Leitung mal den Pegel
ändern müssen.
Ich habe mal noch etwas recherchiert, Eof scheint beim Serial Port
obsolet zu sein, ist ein Relikt aus älteren Zeiten.
Grüße, Alex
bluppdidupp schrieb:> Das ist das normale Verhalten. Das EOF-DataReceived wird einfach> unmittelbar nach einem Chars-DataReceived Event ausgelöst,
blöde frage, woher soll denn bei Seriell ein EOF kommen, wenn man Daten
im Binary Modus überträgt?
Ich hab das jetzt mal ausprobiert. Wenn der Puffer leer ist beim Event,
ist der EventType tatsächlich Eof. Aber das hieße ja, dass Bytes, die
Eof entsprächen, einfach verschluckt würden, was ja auch nicht sein
darf. Ich vermute aber eher, das nach einem Datenblock, der Eof
enthielt, nochmal ein Event kommt, das dann das Eof signalisiert. Alles
andere wäre ja Unsinn.
Aber wie schon gesagt, das ist für mich eher nebensächlich. Mein Problem
ist das Handshake.
Grüße, Alex
Peter II schrieb:> blöde frage, woher soll denn bei Seriell ein EOF kommen, wenn man Daten> im Binary Modus überträgt?
Das liegt wohl daran, das bei MS da wohl jemand zu tief ins Glas
geschaut hat ;D
Es wird gesetzt:
this.dcb.EofChar = 26; // ohne Relevanz ;D
this.dcb.EvtChar = 26; // wird unnötigerweise mit WaitForCommEvent
"abgefragt" und wird an folgender Stelle dann als Eof ausgelöst:
1
// System.IO.Ports.SerialStream.EventLoopRunner
2
private void CallReceiveEvents(object state)
3
{
4
// [...]
5
if (serialStream.DataReceived != null)
6
{
7
if ((num & 1) != 0)
8
{
9
serialStream.DataReceived(serialStream, new SerialDataReceivedEventArgs(SerialData.Chars));
10
}
11
if ((num & 2) != 0)
12
{
13
serialStream.DataReceived(serialStream, new SerialDataReceivedEventArgs(SerialData.Eof));
Alexander H. schrieb:> ch vermute aber eher, das nach einem Datenblock, der Eof> enthielt, nochmal ein Event kommt, das dann das Eof signalisiert. Alles> andere wäre ja Unsinn.
Nein, beim vorangegangenen DataReceived-Event war das EOF (0x1A) schon
mit dabei - Geht also nicht verloren.
Zum Handshake-Problem kann ich sonst leider auch nichts weiter
beitragen, damit habe ich bislang nichts gemacht. Ein Board mit dem
ft232r hätte ich zwar rumliegen, da könnte ich aber frühestens am
Wochenende mal mit rumprobieren.
Wenn Du das mal machen könntest, wäre das natürlich toll. Wie gesagt,
ich sehe noch eine Chance in der Verwendung des D2XX treibers von FTDI.
Grüße, Alex
Was erhoffst du dir denn von dem Handshake?
Scheinbar verwende es ja kaum jemand, ich wüsste auch nicht wozu man es
in der Richtung µC -> PC brauchen sollte. Der PC ist schnell genug um
die Paar Bytes zu verarbeiten.
Naja, offensichtlich ja nicht. Die alte Mühle, die ich hier zu
Testzwecken rumstehen habe, packt es nicht. Andere Rechner schaffen es,
deshalb würde ich den FTDI als Flaschenhals mal ausschließen.
Alexander H. schrieb:> Naja, offensichtlich ja nicht. Die alte Mühle, die ich hier zu> Testzwecken rumstehen habe, packt es nicht. Andere Rechner schaffen es,> deshalb würde ich den FTDI als Flaschenhals mal ausschließen.
oder Programmierfehler. Man kann ich C# auch viele Fehler machen, damit
schafft es dann ein aktuell PC nicht mehr.
z.b. das ständig hinzufügen der Daten an ein Array. Oder das byteweise
verarbeiten, wenn es auch blockweise geht.
Auch das arbeiten mit dem Event bedeutet einen gewissen Overhead.
Kannst du etwas mehr von dem Programm zeigen?
catch (Exception exc) { /*throw new Exception(exc.Message, exc);*/ }
20
this.portResult.GetFrameFromBufferAsynch();
21
}
GetFrameFromBufferAsynch läuft dann in einem eigenen Thread, FrameBuffer
ist eine ConcurrenQueue. Ich weiß nicht, wo ich das noch straffen soll.
Ich verweise mal noch auf Thread www.mikrocontroller.net/topic/338068
So hat alles begonnen.
Grüße, Alex
Alexander H. schrieb:> GetFrameFromBufferAsynch läuft dann in einem eigenen Thread, FrameBuffer> ist eine ConcurrenQueue. Ich weiß nicht, wo ich das noch straffen soll.
dann finde ich das ganze über den Event schon sehr umständlich. Warum
erst alles über ein Event einlesen, dann in eine neue Liste stecken die
dann wieder über eine Thread verarbeitet wird.
mach doch gleich alles in dem Thread, oder ist selber so langsam das er
die Daten nicht schnell genug verarbeiten kann?
bluppdidupp schrieb:> Ein Board mit dem> ft232r hätte ich zwar rumliegen, da könnte ich aber frühestens am> Wochenende mal mit rumprobieren.
Da muss ich wohl noch ein Wochenende schieben ;D