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
Und was soll das Exception fangen bringen, wenn nirgendwo eine geschmissen wird? Der Aufhänger wird wohl eher in den nicht geposteten Programmteilen liegen.
@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
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).
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
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.
@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
Ich sehe nirgends einen Aufruf von SetCommTimeouts Du musst die Funktion schon auch aufrufen. Die Struktur ausfuellen ist zuwenig!
[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
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.
Vorher setzten, dann beachtet Readfile die Werte auch. Deine Erkärung, warum vorher sinnlos ist versteh ich leider nicht.
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.