Forum: PC-Programmierung Receive von RS232 absichern


von Stefan (Gast)


Lesenswert?

Hi.
Ich hab mir in C++ ein Programm geschrieben, mit dem ich unter anderem
Zeichen von meinem µC empfangen kann.

Ich behandle die mit Hilfe meiner Funktionen "sende_COM,empfange_COM"
die RS232-Schnittstelle wie eine Datei (Createfil, Readfile).
Mir ist beim testen aufgefallen das wenn ich von der PC-Seite lesen
will, mein µ-Controller aber nicht sendet, sich das Programm aufhängt.

Auf meinem Rechner habe ich dies Problem zwar nichtmehr, aber um auf
Nummer sicher zu gehen würd ich mir da gerne "etwas" einbauen das den
Fehler abfängt.

Ich dachte erst an eine Try-Catch Anweisung, aber das klappt nicht. :(

empfange_COM
{
//
hCom = CreateFile
//
ReadFile(hCom,&zeichen,1,&dwBytesRead,0);
CloseHandle(hCom);
}

.
.
.
try
{
    empfange_COM();
}
catch(...) // "..." sollte alle Fehler abfangen.
{
    cout<<"Fehler beim lesen der RS232"<<endl;
}
.
.
.


Ich hoffe ich bin nicht komplet auf dem falschen Weg, und ihr könnt mir
ein bisschen weiterhelfen.

MFG Stefan

von Tobi H. (tobi-) Benutzerseite


Lesenswert?

Und was soll das Exception fangen bringen, wenn nirgendwo eine
geschmissen wird?
Der Aufhänger wird wohl eher in den nicht geposteten Programmteilen
liegen.

von Stefan (Gast)


Lesenswert?

@Tobi Und was soll das Exception fangen bringen

Also eigentlich hatte ich vor das wenn ich eine gewisse Zeit versuche
Daten von der Com zu lesen, das aber nicht klappt ich im Programm
"weiterspringe" also nicht die ganze Zeit auf eine Eingabe warte.
Dafür habe ich aber keine Funktion gefunden. Statt dessen bin ich auf
die Funktion "try-catch" gestossen und dachte mir damit könnte es
auch klappen.

Ps.:
Hier meine Funktion:
empfange_COM ()
{
   DWORD dwBytesWritten;
   char *pcCommPort="Com3";  //Hier die Schnittstelle auswählen

   hCom = CreateFile( pcCommPort,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    NULL, // no security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    0,    // not overlapped I/O
                    NULL  // hTemplate must be NULL for comm devices
                    );
   dcb.BaudRate = CBR_9600;     // set the baud rate
   dcb.ByteSize = 8;             // data size, xmit, and rcv
   dcb.Parity = NOPARITY;        // no parity bit
   dcb.StopBits = ONESTOPBIT;    // one stop bit

   ReadFile(hCom,&zeichen,1,&dwBytesRead,0);
   CloseHandle(hCom);
   return(0);
}

Wenn ich mit meinem µC was schicke klappt alles super, nur wie gesagt
bei einer "Störung" (µC schickt nichts zum PC) bleibt die PC-Software
hängen.

MFG

von asddas (Gast)


Lesenswert?

Ich denke das Problem ist, das ReadFile blockiert solange nichts
empfangen wurde. Schau mal in der MSDN nach.

Du kannst es in einen Thread auslagern oder einfach pollen bis was
empfangen wurde (synchron/asynchron).

von T. Stütz (Gast)


Lesenswert?

Um einen (Empfangs-) Timeout zu machen genügt das Aufrufen der Funktion
SetCommTimeouts mit entsprechenden Parameter (ausgefüllte Struktur)

Bei richtiger Wahl kommt ReadFile zurück wenn eine bestimmte Zeit
abgelaufen. => MSDN,Dokumentation zu SetCommTimeouts beachten

Gruss

von Alex (Gast)


Lesenswert?

Am besten sind für sowas Threads. Du erzeugst einen Thread, der laufend
die COM kontrolliert und meinetwegen die Frames (falls du dir ein
simples Protokoll definiert hast) empfängt und kontrolliert.
Gleichzeitig organisiert dieser Thread einen Empfangspuffer und
signalisiert dem Hauptthread (im Endeffekt der Visualisierung), wenn
komplette Daten vorliegen.

von Stefan (Gast)


Lesenswert?

@asddas,Alex
Also eure Mehtoden mögen zwar evtl. die besseren sein, aber da ich
nicht soo fit im programieren bin (pollen? ich kenn nur pullern :) ),
werd ich mir lieber mal das mit den Setcommtimeouts anschauen.

Leider klappt es aber auch nicht:

empfange_COM ()
{
   DWORD dwBytesWritten;
   char *pcCommPort="Com3";  //Hier die Schnittstelle auswählen
   COMMTIMEOUTS cto;
   hCom = CreateFile( pcCommPort,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    NULL, // no security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    0,    // not overlapped I/O
                    NULL  // hTemplate must be NULL for comm devices
                    );
   //RS232 konfigurieren
   dcb.BaudRate = CBR_9600;     // set the baud rate
   dcb.ByteSize = 8;             // data size, xmit, and rcv
   dcb.Parity = NOPARITY;        // no parity bit
   dcb.StopBits = ONESTOPBIT;    // one stop bit
   //Com-Lese-Timeouts konfigurieren
   cto.ReadIntervalTimeout = 500; //Da ich nur ein Byte empfangen will,
ist der Wert glaub ich egal.
   cto.ReadTotalTimeoutMultiplier = 500; //Sollte bei mir glaub ich
auch egal sein.
   cto.ReadTotalTimeoutConstant = 500; //TimeConst+Multiplier*1Byte
=1sec das sollte locker reichen um zu merken das was nicht stimmt
   cto.WriteTotalTimeoutMultiplier = 0;
   cto.WriteTotalTimeoutConstant = 0;

   ReadFile(hCom,&zeichen,1,&dwBytesRead,0);
   CloseHandle(hCom);
   return(0);
}


Das Programm wird zwar kompiliert, aber es bleibt trotzdem "hängen"
wenn ich auf Daten warte un keine ankommen.
Was sollte den genau passieren wenn ich jetzt 1sec. versuche zu lesen,
aber keine Files empfange?
Springe ich dann einfach in die nächste Zeile weiter?
(-CloseHandle(hCom); ?

-Ich seh schon, das wird wohl wieder ein Sonntag vorm Rechner, -zur
Freude meiner Freundin :(

MFG

von Karl H. (kbuchegg)


Lesenswert?

Ich sehe nirgends einen Aufruf von
SetCommTimeouts
Du musst die Funktion schon auch aufrufen. Die Struktur
ausfuellen ist zuwenig!

von Stefan (Gast)


Lesenswert?

[Du musst die Funktion schon auch aufrufen.]

Hab ich auch schon dran gedacht ;)
Aber wo soll ich das aufrufen?
Bevor, oder nachdem ich auf der RS232 auf ein Zeichen warte?
In meinen Augen macht beides kein Sinn.
1.)Ruf ich es vorher auf, kann ich lange warten da ich ja
nochnichteinmal auf ein Zeichen warte.
2.)Rufe ich es nach meinem ReadFile-Befehl auf, ist ja eh alles zu
spät, da mein Rechner dann schon hängt.

Ich hatte gehofft das mit dem anlegen der Struktur evtl. automatisch
die Daten in die Readfile-Funktion eingebunden werden.

Kannst du mir bite sagen wie das "richtige" Einbinden geht?


Ps.: Schönen 1. Advent

MFG

von asddas (Gast)


Lesenswert?

Du hast dir die Antwort ja im Grunde schon selber gegeben, nach dem
ReadFile blockiert das Programm, da kann nichts mehr passieren.

Vielleicht hilft dir der Artikel bzw. das Demoprogramm ein bisschen
weiter:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp

Ansonsten musst du einfach mal ein bisschen im Internet suchen, da
finden sich sicherlich fertige Lösungen.

von Tobi H. (tobi-) Benutzerseite


Lesenswert?

Vorher setzten, dann beachtet Readfile die Werte auch. Deine Erkärung,
warum vorher sinnlos ist versteh ich leider nicht.

von Karl H. (kbuchegg)


Lesenswert?

> Aber wo soll ich das aufrufen?

Ich denke, Dir ist absolut nicht klar wie sowas funktioniert.
SetCommTimeouts() setzt das I/O System in einen Zustand.
Dieser Zustand, in diesem Fall die zu verwendenden Werte
fuer die Timeouts, werden dann beim naechsten ReadFile
Aufruf benutzt um das Verhalten dieses Aufrufs zu steuern.
In dieselbe Kategorie faellt auch Dein Setzen der dcb-Werte.
Voellig sinnlos, solange Du dem I/O System nicht mitteilst,
das es diese auch verwenden soll.

Im uebrigen gibt es fuer so gut wie alles was mit Windows-
Programmierung zusammenhaengt, Demos im Web. Ich rate Dir
eindringlich, nach solchen Demos zu suchen und diese zu studieren.
Nicht einfach uebernehmen, nein, studieren. Warum wird jener
Aufruf gemacht? Welche Werte werden wann, warum und wo gesetzt?
Das alles muss Dir aus dem Demo klar sein. Dann wird das Demo
etwas abgewandelt: Was passiert, wenn ich jenen Wert aendere?
Wenn ich das nun so umaendere, muesste sich das System jetzt
eigentlich so verhalten. Tut es das auch? Wenn ja, ist das ein
starkes Indiz, das Du am richtigen Weg bist. Wenn nein, dann hast
Du noch irgendwo einen Denkfehler und musst weiter studieren.

Man kann Microsoft viel vorwerfen. Auch in Bezug auf die Qualitaet
ihrer Doku. Aber fuer praktisch alle API Calls gibt es in der MSDN
eine meist umfangreiche Dokumentation, die meist auch ein
kurzes Demo-Program zeigt. Alles online erreichbar, per Google
leicht zu finden.

Nimms nicht persoenlich: Aber wenn Du nicht mindestens bereits
ein paar andere Libraries erforscht und anwenden gelernt hast,
dann ist das was Du hier machst zum Scheitern verurteilt: Ein
Programmieren nach dem Prinzip 'Versuch und Irrtum' funktioniert
bei Neulingen nicht. Besorg Dir Literatur, die dich in die
Grundbegriffe einfuehrt, sonst kommst Du nicht weit. Insbesondere
nicht in C++.

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.