Hallo Leute,
Ich bin gerade dabei eine Anwendung zu schreiben wo wir
eine alte Steuerung per RS232 einbinden wollen.
Ich habe nun im .net 2.0 die SerialPort Klasse versucht zu verwenden.
Nun stosse ich aber auf das Problem, dass das DataReceived Ereignis
nicht startet.
Folgenden Code habe ich verwendet:
private void Form1_Load(object sender, EventArgs e)
{
seri = new SerialPort("COM1", 9600, Parity.None, 8,StopBits.One );
try
{
seri.Open();
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
if (!seri.IsOpen)
return;
seri.DataReceived += new SerialDataReceivedEventHandler(seri_DataReceived);
}
void seri_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort seri = (SerialPort) sender;
string a = seri.ReadExisting();
// Bearbeite a in GUI
}
Ich habe nun das Problem, dass mein Programm nicht
in seri_DataReceived kommt, obwohl Daten über die serielle
kommen. Ich habe im Hyperterminal Kabel und Anschluss überprüft,
da kommmen die Daten an.
Datenblock der auf einmal kommt:
STATION:1 + CR + LF +
PG:4 + CR + LF +
PSET:54 + CR + LF +
DIA:3 + CR + LF +
DT:14.05.2007_14:23:12 + CR + LF +
GRUNDMOMENT:__30.00 + CR + LF +
MOMENT:_234.21 + CR + LF +
WINKEL:4567 + CR + LF +
ERG:IO + CR + LF +
FC: + CR + LF
Hat wer einen Lösungsvorschlag was ich verkehrt mache?
Besten Dank für Eure Mühe,
Herbert
Hast du mal einen Breakpoint in den DataReceived-Handler gehängt? Nicht dass es sich hier um ein Threading-Problem handelt, denn der Handler wird nicht im UI-Thread aufgerufen!
Den Haltepunkt habe ich gesetzt, auch eine MessageBox als erster Aufruf war drinnen die nur sagt "Bin da" .
Aber es kommt nix.
Ich habe gerade in der MSDN gelesen, dass der Methodenaufruf
in einem zweiten Thread aufgeht, da ich aber nur wenig
Erfahrung mit Threads habe -> was macht es für einen
Unterschied?
mfg
Herbert
Einen großen. Unter 2.0 sollte dir eigentlich eine Exception entgegenballern (cross thread). Du darfst von Threads nichts auf dem GUI machen (schau mal in die FAQ, da findest du eine Anleitung).
Ist auch sichergestellt, dass der GC nicht eventuell seri abräumt?
lassen wir mal die GUI außer Acht
gegen den "Fehler" habe ich Control.CheckForIllegalCrossThreadCalls = false;
drinnen. Momentan nur ein Testprogramm!
Das Programm besteht nur aus einer Form und deren
Load Methode und der Methode für die Eventbehandlung des SerialPort.DataReceived Events.
Kann es eine fehlende/falsche Programmierung der SerialPort Klasse
sein oder habe ich das richtig gemacht?
=> Danke für den Tipp mit der FAQ, ist sehr gut beschrieben
Danke,
Herbert
Original von svenson
Einen großen. Unter 2.0 sollte dir eigentlich eine Exception entgegenballern (cross thread). Du darfst von Threads nichts auf dem GUI machen (schau mal in die FAQ, da findest du eine Anleitung).Ist auch sichergestellt, dass der GC nicht eventuell seri abräumt?
MessageBoxen lassen sich immer anzeigen, egal von welchem Thread aus.
Der Code sieht sauber und richtig aus, eigentlich sollte das so funktionieren. Verbinde mal noch das Event ErrorReceived mit einem Handler. Mit dem Hyperterminal, ok ... biste Dir sicher, dass der COMport richtig ist, dann gibt's noch Handshake, Rts und Dtr? Und dann schau' mal noch nach dem ReceivedBytesThreshold an.
Handshake habe ich lt. Anleitung auf .None gesetzt = Standard.
Über RTS und DTR habe ich keine Infos.
ReceivedBytesThreshold ist auf 1
Kurios ist an diesem PC, mit diesem Kabel bekomme
ich die Werte über das Hyperterminal herein.
Dort stelle ich Com1,9600,8,n,1 und keine Flusssteuerung ein
Interpretiere ich das so richtig:
wenn am Eingangsbuffer mindestens 1 Byte anliegt (ReceivedBytesThreshold ),
dann feuert .net 2.0 das DataReceived Event.
und ich kann über ReadExisting() den string auslesen
und weiterverarbeiten.
Gibt es einen anderen Ansatz wie man zu den Daten von der
seriellen Schnittstelle kommt?
Wäre um jede Hilfe dankbar,
Herbert
_Original von hemasek_Über RTS und DTR habe ich keine Infos.
Dann deaktivieren, falls sie true sind.
_Original von hemasek_Kurios ist an diesem PC, mit diesem Kabel bekomme
ich die Werte über das Hyperterminal herein.
Dort stelle ich Com1,9600,8,n,1 und keine Flusssteuerung ein
Ist das HyperTerminal noch eingeschaltet, wenn das Programm auf Daten warten soll? Das Terminal sendet soweit ich weiss eine Art "Hallo" in den Seriellen Port, macht das auch Dein Programm? Von alleine kommt da normalerweise nix - es ist nun mal kein Monolog sondern eine Kommunikation. 😉
_Original von hemasek_Interpretiere ich das so richtig:
wenn am Eingangsbuffer mindestens 1 Byte anliegt (ReceivedBytesThreshold ),
dann feuert .net 2.0 das DataReceived Event.
und ich kann über ReadExisting() den string auslesen
und weiterverarbeiten.
Richtig, wobei ReadExisting() eine Momentaufnahme ist und es ein paar Millisekunden später noch mehr Daten anliegen können. Das Event wird aber nur einmal gefeuert, soweit ich weiss muss dann erst wieder was gesendet werden.
_Original von hemasek_Gibt es einen anderen Ansatz wie man zu den Daten von der
seriellen Schnittstelle kommt?
Nein, aber Du kannst mal versuchen ein Thread.Sleep() zu machen nachdem Du den Port geöffnet und was gesendet hast. Dann siehste bei BytesToRead die Anzahl der empfangenen Bytes, unabhängig vom Event.
SeboStone schrieb:
Nein, aber Du kannst mal versuchen ein Thread.Sleep() zu machen nachdem Du den Port geöffnet und was gesendet hast. Dann siehste bei BytesToRead die Anzahl der empfangenen Bytes, unabhängig vom Event.
du musst ja nicht unbedingt auf das Data_Received event warten, sondern kannst dir auch eine Methode bauen, die Daten von der seriellen Schnittstelle pollt. (SerialPort.ReadExisting, .ReadLine, ...). Sobald daten von der seriellen Schnittstelle empfangen wurden, kannst du ein event feuern. Die methode lässt du in innerhalb eines eigenen Threads in einer schleife laufen.
mfg
martin
Richtig, in dem DataReceived-Event musst Du eh solange pollen, bis Du soviele Bytes wie erwartet (normalerweise weiss man wie lang eine Nachricht ist -> schau in die Protokollunterlagen) bekommen hast oder ein Timeout gefeuert wird.
Wenn die Kommunikation mit einem definierten Stopzeichen abläuft (also and jeden datensatz wird ein bestimmtes zeichen angehängt, das das ende des datensatzes markiert), kannst du SerialPort.NewLine = 'meinStopzeichen" und SerialPort.ReadLine verwenden
Danke für Eure Antworten,
Ich habe nach jedem Messwert ein CR und ein LineFeed
was ist denn da das zugehörige Stopzeichen für LF?
mfg
Herbert
hallo zusammen!
ich bin anfänger in c#.........und habe jetzt die aufgabe......."alle com-port abrufen, um die bestimmte gerät zu finden"..........ich habe alle com auf meinen pc mit der hilfe von 'port.name und using System.IO.Ports' gefunden.....aber wie kann ich mehr info über gerät aufrufen? zum beispiel 'name' oder andere info für indentität? .....
grüsse rudi
p.s.""
Wie oben schon steht, Du must in den Port was senden ... wenn Du nix in den Wald rufst, kommt auch nix 😉
Ob dem so ist, hängt einzig und allein von der Art der Kommunikation ab. Natürlich kann einer (oder beide) Teilnehmer blind Daten auf die serielle senden. Das macht jeder GPS-Empfänger so, jedes Modem, etc.!
Die Serielle schreibt keinerlei Protkoll vor.
Original von svenson
Ob dem so ist, hängt einzig und allein von der Art der Kommunikation ab. Natürlich kann einer (oder beide) Teilnehmer blind Daten auf die serielle senden. Das macht jeder GPS-Empfänger so, jedes Modem, etc.!Die Serielle schreibt keinerlei Protkoll vor.
Jep, beides richtig, hab' ich vergessen zu erwähnen. 😉
Hallo Leute,
Danke für Euer Bemühen, ich habe den Fehler nun gefunden:
Hyper Terminal lässt immer CTS Signal stehen, damit der Gegenüber
in jedem Fall sendet. Es ist soweit richtig, dass es beide Varianten gibt:
Man kann nun 2 Möglichkeiten ausschöpfen:
Ich habe mich für Var. 2 entschieden.
Folgendes funktioniert nun bei mir:
Die Serielle frage ich mit .ReadLine in einem eigenen Thread ab
und schaufle den string Wert in die GUI lt. FAQ Beitrag
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke)
mfg
Herbert
Da warst du jetzt schneller 😁
Ich wollte nämlich vorschlagen, mal mit einem Schnitstellentester (es gibt so kleine mit Leuchtdioden) mal nachzusehen, ob die ANeige bei beiden Programmen (Hyperterm und deins) gleich ist.
Mfg Hajoseb
**"Zufall ist das Pseudonym Gottes, wenn er nicht selbst unterschreiben will.” **
Anatole France
Hi,
kann es sein, dass deine Form_Load-Methode gar nicht aufgerufen wird? Ich hatte das Problem schon öfters.
Ich initiere meine Sachen jetzt immer im Konstrukor. Das geht immer.
Die DataReceived sollte immer aufgerufen werden, wenn annähernd so was wie Daten anstehen. Ich das mal ausprobiert. Funktioniert sogar wenn man nur einen Draht von der Steckdose in den COM Prot hält. Da raucht zwar mein Laptop abißerl aber sonst gehts.
Raider heißt jetzt Twix
Ich möchte hier auch noch was dazu sagen, da ich beruflich viel mit Seriellen Schnittstellen zu tun habe:
Einfach das CTS und das RTS-Signal zu verbinden birgt natürlich die Gefahr des Datenverlustes. RTS/CTS-Leitungen sind Handshake-Leitungen die die Bereitschaft der Schnittstellen anzeigen.
Sollte dein Gerät CTS/RTS unterstützen kann ich nur empfehlen das auch zu nutzen (SerialPort.Handshake = Handshake.RequestToSend).
Eventuell fehlt aber auch das DTR-Signal. Viele Geräte bestehen darauf.
rudi:
.aber wie kann ich mehr info über gerät aufrufen? zum beispiel 'name' oder andere info für indentität?
Die serielle Schnittstelle ist einfach nur eine serielle Schnittstelle. Informationen über das Gerät wirst du nur über Kommunikation mit diesem bekommen. Bei einem Modem zum Beispiel mit den entsprechenden AT-Befehlen (ATI etc.)
Das Event DataReceived sollte übrigens ganz normal funktionieren, wobei natürlich der ReceivedBytesTreshold beachtet werden muss (wie schon richtig bemerkt wurde), sollte das Gerät kein EOF-Byte senden.