Moin Moin,
ich brauche mal euer Wissen..
Und zwar sende ich Befehle von meiner GUI an einen µC. Das funktioniert
soweit auch wunderbar ( wenn es Zyklisch passiert.. ). Das heißt ich
arbeite die ganzen Befehle mit nem Timer nach und nach ab..
Nun habe ich versucht direkt nach dem Start ein paar Infos vom µC
abzurufen.. Das klappt leider nicht. Ich muss an den stellen wo ich die
Informationen haben möchte, warten bis das Datenpaket eingetroffen ist..
P.s
Die Daten hole ich via Event von der Seriellen ab.
Wie stelle ich das an?
- Delay ist keine Alternative..
- while natürlich auch nicht..
gibt es noch andere Möglichkeiten?
Ist ja klar, dass das nicht geht. Schau mal in Zeile 37. Da hast Du eine
Race Condition. Die serielle Schnittstelle ist Asynchron.
Ich würde da eher schreiben.
Oliver R. schrieb:> Hi,>> Zeile 37? Ich seh' hier keinen Code...
Ich auch nicht. Das war auch purer Sarkasmus von mir mit einem hauch
ernst gemeinter Hilfe. Der asynchrone Zugriff hat mir auch schon viel
Ärger bereitet.
Aber wenn man als TO nichtmal in der Lage ist, den Quelltext anzuhängen,
dann ist ihm wahrlich nicht zu helfen.
Du müsstest dort eine StateMachine verwenden und die am einfachsten per
Timer aufrufen. Dort drin kannst du dann Daten schicken und auf Daten
warten.
Die Schrittkette kannst du dann bereits am Programmstart ausführen
(zumindest anstoßen).
Micha schrieb:> Du müsstest dort eine StateMachine verwenden
Im Prinzp: ja. Praktisch geht sowas auch per Timer, der in sinnvollen
Abständen einen Timerevent in das Framework feuert. Immerhin puffert das
OS ja den ganzen seriellen Stream.
Aber normalerweise macht man das eher so, daß man sich in seinem eigenen
Programm einen zweiten Thread startet, der rein garnix mit dem Framework
der Oberfläche zu schaffen hat. Dieser Thread arbeitet streng
prozedural, wartet also per sleep oder so, bis die Serielle wieder ein
Zeichen verfügbar hat. Dann wird das entweder zu irgendwelchen
Datenstrukturen zusammengesetzt, die nur der TO kennt, oder es wird für
den GUI_Thread zwischengepuffert und für den GUI-Thread ein dazu
passender Event ausgelöst.
Das ist natürlich etwas komplizierter als schlichtweg im GUI-Thread auf
I/O zu warten oder per Timer zu pollen. Aber letzteres geht in manchen
Fällen auch.
W.S.
Was soll denn mein Quellkode groß dazu beitragen? Im Endeffekt brauche
ich Ideen wie ich am besten auf ein komplett empfangenes Kommando warten
kann..
Aber klar, ich poste mal mein Kode..
Hier empfange ich die Daten:
Das hört sich nach einer guten Idee an. Den Thread der die ganzen Daten
sendet bzw. empfängt kann dann ja ruhig wie Du schon sagtest, per Sleep
warten..
W.S. schrieb:> Aber normalerweise macht man das eher so, daß man sich in seinem eigenen> Programm einen zweiten Thread startet, der rein garnix mit dem Framework> der Oberfläche zu schaffen hat. Dieser Thread arbeitet streng> prozedural, wartet also per sleep oder so, bis die Serielle wieder ein> Zeichen verfügbar hat. Dann wird das entweder zu irgendwelchen> Datenstrukturen zusammengesetzt, die nur der TO kennt, oder es wird für> den GUI_Thread zwischengepuffert und für den GUI-Thread ein dazu> passender Event ausgelöst.
Hi,
Natürlich hilft der Quellcode weiter. Was denn sonst?
Leider hast Du uns die Stelle, wo Du auf die Antwort des MCs wartest,
trotzdem vorenthalten!
Deshalb vermute ich mal ganz stark, dass Du dort auf "manaualResetEvent"
wartest. Dabei blockierst Du Dein UI und der Dispatcher kann dann auch
"Client_DataReceived" nicht mehr ausführen.
Dafür gibt es zwei Lösungen:
1. Mach es so wie von W.S. vorgeschlagen
2. Benutze async/await, dann läuft der Dispatcher weiter:
Oliver R. schrieb:> Leider hast Du uns die Stelle, wo Du auf die Antwort des MCs wartest,> trotzdem vorenthalten!
Ah, sorry!
Also nach dem öffnen des Portes, stelle ich ein paar Anfragen an nen µC
und möchte halt gerne warten bis diese ankommen.
1
Jobs.Read.Version(sender,e);
2
Serial.manaualResetEvent.Reset();
3
Serial.manaualResetEvent.WaitOne();
Dispatcher..?! Okay da muss ich mich noch einlesen.
Das muss ich quasie machen, wenn ich die Anfragen stelle, richtig?
Hallo!
Hier der beispielcode von ms... Ist zwar für Raspberry, kann aber
angepasst werden...
using Windows.Storage.Streams;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
public async void Serial()
{
string aqs = SerialDevice.GetDeviceSelector("UART0");
/* Find the selector string for the serial device */
var dis = await DeviceInformation.FindAllAsync(aqs);
/* Find the serial device with our selector string */
SerialDevice SerialPort = await SerialDevice.FromIdAsync(dis[0].Id);
/* Create an serial device with our selected device */
/* Configure serial settings */
SerialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
SerialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
SerialPort.BaudRate = 9600;
/* mini UART: only standard baudrates */
SerialPort.Parity = SerialParity.None;
/* mini UART: no parities */
SerialPort.StopBits = SerialStopBitCount.One;
/* mini UART: 1 stop bit */
SerialPort.DataBits = 8;
/* Write a string out over serial */
string txBuffer = "Hello Serial";
DataWriter dataWriter = new DataWriter();
dataWriter.WriteString(txBuffer);
uint bytesWritten = await
SerialPort.OutputStream.WriteAsync(dataWriter.DetachBuffer());
/* Read data in from the serial port */
const uint maxReadLength = 1024;
DataReader dataReader = new DataReader(SerialPort.InputStream);
uint bytesToRead = await dataReader.LoadAsync(maxReadLength);
string rxBuffer = dataReader.ReadString(bytesToRead);
}
Quelle:
https://docs.microsoft.com/de-de/windows/iot-core/learn-about-hardware/pinmappings/pinmappingsrpi
Musst eben den read Teil in einen extra Thread packen und ein Do
rundherum machen. Hoffe das hilft
Hallo nochmal,
der Dispatcher arbeitet bei WINDOWS-Programmen alle vorkommenden
Ereignisse (z.B. Button gedrückt oder Daten vom Port empfangen etc.) ab
und zwar synchron.
D.h. ich kann nicht gleichzeitig mit WaitOne() auf ein
Synchronisationsobjekt warten (der ManualResetEvent) und meine Daten vom
Port empfangen.
Pack Deine drei Zeilen unter das await... Statement und gut ist.
Aber: Benutze einen AutoResetEvent. Ansonsten muss das .Reset() NACH dem
WaitOne() erfolgen. Wie der Name schon sagt macht das ein AutoResetEvent
automatisch.
Da Du aber sicherlich auf mehrere Datenpakete dauerhaft warten möchtest,
ist die Vorgehensweise von W.S. deutlich übersichtlicher. Sammel in
Deinem Thread die Daten und löse im GUI ein Ereignis aus, wenn Du damit
fertig bist.
Gruß,
Hi,
es wäre wirklich gut, wenn Du Dir die Doku zum async/await-Pattern
durchlesen würdest. Wir kennen hier nur Auszüge Deines Codes, das macht
eine Hilfe nicht gerade einfacher.
Es sieht so aus, als ob Du die Methode mit async/await in eine eigene
Klasse gepackt hast. Das Pattern funktioniert aber nur dann, wenn die
Methode Bestandteil des GUIs ist. Also eine Member-Funktion des Forms!
Gruß,
Warum sollte man aber auch den Zugriff auf die serielle Schnittstelle im
GUI-Thread haben wollen? Das ist doch vollkommener Unsinn?!
Wenn ich so meine RS232 Codes durchsehe, dann erstelle ich eine Instanz
der Klasse, habe das asynchrone Data-Receive-Event und hole mir die
Daten dann per Invoke in meinen Thread rüber.
Das läuft absolut stabil und ich habe seitdem keinerlei Probleme mehr
mit Race Conditions oder Zugriffsverletzungen.
Oliver R. schrieb:> Hi,>> es wäre wirklich gut, wenn Du Dir die Doku zum async/await-Pattern> durchlesen würdest. Wir kennen hier nur Auszüge Deines Codes, das macht> eine Hilfe nicht gerade einfacher.> Es sieht so aus, als ob Du die Methode mit async/await in eine eigene> Klasse gepackt hast. Das Pattern funktioniert aber nur dann, wenn die> Methode Bestandteil des GUIs ist. Also eine Member-Funktion des Forms!>> Gruß,
Sie ist ein Member der eigentlichen Form. Mein Serielles "Modul" ist in
einer eigenen Klasse, stört das?
Ja!
es gibt ja viele Wege zum Ziel, besonders mit C#. Ich selbst benutze in
keinem meiner Programme diese eventbasierte serielle Klasse, sondern
stets synchrone serielle read/write Funktionen, die in eigenen Threads
laufen.
Fast immer muss man nämlich auf eine vollständige Antwort von einem
Gerät warten und das Aufteilen der Antwort in mehrere Events macht
irgendwie überhaupt keinen Sinn.
Tu Dir also selbst einen Gefallen und mach es genauso.
Gruß,
Oliver
Martin S. schrieb :
>Warum sollte man aber auch den Zugriff auf die serielle Schnittstelle im>GUI-Thread haben wollen? Das ist doch vollkommener Unsinn?!>Wenn ich so meine RS232 Codes durchsehe, dann erstelle ich eine Instanz>der Klasse, habe das asynchrone Data-Receive-Event und hole mir die>Daten dann per Invoke in meinen Thread rüber.>Das läuft absolut stabil und ich habe seitdem keinerlei Probleme mehr>mit Race Conditions oder Zugriffsverletzungen.
Das sehe ich genau so. Ich habe es auch so gelösst, funktioniert sehr
zuverlässig.
Folgendes ist aber zu bedenken (vielleicht ist das, das Problem was Du
hast):
Wenn der Mikrokontroller Daten (n Bytes) an PC Sendet, dann „kommen die
Daten in Häppchen an“. D.h. der DataReceivedHandler wird mehrfach
aufgerufen. Beim jeden Aufruf kriegt man das nächste Häppchen was man
abspeichern/verarbeiten kann. (Bitte sehe mein Beispiel)
Jan W. R. schrieb:> Wenn der Mikrokontroller Daten (n Bytes) an PC Sendet, dann „kommen die> Daten in Häppchen an“.
Natürlich tun sie das. Deswegen empfängt man sowas auch nicht im
GUI-Thread.
Man hat eine Klasse, die die Funktionalität RS232 kapselt, erstellt
einen neuen Thread in dem die Klasse arbeitet und wenn innerhalb der
Klasse nach n Events festgestellt wird, dass die Daten nun vollständig
sind, dann feuert sie ein Event an den GUI - Thread, der sagt, dass die
Verarbeitung nun abgeschlossen ist.
DANN hat man auch sicher verwertbare Daten und erst dann ist es
überhautp sinnvoll, etwas anzuzeigen. Es sei denn, man steht drauf,
zuzusehen, wie die Daten kommen. Dann muss man das Event halt bei jedem
Receive auslösen.
C# bietet doch geniale Möglichkeiten, das ganze so abstrakt zu halten,
dass man im GUI Thread sich mit nichts mehr herumzuärgern braucht.
Das Konzept ist dann absolut failsafe.
Martin S schrieb :
>DANN hat man auch sicher verwertbare Daten und erst dann ist es>überhautp sinnvoll, etwas anzuzeigen. Es sei denn, man steht drauf,>zuzusehen, wie die Daten kommen. Dann muss man das Event halt bei jedem>Receive auslösen.>C# bietet doch geniale Möglichkeiten, das ganze so abstrakt zu halten,>dass man im GUI Thread sich mit nichts mehr herumzuärgern braucht.>Das Konzept ist dann absolut failsafe.
Das hört sich gut an.
Was C# angeht bin ich ein Anfänger.
Das Multithreading finde ich nicht so ganz einfach.
Vielleicht ist jemand so freundlich und bereit ein minimalistisches
Beispiel zu posten?
z.B.
Eine SerielDataReceive Klasse die nach dem N bytes empfangen wurden ein
event an das GUI thread schickt.
Gruss,
Jan
Jan W. R. schrieb:> Martin S schrieb :>>>DANN hat man auch sicher verwertbare Daten und erst dann ist es>>überhautp sinnvoll, etwas anzuzeigen. Es sei denn, man steht drauf,>>zuzusehen, wie die Daten kommen. Dann muss man das Event halt bei jedem>>Receive auslösen.>>>C# bietet doch geniale Möglichkeiten, das ganze so abstrakt zu halten,>>dass man im GUI Thread sich mit nichts mehr herumzuärgern braucht.>>>Das Konzept ist dann absolut failsafe.>> Das hört sich gut an.> Was C# angeht bin ich ein Anfänger.>> Das Multithreading finde ich nicht so ganz einfach.> Vielleicht ist jemand so freundlich und bereit ein minimalistisches> Beispiel zu posten?>> z.B.> Eine SerielDataReceive Klasse die nach dem N bytes empfangen wurden ein> event an das GUI thread schickt.>> Gruss,> Jan
Oliver R. schrieb:> der Dispatcher arbeitet bei WINDOWS-Programmen alle vorkommenden> Ereignisse (z.B. Button gedrückt oder Daten vom Port empfangen etc.) ab> und zwar synchron.> D.h. ich kann nicht gleichzeitig mit WaitOne() auf ein> Synchronisationsobjekt warten
Doch, kann man natürlich. Man muss nur den entsprechenden API-Call
verwenden, der genau dies erlaubt. Also MsgWaitForMultipleObjects() oder
MsgWaitForMultipleObjectsEx().
Sehr sinnvoll ist das allerdings in aller Regel nicht. Im Besonderen
nicht: für die Verarbeitung der Ereignisse eines COM-Ports. Denn der
wird mit dem FileAPI (ein ein wenig mehr) schon absolut hinreichend für
den asynchronen Betrieb unterstützt. Wenn man den Scheiß irgendwann
überhaupt im GUI-Thread benötigt, gibt es genug Mechanismen, in dorthin
zu lenken. Alles bis zu diesem Zeitpunkt kann und sollte im Kontext der
OS-Threads passieren. Denn im Kern ist die asynchrone Betriebsart auch
nix anderes als ein Thread. Bloß dass der implizit vom OS erzeugt wird.
Sprich: das ABSOLUT DÜMMSTE, was man machen kann, ist: Polling des
synchronen API mit einem eigenen Thread. Das senkt nur den Durchsatz,
löst aber nicht das Problem der Synchronisation mit dem GUI-Thread. Da
muss man ganz genauso lösen, als würde man direkt aus dem Kontext der
OS-Threads agieren.
c-hater schrieb:> Doch, kann man natürlich. Man muss nur den entsprechenden API-Call> verwenden, der genau dies erlaubt. Also MsgWaitForMultipleObjects() oder> MsgWaitForMultipleObjectsEx().
Wir reden hier ja über C# und niemand wird wohl ernsthaft auf die Idee
kommen, das dort reinzufrickeln!
Wahrscheinlich wird aber async/await intern ganz ähnlich arbeiten.
Eine Sache muss ich aber noch richtig stellen: In der Hilfe zu
SerialPort steht, dass der DataReceived-Event tatsächlich im Kontext
eines zweiten (nicht-GUI) Threads abgearbeitet wird.
Gruß,
Oliver R. schrieb:> In der Hilfe zu> SerialPort steht, dass der DataReceived-Event tatsächlich im Kontext> eines zweiten (nicht-GUI) Threads abgearbeitet wird.
Jup, so isses auch. Ohne Invoker knallt's. Nicht immer, nur ab und zu.
Das macht den Fehler mies zu finden.
Martin S schrieb :
>Oliver R. schrieb:>> In der Hilfe zu>> SerialPort steht, dass der DataReceived-Event tatsächlich im Kontext>> eines zweiten (nicht-GUI) Threads abgearbeitet wird.>Jup, so isses auch. Ohne Invoker knallt's. Nicht immer, nur ab und zu.>Das macht den Fehler mies zu finden.
Martin S schrieb aber auch :
>Natürlich tun sie das. Deswegen empfängt man sowas auch nicht im>GUI-Thread.>Man hat eine Klasse, die die Funktionalität RS232 kapselt, erstellt>einen neuen Thread in dem die Klasse arbeitet und wenn innerhalb der>Klasse nach n Events festgestellt wird, dass die Daten nun vollständig>sind, dann feuert sie ein Event an den GUI - Thread, der sagt, dass die>Verarbeitung nun abgeschlossen ist.
Warum soll man den einen neuen Thread für diese "SerialReceive" Klasse
(so nenne ich sie) erstellen?
Das data receive event arbeitet doch so wie so in einem nicht GUI
Thread.
…???
Ich würde es mit meinem jetzigen Verständnis folgendermaßen machen :
Eine Klasse erstellen, "SerialReceive" die ein SerialPort kapselt und
das Protokoll beinhaltet. Die Protokollimplementierung befindet sich in
der SerialReceive Klasse. Diese privaten Protokollmethoden werden von
DataReceivedHandler aufgerufen. In den Protokollmethoden wird ein
NewDataPacketReceived event an das GUI thread abgefeuert.
Eine Instanz der SerialReceive Klasse würde ich im GUI thread erstellen.
Ich würde also keinen weiter Thread erstellen.
Was hält ihr von dieser Lösung. Wäre das eine saubere und richtige
Implementierung? oder habe ich irgendwas Falsch verstanden?
Gruss,
Jan
Jan W. schrieb:> Was hält ihr von dieser Lösung. Wäre das eine saubere und richtige> Implementierung? oder habe ich irgendwas Falsch verstanden?
Genau so habe ich das jetzt auch gemacht.
Das funktioniert soweit auch richtig super.
Das mit dem "Warten", habe ich jetzt auch lösen können.
Ist zwar sehr unsauberer Code aber ich weiß gerade nicht weiter und so
wichtig ist es jetzt auch nicht. Habe an der Stelle, wo ich warten muss,
ein "await Task.Delay(x)" eingebaut. Siehe da, das "DateReceivedEvent"
wird weiterhin gefeuert und kann ohne Probleme in der Zeit meine
eingehenden Daten auswerten.
Jan W. schrieb:> Martin S schrieb :>>>Oliver R. schrieb:>>>> In der Hilfe zu>>> SerialPort steht, dass der DataReceived-Event tatsächlich im Kontext>>> eines zweiten (nicht-GUI) Threads abgearbeitet wird.>>>Jup, so isses auch. Ohne Invoker knallt's. Nicht immer, nur ab und zu.>>Das macht den Fehler mies zu finden.>> Martin S schrieb aber auch :>>>Natürlich tun sie das. Deswegen empfängt man sowas auch nicht im>>GUI-Thread.>>>Man hat eine Klasse, die die Funktionalität RS232 kapselt, erstellt>>einen neuen Thread in dem die Klasse arbeitet und wenn innerhalb der>>Klasse nach n Events festgestellt wird, dass die Daten nun vollständig>>sind, dann feuert sie ein Event an den GUI - Thread, der sagt, dass die>>Verarbeitung nun abgeschlossen ist.>> Warum soll man den einen neuen Thread für diese "SerialReceive" Klasse> (so nenne ich sie) erstellen?
"Man" macht das nicht, das macht das Framework selbst.
> Das data receive event arbeitet doch so wie so in einem nicht GUI> Thread.> …???
Richtig.
> Ich würde es mit meinem jetzigen Verständnis folgendermaßen machen :>> Eine Klasse erstellen, "SerialReceive" die ein SerialPort kapselt und> das Protokoll beinhaltet. Die Protokollimplementierung befindet sich in> der SerialReceive Klasse. Diese privaten Protokollmethoden werden von> DataReceivedHandler aufgerufen. In den Protokollmethoden wird ein> NewDataPacketReceived event an das GUI thread abgefeuert.>> Eine Instanz der SerialReceive Klasse würde ich im GUI thread erstellen.> Ich würde also keinen weiter Thread erstellen.>> Was hält ihr von dieser Lösung. Wäre das eine saubere und richtige> Implementierung? oder habe ich irgendwas Falsch verstanden?
Das verschiebt das Problem, aber löst es nicht. Das ist genau der Fall,
den ich weiter oben schon beschrieben habe. Irgendwann rumpelt es und
man kann suchen, woran es liegt.
Ich sehe auch ehrlichgesagt das Problem nicht. Es gibt millionen
Beispiele im Internet und unzählige zugehörige Antworten zu den Fragen
auf Stackoverflow. Da steht das alles lang und breit erklärt. Warum
nimmst Du nicht einfach so einen Code - der funktioniert wenigstens.
Martin S. schrieb :
>Das verschiebt das Problem, aber löst es nicht. Das ist genau der Fall, den ich
weiter oben schon beschrieben habe. Irgendwann rumpelt es und man kann suchen,
woran es liegt.
In dem NewDataPacketReceived event handler verwende ich natürlich das
threadsichere Aufrufes von Windows Forms-Steuerelementen.
textBox1.InvokeIfRequired(() => textBox1.Text += indata); // +=indata);
InvokeIfRequired ist eine sinnvolle Ergänzungsmethode für das
Threadsichere Aufrufe von Windows Forms-Steuerelementen.
mehr Info unter :
https://stackoverflow.com/questions/2367718/automa...
>Ich sehe auch ehrlichgesagt das Problem nicht. Es gibt millionen Beispiele im
Internet und unzählige zugehörige Antworten zu den Fragen auf Stackoverflow. Da
steht das alles lang und breit erklärt. Warum nimmst Du nicht einfach so einen
Code - der funktioniert wenigstens.
Ich möchte verstehen warum etwas funktioniert, und warum nicht.
Gibt es eine Möglichkeit das NewDataPacketReceived event so zu
implementieren das es synchron zum GUI thread kommt?
Dann könnte man sich das threadsichere Aufrufen der Windows
Forms-Steuerelementen sparen.
Mann könnte also im NewDataPacketReceived event Handler schreiben:
textBox1.Text += indata;
Gruss,
Jan
Jan W. schrieb:> Dann könnte man sich das threadsichere Aufrufen der Windows> Forms-Steuerelementen sparen.
Das kannst Du dir nie sparen. Aber du kannst es asynchron gestalten per
.BeginInvoke(). Dann bist du threadsicher und hast keine Verzögerung.
Jan W. schrieb:> Ich möchte verstehen warum etwas funktioniert, und warum nicht.
Lobenswerter Ansatz. Hoffentlich schaffst du es...
> Gibt es eine Möglichkeit das NewDataPacketReceived event so zu> implementieren das es synchron zum GUI thread kommt?
Natürlich: Man verlagert das Problem der Synchronisierung mit dem
GUI-Tread in die Klasse, die das Event generiert. Aber schon allein die
dazu zu importierenden Abhängigkeiten sagen: das ist keine sehr
nützliche Idee im Sinne der Codeisolation (auch wenn sie natürlich
durchaus funktioniert).
Dein Problem ist das typische Anfängerproblem: du hältst deine
GUI-Anwendung für den Kern des Universums, weil es zu diesem Zeitpunkt
so ziemlich alles ist, was du kannst.
Ist sie aber nicht, sollte sie jedenfalls nicht sein. Normalerweise
sollte das GUI nur Schnittstelle zwischen Anwender und der eigentlichen
Funktion des Programms sein.
Wenn du dieses Konzept konsequent umsetzt, wirst du sehr bald bemerken,
dass Synchronisationen mit dem GUI-Thread zu einer eher seltene Aufgabe
wird und das die das Innenleben deiner Form praktisch nur noch daraus
besteht, die GUI-Logik abzubilden und die wenigen Events des
eigentlichen Nutz-Programms zu empfangen und zu synchronisieren, die
wirklich das GUI erreichen müssen.
....
hier mein Seriell-IO-Test
öffnet am Mac die seriellen "RS232" USB Schnittstelle
"/dev/cu.usbmodem14101",
setzt DTR low (low-aktiv),
liest vom ARDUINO eine Zeile (auf Escapesequenz \n endend),
sendet einen String (auf Escapesequenz \n endend) an den ARDUINO,
liest vom ARDUINO noch eine Zeile (auf Escapesequenz \n endend),
setzt DTR high,
schließt den seriellen Port,
1
#include <stdio.h> /* Standard input/output definitions */
2
#include <stdlib.h>
3
#include <stdbool.h>
4
#include <string.h> /* String function definitions */
5
#include <unistd.h> /* UNIX standard function definitions */
6
#include <fcntl.h> /* File control definitions */
7
#include <errno.h> /* Error number definitions */
8
#include <termios.h> /* type and macro definitions. Linux version. */
9
#include <sys/ioctl.h>
10
#define PORT "/dev/cu.usbmodem14101"/* change this to your USB port Device Name */
Winfried J. schrieb:> ...
Was willst du uns damit zeigen? Weder beantwortet das die Frage vom TO
noch ist das C# Code.
Außerdem liest du blocking. Genau das will der TO nicht.
Das Beispiel zeigt im Detail undvollständig wie die Kommunikation
funktioniert und was zu beachten ist. Was der TO wünscht, C# und und
nonblockig ist leicht anzupassen. Die Entsprechungen in Borland C# kann
er selbst vornehmen und wie man die den Fluss regelmaäßig auf einzelne
oder Gruppen von Zeichen checkt ist eine Teilmenge der Funktion
USBSerialgetline. Etwas Selber-Denken wird erlaubt sein, ottach?
Namaste
Winfried J. schrieb:> Borland C#
Der war gut. Das muss ich mir merken.
PS: Dein Code ist kacke. Da werden unterschiedliche Abstraktionsebenen
wild durcheinander gemischt. Den solltest du mal refaktorieren.
Keiner N. schrieb:> Winfried J. schrieb:>> Borland C#>> Der war gut. Das muss ich mir merken.>> PS: Dein Code ist kacke. Da werden unterschiedliche Abstraktionsebenen> wild durcheinander gemischt. Den solltest du mal refaktorieren.
Kein wunder das so mancher Aufzug stehen bleibt :D
> Kein wunder das so mancher Aufzug stehen bleibt :D
Aber nicht weil ich etwas in C programmiere.
> Dein Code ist kacke.
Zeig mir bitte deinen Besseren. ich wäre dankbar.
> Da werden unterschiedliche Abstraktionsebenen> wild durcheinander gemischt.
Ja, stammt aus verschiedene Quellen und wurde von mir modifiziert bis er
zuverlässig funktionierte wie ich es wünschte.
>Den solltest du mal refaktorieren.
|
r
Ist nur ein Test zu grundsätzlichen Funktionsweise
In der späteren Anwendung wird das noch durchstrukturiert
Winfried J. schrieb:>> Kein wunder das so mancher Aufzug stehen bleibt :D>> Aber nicht weil ich etwas in C programmiere.>>> Dein Code ist kacke.> Zeig mir bitte deinen Besseren. ich wäre dankbar.
1
static void Main(string[] args){
2
using (var myPort = new SerialPort("/dev/ttyACM0", 115200)){
3
myPort.Open();
4
myPort.Write("Hallo Welt");
5
var readData = myPort.ReadLine();
6
Console.WriteLine(readData);
7
}
8
}
Bitte schön. Nicht, dass der Code dem TO weiterhelfen würde. Trozdem ist
der näher dran als deiner, weil wenigstens die gleiche
Programmiersprache.
Zu beachten ist auch, dass ich keinen Low Level Krams (ioctrl)
dazwischen streue. Darauf war meine Kritik bezogen.
>> Da werden unterschiedliche Abstraktionsebenen>> wild durcheinander gemischt.>> Ja, stammt aus verschiedene Quellen und wurde von mir modifiziert bis er> zuverlässig funktionierte wie ich es wünschte.
Toll zusammenkopierter Kram. Das ist natürlich die Welt. Dazu das ganze
noch hochtrabend mit USB betitelt. Wolltest wohl ein wenig angeben? Ist
nur eine 08/15 serielle Schnittstelle.
1
>>Den solltest du mal refaktorieren.
2
> |
3
> r
Da gehört definitiv kein r dazwischen.
https://de.wikipedia.org/wiki/Refactoring> Ist nur ein Test zu grundsätzlichen Funktionsweise> In der späteren Anwendung wird das noch durchstrukturiert
Man sollte seinem Code von Anfang an eine Struktur geben. Das macht die
Sache wesentlich einfacher zu testen und debuggen.
Will meinen, Kapsel noch das write und das DTR setzen. Gib den
Funktionen vernünftige Namen, dann reicht das schon und die Kommentare
brauchst du dann auch nicht mehr.
Schon, aber ist schon 10 Jahre her seit ich mich damit rum gezankt habe.
Ich bleib lieber beim einfachen C, ohne # ohne ++ und ohne Visual davor.
Das Konzept ist ja noch zu verstehen, aber zurecht komme ich mit den
Klassen nicht wirklich.
Funktionen sind mir da sympathischer.
Namaste