mikrocontroller.net

Forum: PC-Programmierung C# Serial read


Autor: Christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich habe eine Software die Daten sendet und eine die sie über einen 
virtuellen Port empfängt.
Beide Anwendungen sind in C# Forms programmiert.
Die sendende Anwendung schickt in unterschiedlichen Intervallen, 
unterschiedliche Zeilenanzahlen.


Die gesendeten Daten haben das Format S0P0N0 \r\n (die Nullen sind die 
Werte die sich ändern), Ich bin gerade ratlos wie ich das Problem mit 
unterschiedlicher Zeilenzahl handeln kann und wie ich am besten die 3 
Werte wieder aus dem String extrahiere.
Das Sendeprotokoll könnte ich falls nötig relativ leicht ändern.

Ich hoffe jemand kann mir weiterhelfen,
MfG. Christoph

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grundsätzlich geht immer die Regex.Match-Methode;

hier geht es mit der String.Split-Methode noch einfacher:

String.Split(new Char[] {'S', 'P', 'N'}, "S0P0N0")
// returns {"0", "", "0", "", "0"}
… oder so ähnlich.

VG Torsten

Autor: Meisterklops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist eine Instanzmethode, also
var s = "S0P0N0";
var x = s.Split(new [] { 'S', 'P', 'N' }, StringSplitOptions.RemoveEmptyEntries);
// Dann Fehlerprüfung und Typumwandlung ...

Christoph schrieb:
> Ich bin gerade ratlos wie ich das Problem mit
> unterschiedlicher Zeilenzahl handeln kann

Den entsprechenden Code für jede Zeile ausführen (Schleife)?

Autor: Meisterklops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Als Separatoren-Array kann man natürlich auch eine (readonly) 
Klassenvariable verwenden anstatt es immer wieder neu zu erzeugen.

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meisterklops schrieb:
> Ist eine Instanzmethode
Blöde Instanzmethoden! :(
Da hätten die auch eine Extension draus machen können! ;)
public static class myString {
    static String[] Split(this String S, char[] chrs) {
        return S?.Split(chrs);
    }
}

Ich war in Gedanken bei String.Join(). Sorry + Danke, Meisterklops!

> Den entsprechenden Code für jede Zeile ausführen (Schleife)?
… und dann vorher mit s?.Split(null) die Zeilen finden?

Oder eben mit einer RegEx in einem einzigen Schritt:
https://msdn.microsoft.com/library/b873y76a(v=vs.110).aspx
Kapitel "Alternatives to String.Split".

: Bearbeitet durch User
Autor: Christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!

Werd das gleich mal in mein Programm einbauen und testen,
nur das Empfangen ist damit noch immer nicht gelöst.

Wenn der serialPort ein "DataReceivedEvent" auslöst werden ja alle 
empfangenen Daten in den Empfangspuffer geschrieben oder?
Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?

MfG. Christoph

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph schrieb:
> Wenn der serialPort ein "DataReceivedEvent" auslöst werden ja alle
> empfangenen Daten in den Empfangspuffer geschrieben oder?

Wenn der SerialPort ein "DataReceivedEvent" auslöst, dann bedeutet das, 
dass neue Daten in den Empfangspuffer geschrieben wurden. Vielleicht 
meitest Du das so?

Mit SerialPort.Read(…) oder SerialPort.ReadExisting() werden alle
empfangenen Daten aus dem Empfangspuffer gelesen.

Mit SerialPort.ReadLine() nur eine Zeile.

Aber SerialPort.ReadLine() wartet und hält Deinen Thread an.

Benutzt Du einen BackgroundWorker oder sowas wie "readWriteThread = new 
System.Threading.Thread(readWrite)"?

> Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?

Richtig. System.IO.Ports.SerialPort bietet keinen fertigen 
NewLineReceivedEvent 'out of the box' an.

: Bearbeitet durch User
Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Torsten C. schrieb:
> Benutzt Du einen BackgroundWorker oder …?
> Christoph schrieb:
>> Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?
> Richtig. System.IO.Ports.SerialPort bietet keinen fertigen
> NewLineReceivedEvent 'out of the box' an.

PS: Beim BackgroundWorker würde das 'NewLineReceivedEvent' nur anders 
heißen, also 'BackgroundWorker.ProgressChanged'.

Ich bevorzuge aber System.Threading.Thread mit selbst definiertem 
NewLineReceivedEvent.

Nutzt Du das Windows-Presentation-Framwork oder Windows-Forms?

Je nachdem wird das Ereignis dann über Invoke im UI-Thread ausgelöst.

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe ähnliches Problem vor kurzen gehabt.
Allerdings habe ich in Python das Testprogramm geschrieben.
Wenn das Telegramm kontinuierlich gesendet wird, muss du zunächst
synchronisieren.

Pseudocode
data = ser.read(TELEGRAM_LENGTH) # damit fällt sicher ein volles 
Telegramm hinein
idx = data.find(TELEGRAM_START) # muss eindeutig sein (Verwechslung mit 
Daten prüfen)
start = data.substring(idx,end)
telegram = start + ser.read(TELEGRAM_LENGTH - length(start ))

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
daniel schrieb:
> idx = data.find(TELEGRAM_START)…

Das läuft also auf einen weiteren, einen eigenen Empfangspuffer 
hinaus.

In C# würde sich dafür ein StringBuilder anbieten.

Christoph schrieb:
> Beide Anwendungen sind in C# Forms programmiert.

Das hatte ich gestern übersehen.
Also sähe das Event dann so ähnlich aus:
// Deklaration:
public event EventHandler<String> NewLineReceivedEvent;
// Auslösen aus dem readWriteThread dann mit:
string EmpfangeneZeile = "S0P0N0"; // vorher mit StringBuilder.Remove() entfernt
this.Invoke((MethodInvoker)(() => {
    EventHandler<string> handler = NewLineReceivedEvent;
    handler(this, EmpfangeneZeile);
}));

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.