hallo,
habe ein problem mit meiner seriellen schnittstelle.
diese hat folgende eckdaten:
Kartenleser
Port: COM1
Baud: 9600
Parity: Even
Stopbit: 1
Habe ein C# Projekt(.Net2, VC# Express 2005 ) erstellt, System.IO.Ports eingefügt.
dann habe ich aus den Komponeneten ein Serialport1 in mein Form gezogen.
Dort habe ich die obigen Einstellungen getätigt.
Nun stehe ich ziemlich an, es gibt zwar tausende möglichekeiten und Varianten im Inet, ich verstehe aber nicht ganz, wann ich welche Möglichkeit in Erwägung ziehen kann...
Ich möchte das Programm ausführen und dann per Klick auf einen Button aufgefordert werden, um eine Karte darüberzuziehen. Das soll mit einem Timeout von 10 Sekunden versehen sein. Danach ausgabe der eingelesen Daten in einem Label...
Mein Ansatz:
ich habe in der public form
serialPort1.Open();
eingegeben und auf dem Button, mit dem ich das ereignis auslöse:
label1.Text = serialPort1.ReadLine();
. Weiss da jemand Rat?
Ich bin schon relativ verzweifelt...
Vielen Dank schon im voraus,
LG
Richi
Ich denke, du musst schon etwas mehr Energie reinstecken, damit sich jemand motiviert fühlt zu helfen.... es riecht einfach zu sehr danach die Arbeit auf andere abzuwälzen (auch wenn das vielleicht gar nicht deine Intention ist).
Vielleicht machst du einfach mal ein paar Spiel-Projekte oder analysierst fremde Code-Beispiele bevor du dein Problem angehst.
ich möchte auf jeden fall keine fertige lösung. mein problem ist nur, dass ich mich mit der vielzahl an lösungen überfordert sehe. teilweise funktionieren sie auch wiederum nicht unter vc# express....
gibt es denn eine solides buch, url oder ähnliches, das unter anderem sockets, die verwendung von system.io und ähnliches unter verwendung von .net2 erklärt?
in der hoffnung, hilfe zu finden....
Teste doch erst mal mit einem Terminalprogramm (Hyperterminal ...), ob der Leser funktioniert.
So wie Du das beschrieben hast, solltest Du erst die Karte lesen und dann den Button klicken, denn das ReadLine() im Click-Ereignis läuft sonst ins Leere.
im hyperterminal funktioniert es problemlos. bei auflegen der karte erscheinen die ausgelesenen zeichen...
es sind immer exakt 24 zeichen, die ausgelesen werden - zahlen und buchstaben...
nach dem klick auf den button hängt das programm... kann es sein, dass ich auch noch eine art timeout definieren muss?
Womit wird denn der Datensatz abgeschlossen? Evtl. mal mit SerialPort.NewLine experimentieren.
es endet mit einem Enter.
Habs so Probiert:
SerialPort1.ReadTo((Char)13);
doch irgendwie hängt das form sobald ich auf den button klicke...
Was kommt genau? "\r\n", "\r", "\n"? ReadLine liest bis zum angegebenen NewLine. Das ist standardmäßig "\n".
Du benutz doch die SerialPort Komponente ?
Wo führst du das readline aus?
Wenn du es direkct nach dem Button klick ausführst könnte es sein das noch keine Daten zum lesen das sind.
Benutze das Event des SerialPort "OnDataRecived" und führe darin das readline aus.
wie mache ich es denn, dass ich einfach ab dem klick oder gleich bei programmstart an com1 horche? sobald etwas ausgelesen wird, gibt er es mir dann in einem label oder textfeld aus...
kann man dazu die timer_tick komponente verwenden?
readline wir im button_klick event ausgeführt...
ondatareceived werde ich testen. wird das auch als private void ausgeführt?
Hallo schnurzli,
es gibt eine Methode in einer Windows-API dll (ich glaube es ist die kernel32.dll, aber auswendig weiss ich es grad auch nicht), die Methode heisst jedenfalls CreateFile.
Die kannst Du benutzen um den seriellen Port quasi als "File" zu öffnen. Da kannst dann ganz normal reinschreiben oder draus lesen.
Such einfach mal bei Codeproject, da gibt es einen Artikel dazu, der erklärt wie man genau auf dieser Methode aufbauend von .NET aus auf die RS232 Schnittstelle kommt.
Das .NET Framework selbst bietet leider keinen direkten Zugang, da man das neuerdings bei Microsoft wohl als Sicherheitsrisiko einstuft.
"It is not wise to be wise" - Sun Tzu
Für alle Probleme, die im Zusammenhang mit serieller Kommunikation auftreten gibt es ein tolles Tool namens "PortMon".
Kann man hier downloaden:
http://www.sysinternals.com/utilities/portmon.html
Zeigt alle Daten an, die irgendwie über die serielle Schnittstelle flitzen. Daran kann man dann gut erkennen, ob man vielleicht ewig auf ein Zeichen wartet, was vielleicht nie kommt...
hallo,
habe portmon gestartet und dann auch etwas eingelesen...
die ausgabe funktioniert noch nicht in dem form...
laut dem portmon werden die daten alle richtig übertragen... auch die einstellungen, 9600,7, even, 1...
ich weiss nicht mehr weiter...
ich habe versucht, ondatareceived zu inkludieren, jedoch wird der code nicht angenommen...
hier das logfile:
0 0.00006509 rs232.vshost.ex IRP_MJ_CREATE Serial0 SUCCESS Options: Open
1 0.00000363 rs232.vshost.ex IOCTL_SERIAL_GET_PROPERTIES Serial0 SUCCESS
2 0.00000475 rs232.vshost.ex IOCTL_SERIAL_GET_MODEMSTATUS Serial0 SUCCESS
3 0.00000307 rs232.vshost.ex IOCTL_SERIAL_GET_BAUD_RATE Serial0 SUCCESS
4 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial0 SUCCESS
5 0.00000279 rs232.vshost.ex IOCTL_SERIAL_GET_CHARS Serial0 SUCCESS
6 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_HANDFLOW Serial0 SUCCESS
7 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_BAUD_RATE Serial0 SUCCESS
8 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial0 SUCCESS
9 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_CHARS Serial0 SUCCESS
10 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_HANDFLOW Serial0 SUCCESS
11 0.00001201 rs232.vshost.ex IOCTL_SERIAL_SET_BAUD_RATE Serial0 SUCCESS Rate: 9600
12 0.00000643 rs232.vshost.ex IOCTL_SERIAL_SET_RTS Serial0 SUCCESS
13 0.00000670 rs232.vshost.ex IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
14 0.00000475 rs232.vshost.ex IOCTL_SERIAL_SET_LINE_CONTROL Serial0 SUCCESS StopBits: 1 Parity: EVEN WordLength: 7
15 0.00000279 rs232.vshost.ex IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:1a ERR:3f BRK:3f EVT:1a XON:11 XOFF:13
16 0.00000838 rs232.vshost.ex IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:44 XonLimit:1024 XoffLimit:1024
17 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_BAUD_RATE Serial0 SUCCESS
18 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial0 SUCCESS
19 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_CHARS Serial0 SUCCESS
20 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_HANDFLOW Serial0 SUCCESS
21 0.00001201 rs232.vshost.ex IOCTL_SERIAL_SET_BAUD_RATE Serial0 SUCCESS Rate: 9600
22 0.00000643 rs232.vshost.ex IOCTL_SERIAL_SET_RTS Serial0 SUCCESS
23 0.00000643 rs232.vshost.ex IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
24 0.00000475 rs232.vshost.ex IOCTL_SERIAL_SET_LINE_CONTROL Serial0 SUCCESS StopBits: 1 Parity: EVEN WordLength: 7
25 0.00000279 rs232.vshost.ex IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:1a ERR:3f BRK:3f EVT:1a XON:11 XOFF:13
26 0.00000475 rs232.vshost.ex IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:44 XonLimit:1024 XoffLimit:1024
27 0.00000670 rs232.vshost.ex IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
28 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_BAUD_RATE Serial0 SUCCESS
29 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial0 SUCCESS
30 0.00000223 rs232.vshost.ex IOCTL_SERIAL_GET_CHARS Serial0 SUCCESS
31 0.00000251 rs232.vshost.ex IOCTL_SERIAL_GET_HANDFLOW Serial0 SUCCESS
32 0.00001201 rs232.vshost.ex IOCTL_SERIAL_SET_BAUD_RATE Serial0 SUCCESS Rate: 9600
33 0.00000670 rs232.vshost.ex IOCTL_SERIAL_CLR_RTS Serial0 SUCCESS
34 0.00000643 rs232.vshost.ex IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
35 0.00000475 rs232.vshost.ex IOCTL_SERIAL_SET_LINE_CONTROL Serial0 SUCCESS StopBits: 1 Parity: EVEN WordLength: 7
36 0.00000279 rs232.vshost.ex IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF:1a ERR:3f BRK:3f EVT:1a XON:11 XOFF:13
37 0.00000838 rs232.vshost.ex IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake:0 Replace:4 XonLimit:1024 XoffLimit:1024
38 0.00000643 rs232.vshost.ex IOCTL_SERIAL_CLR_RTS Serial0 SUCCESS
39 0.00000279 rs232.vshost.ex IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI:-1 RM:-1 RC:-2 WM:0 WC:0
40 0.00000419 rs232.vshost.ex IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING
41 0.00000307 rs232.vshost.ex IOCTL_SERIAL_SET_QUEUE_SIZE Serial0 SUCCESS InSize: 1024 OutSize: 2048
42 41.18181473 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
43 0.00000838 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
44 0.00753979 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
45 0.00000866 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
46 0.00799180 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
47 0.00000838 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
48 1.91058249 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
49 0.00000950 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
50 0.00000000 rs232.vshost.ex IOCTL_SERIAL_WAIT_ON_MASK Serial0
Du öffnest die Schnittstelle, aber Zeichen kommen da keine reine...... daher wohl auch nicht im Programm.
was auch komisch ist, dass die konfigurationsdaten 3 mal übertragen werden...
SERIAL_WAIT_ON_MASK sollte ja nur einmal erscheinen, es erscheint aber gleich 5mal wenn ich die karte auf den leser lege und 4 mal wenn ich die karte wegnehme...
Benutze mal PortMon in Zusammenhang mit Hyperterminal. Und falls dort was ankommt, schau dir nochmal das Log an.
Hallo,
wenn ich das richtig gesehen habe, löscht du RTS. Vielleicht sendet deshalb der Kartenleser nicht. Hyperterminal setzt RTS immer.
Ich vermute mal, dass der Kartenleser sowieso nur mit ner 3-Drahtleitung verbunden ist. Damit wird RTS überhaupt nicht übertragen. Es wird ja auch kein HW-Handshake benutzt. Zudem schien ja im Hyperterm was anzukommen, nur in seiner App nicht.
@svenson: habe es bereits getestet. beim ht kommt die konfiguration einmal und dann wird bei auflegen der karte ein string ausgelesen... bei dem script kommt die konf mehrmals und bei auflegen der karte erscheint nur das bereits erwähnte SERIAL_WAIT_ON_MASK....
@martinh: wie setze ich das rts im script? habe versucht RTSEnable auf true zu setzen, doch kein erfolg....
kann es sein, dass ich den read irgendwie mit einem write anstossen muss?
mein code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace rs232
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Close();
}
private void serialPort1_onDataReceived(object sender, SerialDataReceivedEventArgs e)
{
textBox1.Text = serialPort1.ReadLine();
textBox1.Text = serialPort1.ReadTo("\n");
}
}
}
ja und das steht in der designer.cs des forms:
this.serialPort1 = new System.IO.Ports.SerialPort(this.components);
//
// serialPort1
//
this.serialPort1.DataBits = 7;
this.serialPort1.Parity = System.IO.Ports.Parity.Even;
this.serialPort1.ReadBufferSize = 1024;
this.serialPort1.RtsEnable = true;
Ich benutze OpenNetCF für meine Progs die mit der Seriellen Schnittstelle arbeiten. Das funktioniert gut bei mir. Ich benutze aber auch .Net 1.1.
Ich würde einfach mal mit einer 2. Schnittstelle und einen Nullmodemkabel versuchen etwas aus der Schnittstelle zu lesen.
Lass mal die Read-Funktionen in OnDataReceived weg und setze mal einfach einen Breakpoint mit dem Debugger rein. Der sollte auch angesprungen werden.
springt leider nicht bis dort hin. ich glaube mir fehlt die verbindung zu ondatareceived...
In deinem Code ist zumindest kein Einhängen in den Event zu sehen.....
🙁 das ist gemein, aber ich verstehs natürlich. anders lerne ich nur das abschreiben des codes, was ncith sehr förderlich wäre 🙂 ich werde versuchen, ein "event einzuhängen"
wo finde ich ausreichend informationen, um rs232 unter .net2 ausführen zu können? gibt es da eine gute empfehlung?
lg
Vermutlich gibts da nicht viel, denn eigentlich ist es ziemlich einfach und die Hilfe beschreibt das auch ausreichend. Es gibt - wie praktisch überall in .NET - die Möglichkeit synchron zu arbeiten (z.B. mit ReadLine()) oder ereignisgesteuert, also asynchron über den OnDataReceived-Event. Viel mehr gibts eigentlich nicht zu wissen. Über RS-232 im Allgemeinen gibts viel im Netz (Handshaking, Steuerleitungen, etc.).
hallo,
habe jetzt das ondatareceived event eingebaut. bemerkte, dass ich wie in vb.net ein delegate benötige... zumindest funktioniert es so teilweise...
in meinem form.cs rufe ich das wie folgt auf:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace rs232
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Close();
Close();
}
delegate void MessageDataDelegate(string data);
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
MessageDataDelegate dlgte = new MessageDataDelegate(MessageData);
string recvData = serialPort1.ReadExisting();
this.Invoke(dlgte, new object[] { recvData });
}
private void MessageData(string data)
{
textBox1.Text = data;
}
}
}
jetzt werden aber nur noch die letzten 6 zeichen des strings in der textbox ausgegeben. laut port mon werden sie immer zu 8 zeichen großen teilen eingelesen. ds heisst, dass die textbox sehr wohl alle ausgibt aber eben nur nacheinander...
wie schafft man es, dass man den string als gesamtes ausliest und in der textbox ausgibt?
meine idee wäre eben, dass ich anstelle von readexisting mit readline arebeite und dann auf ein ende warte.... das funkr aber so nicht wie ich es probiert habe...
Kurz gesagt: Gar nicht. Du musst bei asynchronem Vorgehen immer davon ausgehend, dass dir gesendet Daten in beliebigen "Paketen" eingehen. Obwohl dein Leser vielleicht 8 Zeichen am Stück gesendet hat, kommen auf Empfängerseite erst 6, dann 2 Zeichen an, oder sogar jedes Zeichen einzeln. Es ist also an dir die Zeichen zusammenzubasteln. Die serielle Schnittstelle verhält sich wie ein Stream (ist auch einer) und ist kein Paketdienst, der sicherstellt, dass Daten auch gemeinsam eintrudeln.
Wenn du tatsächlich zu jedem Zeitpunkt weisst, wie viel Zeichen erwartet werden, bzw. du ein Trennerzeichen kennst, was ein Paket abschliesst, dann ist es i.d.R. wirklich besser mit densychronen Funktionen zu arbeiten, aber eben nicht in OnDataReceived, sondern in einer eigene Ablaufkonstruktion. Üblicherweise definiert man für solche Protokolle eine Zustandsmaschine.
OnDatareceived hingegen bietet sich eher für streamorientierte Protokolle an.
habs jetzt hinbekommen. es funkt doch 🙂
mit readto... hatte ich schon mal probiert aber mit \n.
funktioniert anscheinend aber nur mit \r...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace rs232
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Close();
Close();
}
delegate void MessageDataDelegate(string data);
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
MessageDataDelegate dlgte = new MessageDataDelegate(MessageData);
string recvData = serialPort1.ReadTo("\r");
this.Invoke(dlgte, new object[] { recvData });
}
private void MessageData(string data)
{
label1.Text = data;
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}