Forum: PC-Programmierung Com Port Rückgabe


von sandman (Gast)


Lesenswert?

Hallo zusammen,

ich versuche mit einem Timer in C# über die RS232 - Schnittstelle einen 
Eingang vom STM32 ständig abzufragen. Klappt soweit auch. Nur, damit ich 
in C# was auslösen kann bei einem bestimmten Ereignis, muß ich den 
gelesenen Wert, der in einem string gespeichert wird, zerlegen. Ich habe 
es bereits versucht, den string in ein char array zu konvertieren, nur 
komme ich nicht weiter. Folgendes erhalte ich vom Comport zurück: in 
0[?25l  in 0 = 0 >[?25h.

Ich möchte die Zeichenfolge "in 0 = 0" von dem String auswert. Der Rest 
sind VT100, oder Hyperterminalbefehle, weiß es nicht so recht. Kann mir 
da jemand einen Tipp geben ? Wäre super.

: Verschoben durch User
von Peter II (Gast)


Lesenswert?

sandman schrieb:
> Der Rest
> sind VT100, oder Hyperterminalbefehle, weiß es nicht so recht.

dann musst du dir erstmal die doku/rfc zu VT100 durchlesen und dann 
kannst du einen filter schreiben der diese Infos entfernt. Dann sollte 
dein gesuchter text übrig bleiben.

von Sven H. (dsb_sven)


Lesenswert?

sandman schrieb:
> den string in ein char array zu konvertieren

Das sollte in c# vollkommen überflüssig sein. Wenn du Textsegmente 
miteinander vergleichen willst, kannst du das in c# auch direkt tun.
1
if (emfpangsstring == "0 = 0")
2
{
3
   // tu was
4
}

Außerdem kann die serielle Schnittstelle einen Event auslösen, in dem du 
dann die Daten entgegen nehmen kannst. Dann kannst du dir den Timer 
sparen ;-)

von sandman (Gast)


Lesenswert?

Hallo Sven,

den Timer nehme ich halt, weil er es dauernd überprüfen soll. Dein 
Lösungsansatz hatte ich auch schon mal versucht, hat bei mir aber nichts 
ausgelöst. Hier mal mein Code:

            input = serialPort.ReadExisting();
            if (input == "in 0 = 0")
            {


                MessageBox.Show("Richitg");
                textBox2.Text = input;
            }

Wenn ich am Eingang 0 ein Signal anlelge, egal mal welches, sehe ich 
dann im Debugger von VS, dass dann "in 0 = 1" steht. Also die Auswertung 
funktioniert. Nur wird keine Messagebox geöffnet.

von Karl H. (kbuchegg)


Lesenswert?

sandman schrieb:
> Hallo Sven,
>
> den Timer nehme ich halt, weil er es dauernd überprüfen soll.

Was soll er dauernd überprüfen?


Wenn vom µC ein neuer Text reinkommt, kriegt dein C# Programm in Form 
eines Events Bescheid und kann sich das, was reingekommen ist ansehen, 
analysieren und in Variablen die Erkentnisse ablegen.

Wozu soll das dann mit einem Timer ständig 'überprüft' werden?

> Lösungsansatz hatte ich auch schon mal versucht, hat bei mir aber nichts
> ausgelöst. Hier mal mein Code:
>
>             input = serialPort.ReadExisting();

Kein Mensch sagt, dass mit einem ReadExisting die komplette Zeile 
vorliegt. Du liest das, was bisher alles über die Serielle reingekommen 
ist.
Das kann der Text sein
  "0[?25l  in 0 = 0 >[?25h."
kann aber auch der Text
  "0[?25l  in 0 = "
sein, weil der Rest zum Zeitpunkt des Aufrufs noch gar nicht vollständig 
übertragen ist sondern die Zeichen noch auf der Leitung unterwegs sind.


Vielleicht solltest du mal den Code anderer Leute studieren, wie man 
eine Eventgetriebene Empfangsroutine in C# schreibt. So schwer ist das 
nicht und du kannst dabei nur lernen, wie man es richtig macht.

von sandman (Gast)


Lesenswert?

Er soll überprüfen, ob der Zustand des Ausganges sich von 0 auf 1 
geändert hat, und das ständig.

von Peter II (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Vielleicht solltest du mal den Code anderer Leute studieren, wie man
> eine Eventgetriebene Empfangsroutine in C# schreibt. So schwer ist das
> nicht und du kannst dabei nur lernen, wie man es richtig macht.

das hilft ihm aber überhaupt nicht weiter, er muss erstmal den Klartext 
extrahieren.

Und wenn der vorher etwas schicken muss, dann hilft ihm der event 
ansatzt auch nicht. Im event muss man dann selber noch die Daten 
zusammen ketten weil nicht  alles auf einmal kommt.

Und wenn ich die letzen Thread zu c# com und event suchen dann merkt man 
das der event ansatz mehr Probleme als lösungen schafft.

eine üblich Kommuniktion läuft ja so ab

sende
empfang beständigung
sende
empfang beständigung

Dabei hilft einem der Event überhaupt nicht weiter, weil man eh auf die 
bestätiung warten muss, dann kann man auch gleich ein Read machen.

von sandman (Gast)


Lesenswert?

hi peter,

bin auch eher Deiner Meinung mit dem Read. Denn wie gesagt, im Debugger 
von VisualStudio stehen halt die Sonderzeichen mit drin, habe mir 
überlegt, dass doch die Variante mit dem string input in eine char Array 
zu kopieren die beste Lösung geben würde. Dann könnte man doch mit einer 
for Schleife Zeichen rausfiltern. Nur weiss ich grad im Moment noch 
keinen sinnvollen Ansatz dafür

von Sven H. (dsb_sven)


Lesenswert?

Normalerweise schreibe ich die Daten, die ich im Event mit 
ReadExisting() bekomme in einen globalen Speicher (kann ne Liste mit 
Bytes sein oder ein String, an den angehängt wird oder oder oder) und 
jedes mal, wenn neue Daten hinzu kommen, prüfe ich, ob das, was ich 
erwarte, sei es nun eine definierte Länge oder ein Steuerzeichen oder 
wasauchimmer, angekommen wurde und starte dann die Verarbeitung der 
komplett empfangenen Daten.

Dazu braucht es keinen Timer. Der verzögert die ganze Sache sowieso nur, 
denn der Timer schlägt nämlich nie genau dann zu, wenn grade alle Daten 
da sind.


Also die Vorgehensweise nochmal in Schritten:

- Beim Event alle Daten von der Schnittstelle lesen und global ablegen 
(global meint hier eine Funktionsübergreifende Variable, sprich eine 
Eigenschaft der Klasse)
- Nach jedem Empfang prüfen, ob die Bedingung, die vollständigen Empfang 
aller Daten anzeigt, erfüllt ist
- Daten aus dem Puffer nehmen und verarbeiten

von Sven H. (dsb_sven)


Lesenswert?

Und das char Array brauchst du in c# nicht. Ein string stellt die die 
selben Möglichkeiten zur Verfügung und noch mehr!

stringname[index] gibt dir auch nur ein Zeichen zurück ;-)

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz Buchegger schrieb:
>> Vielleicht solltest du mal den Code anderer Leute studieren, wie man
>> eine Eventgetriebene Empfangsroutine in C# schreibt. So schwer ist das
>> nicht und du kannst dabei nur lernen, wie man es richtig macht.
>
> das hilft ihm aber überhaupt nicht weiter, er muss erstmal den Klartext
> extrahieren.

Was hilft ihm nicht?
Erst mal muss er ja wohl die komplette Antwort haben, ehe er den 
Klartext extrahieren kann.


> eine üblich Kommuniktion läuft ja so ab
>
> sende
> empfang beständigung
> sende
> empfang beständigung
>
> Dabei hilft einem der Event überhaupt nicht weiter, weil man eh auf die
> bestätiung warten muss, dann kann man auch gleich ein Read machen.

Das sind dann die Programme, die (überspitzt) das halbe Windows 
einfrieren, nur weil sie auf Antwort von der Gegenstelle warten.

von Peter II (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das sind dann die Programme, die (überspitzt) das halbe Windows
> einfrieren, nur weil sie auf Antwort von der Gegenstelle warten.

nein das ganze kommt ja in ein Thread.

Wie will man sonst sauber das Frage - Antwort spiel hinbekommen. 
Statemaschine schön und gut aber wie macht man dann ein Timeout - wieder 
mit Timer?

von sandman (Gast)


Lesenswert?

wieso, der string sieht jedesmal gleich aus wenn ich im debugger schaue, 
der unterschied ist nur wenn eine 1 anliegt oder eine 0, also  "in 0 = 
1" oder "in 0 = 0". müßte nur diesen bereich extrahieren können 
sinnvollerweise. was man oben in dem string nicht sieht ist, dass in den 
sonderzeichen auch noch ein <-- kleiner pfeil mit enthalten ist...... 
das macht es glaub noch schwieriger, den string zu extrahieren

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

sandman schrieb:
> das macht es glaub noch schwieriger, den string zu extrahieren

Wer sich beim Programmieren auf den GLauben verläßt hat es sowieso sehr 
schwer... C# (wie vermutlich jede andere Programiersprache) kennt auch 
eine Methode um su prüfen ob ein Teilstring in einem anderem enthalten 
ist, man müßte nur mal die Doku lesen und verstehen...

von Uwe (Gast)


Lesenswert?

Nicht ideal sollte aber schnell sein

for (i=0;emfpangsstring[i]!=0;i++)
{
if (empfangsstring[i]=='i')
 if (empfangsstring[i+1]=='n')
  if (empfangsstring[i+2]==' ')
   if (empfangsstring[i+3]=='=')
    if (empfangsstring[i+4]==' ')
    {
      wert=empfangsstring[i+5];
      wert=wert-0x30;
      if(wert==1) MsgBox("Wert ist 1");
    }
}

von Peter II (Gast)


Lesenswert?

Uwe schrieb:
> Nicht ideal sollte aber schnell sein

geht doch auch schöner

int i = emfpangsstring.IndexOf("in = ");
if ( i > 0 ) {
   wert = int.parse( empfangsstring[i+5] );
}

von sandman (Gast)


Lesenswert?

hallo uwe,

die hilfsvariable sollte auch als string deklariert werden, oder ? Bei 
int.parse kommt bei mir die Fehlermeldung, dass int keine Definition für 
parse enthält...........

von Peter II (Gast)


Lesenswert?

sandman schrieb:
> die hilfsvariable sollte auch als string deklariert werden, oder ?

warum ist es denn ein String?

> dass int keine Definition für
> parse enthält...........
schreib mal

int.Parse( empfangsstring[i+5] )

von sandman (Gast)


Lesenswert?

ich meinte die variable wert. bei int.Parse kommt auch ein fehler

von Peter II (Gast)


Lesenswert?

sandman schrieb:
> ich meinte die variable wert.

da muss ein int sein.

> int.Parse kommt auch ein fehler
und welcher?

kannst du überhaupt Programmieren? Denn solche fehler sollte man schon 
selber beheben können.


int.Parse( empfangsstring[i+5].ToString() )

von Sven H. (dsb_sven)


Lesenswert?

Wie wäre es denn mit
1
int empfangPruefen(string empfangsstring)
2
{
3
  if (empfangssting.Contains("0 = 0")
4
  {
5
    return 0;
6
  }
7
  else if (empfangsstring.Contains("0 = 1")
8
  {
9
    return 1;
10
  }
11
12
return -1;
13
}

von sandman (Gast)


Lesenswert?

hallo sven,

ich bin programmieranfänger, meine input Variable ist als string 
deklariert und nennt sich "input".

von Sven H. (dsb_sven)


Lesenswert?

Also, im Event könntest du in etwa so was machen:
1
// Vorhandene Daten einlesen
2
input += serialPort1.ReadExisting();
3
4
// Prüfen, ob ein gültiger string empfangen wurde
5
ergebnis = empfangPruefen(input);
6
7
// wenn ja, string ausleeren
8
if (ergebnis != -1)
9
{
10
  input = string.empty;    // das gleiche wie input = ""
11
}

Die Funktion "empfangPruefen" steht in einem meiner Post weiter oben.

Worüber du dir jetzt noch Gedanken machen musst ist
- kann es sein, dass zwei gültige Testabschnitte in "input" stehen? (wie 
schnell sendet denn der µC die Daten?)
- Wenn ja, wie stelle ich sicher, dass ich alle Daten auch auswerte
- Ist es nötig, sicherzustellen, dass nicht zwei Threads gleichzeitig 
auf die Variablen "input" und "ergebnis" zugreifen? (Hier wieder, wie 
lange dauert die Abarbeitung des Events und wie schnell kommen Daten am 
PC an?)
- Wenn ja, wie stelle ich das sicher? Reicht ein einfaches lock() { } 
oder muss ich mir deutlich mehr Gedanken machen?


Normalerweise brauchst du dir zum ausprobieren um die Fragen keinen Kopf 
zu machen. Wenn das allerdings mal irgendwo dauerhaft laufen soll, 
kannst du dir es nicht leisten, solche Punkte außer Acht zu lassen.

von sandman (Gast)


Lesenswert?

// Vorhandene Daten einlesen
input += serialPort1.ReadExisting();

// Prüfen, ob ein gültiger string empfangen wurde
ergebnis = empfangPruefen(input);

// wenn ja, string ausleeren
if (ergebnis != -1)
{
  input = string.empty;    // das gleiche wie input = ""
}


alse den Teil schreibe ich in mein Timer rein ?

von Sven H. (dsb_sven)


Lesenswert?

Nein. In das Event, dass die serielle Schnittstelle dir rauswirft. 
Vergiss den Timer einfach ;-)

von W.S. (Gast)


Lesenswert?

Reden wir hier etwa über Windows? Ja?
Da wird (ganz unten, auf der API-Ebene von Windows) eine Datei 
aufgemacht, wenn man einen COM-Port öffnen will. Als Ergebnis gibt es 
ein Handle auf diese Datei - aber es gibt per se keinerlei 
Empfangs-Event.

Möglicherweise gibt es in den Untiefen der zugehörigen C# Runtime 
irgendeine Hook-Funktion, die über ClearCommError(hPort, dwErrorCode, 
&statPort) und dann statPort.cbInQue ermittelt, ob es unabgeholte 
Zeichen gibt und dann einen vorher definierten Event auslöst / über 
Broadcast oder dediziert ist ja egal.

Aber das Ganze scheint mir hier ja völlig daneben zu liegen. Lest doch 
mal gründlich:

sandman schrieb:
> ich versuche mit einem Timer in C# über die RS232 - Schnittstelle einen
> Eingang vom STM32 ständig abzufragen.

Er will "einen Eingang vom STM32 abfragen"! Was soll das? Bloß eine 
falsche Formulierung? Ich nehme mal an, er will einen Ausgang vom STM32 
abfragen, der an irgendein Input-Handshake-Bein der RS232 gelegt wurde. 
Also, welchen Zustand RTS, DSR usw. haben. Ich kann jedenfalls nicht 
sehen, daß der STM32 irgendein sinnvolles Zeichen über die eigentliche 
TxD-->RxD Linie schickt. Also ist es sinnlos, über das Ausfiltern von 
empfangenen Bytes zu diskutieren.

W.S.

von Sven H. (dsb_sven)


Lesenswert?

In C# wird ein Event ausgelöst, wenn Daten Empfangen wurden.

Für eine Änderung der Steuerleitungen wird ebenfalls ein Event 
ausgelöst.

von Uwe (Gast)


Lesenswert?


von hinz (Gast)


Lesenswert?

W.S. schrieb:
> Er will "einen Eingang vom STM32 abfragen"! Was soll das? Bloß eine
> falsche Formulierung? Ich nehme mal an, er will einen Ausgang vom STM32
> abfragen, der an irgendein Input-Handshake-Bein der RS232 gelegt wurde.

Was das soll? Der Zustand eines Eingangs des STM32 soll auf den PC 
übertragen werden. Glaub es einfach, statt irgendetwas anzunehmen.

von Starkstromer (Gast)


Lesenswert?

Hat das vielleicht was mit einem STM32 in Verbindung mit OBD von Auto's 
zu tun? Also auswerten einer Meldung von einem Steuergerät des Autos per 
OBD.
Ich vermute das mal, weil anstatt Hyperterminal- oder VT100 Krempel 
könnten das ja entsprechende "Anweisungen" für's Steuergerät sein, die 
und die Infos bzw Daten rüber zu geben.

Also, hat STM32 in dem Falle was mit OBD zu tun?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.