Mal wieder der ComPort, 2 Versionen, fast gleich eine tut eine nicht



  • Ja, die überschrift ist nicht sehr aussagekräftig,
    wusste nicht wie ich mein Problem kurz beschreiben soll.
    Ich habe eine ComPort Klasse, in einer älteren Version setze ich
    gleich beim öffnen auch alle Parameter also, Baudrate, parity Bits,
    etc.. in einer neuen Version habe ich das in zwei Methoden
    aufgeteilt. Das Problem ist jetzt das die alte Klasse funktioniert
    und die neue Klasse nicht. Der restliche Code in der Klasse ist
    unverändert oder nur irrelevant. Das Error Handling habe ich
    teilweise entfernt, ist so noch genug Code.

    Die alte Version

    void ComPort::openPort(string port)
    {
       bool abbruch = false;
       string temp;
       // Handle öffnen
       temp = "\\\\.\\" + port;
       comHandle = CreateFile( temp.c_str(), // Com Port Name
    			   GENERIC_READ | GENERIC_WRITE,
    			   0, // exclusiv Zugriff
    			   NULL, // default Security Attribut
    			   OPEN_EXISTING, // muss halt so sein
    			   0, // not overlapped I/O
    			   NULL // muss NULL sein für Com Zugriff
    			   );
    
       // Error Handling
       if(comHandle == INVALID_HANDLE_VALUE && abbruch != true)
       {
    	  // error handling... -> Funktion wird NICHT abgebrochen
       }
    
       // momentane config auslesen
       bool hatGeklappt;
       hatGeklappt = GetCommState(comHandle, &configuration);
    
       // Error Handling
       if(hatGeklappt != true && abbruch != true)
       {
    	  // error handling... -> Funktion wird NICHT abgebrochen
       }
    
       // config Befüllen
       configuration.DCBlength = sizeof(DCB);
       configuration.BaudRate = CBR_38400;
       configuration.ByteSize = 8;
       configuration.Parity = NOPARITY;
       configuration.StopBits = ONESTOPBIT;
    
       // Daten schreiben
       hatGeklappt = SetCommState(comHandle, &configuration);
    
       // Error Handling
       if(hatGeklappt != true && abbruch != true)
       {
    	  // error handling... -> Funktion wird NICHT abgebrochen
       }
       else if(abbruch != true)
       {
    	  // error handling... -> Funktion wird NICHT abgebrochen
       }
    }
    

    Die neue Version

    int ComPort::openPort(string port)
    {
       string temp;
       // Handle öffnen
       temp = "\\\\.\\" + port;
       comHandle = CreateFile( temp.c_str(), // Com Port Name
    			   GENERIC_READ | GENERIC_WRITE,
    			   0, // exclusiv Zugriff
    			   NULL, // default Security Attribut
    			   OPEN_EXISTING, // muss halt so sein
    			   0, // not overlapped I/O
    			   NULL // muss NULL sein für Com Zugriff
    			   );
    
       // Error Handling
       if(comHandle == INVALID_HANDLE_VALUE)
       {
    	  lastError = "Fehler beim öffnen: " + valueToString(GetLastError());
    	  return -1;
       }
       else
       {
    	  lastError = "ComPort erfolgreich geöffnet";
    	  return 0;
       }
    }
    
    // Aufruf sieht so aus: cp->setCommConfig(CBR_38400, 8, NOPARITY, ONESTOPBIT);
    int ComPort::setCommConfig(int baudRate, int bytes, int parity, int stopBits)
    {
       // momentane config auslesen
       bool hatGeklappt;
       hatGeklappt = GetCommState(comHandle, &configuration);
    
       // Error Handling
       if(hatGeklappt != true)
       {
    	  lastError = "Fehler beim config lesen: " + valueToString(GetLastError());
    	  return -1;
       }
    
       // config Befüllen
       configuration.DCBlength = sizeof(DCB);
       configuration.BaudRate = baudRate;
       configuration.ByteSize = bytes;
       configuration.Parity = parity;
       configuration.StopBits = stopBits;
    
       // Daten schreiben
       hatGeklappt = SetCommState(comHandle, &configuration);
    
       // Error Handling
       if(hatGeklappt != true)
       {
    	  lastError = "Fehler beim config schreiben: " + valueToString(GetLastError());
    	  return -1;
       }
       else
       {
           lastError = "Config erfolgreich geschrieben";
    	   return 0;
       }
    }
    

    Danke an alle die sichs durchlesen!

    Gruß,

    Max



  • Uns allen würde viel mehr weiterhelfen (oder zumindestens weniger Ratespiele a la Kristallkugel) wenn präzisere Problembeschreibung ins Forum gepostet werden.

    Die pauschale Aussage "funktioniert nicht" ist hier Forum nicht gern gesehen.

    Nun, um die Ursache Deines Problems einzugrenzen, welcher Text wird beim Öffnen des COM-Ports ausgegeben? Den Text "Fehler beim öffnen: xx" oder den Text "ComPort erfolgreich geöffnet"?

    Martin



  • Nach jeder API Funktion, bei der du Probz vermutest, GetLastError() nutzen. Ich versteh ned warum ihr ned mal GetLastError() benutzt, die funktion ist ned nur zur zierde da. sie liefert euch so gut wie immer einen aussagekräftigen fehlercode zurück.



  • Oder benutze doch einfach eine getestete und sauber geschriebene Klasse die schon existiert:
    http://www.codeproject.com/KB/system/serial.aspx



  • So, stimmt ich sollte den Fehler genauer beschreiben.
    GetLastError benutze ich hab nur das Error Handling teils rauseditiert
    damits überischtlicher wird.

    Neine, eine fertige Klasse möchte ich nicht, danke 😉

    Das Problem ist nichtmal das öffnen, sondern das schreiben.
    Nur, die write Methode ist bei beiden Versionen exakt gleich,
    ich habe das Problem schon auf diesen Part eingegrenzt. Irgendwo
    in diesem Code muss ein Fehler sein welcher dazu führt das ich mit
    der alten Version anderst schreibe als in der neuen.
    WriteFile führt auch zu keinem Fehler, alles kein Problem, der Fehler
    muss irgendwie bei SetCommState liegen vermute ich.

    Gruß,

    Max



  • dann guck halt ob das handle in der funktion auch echt noch gültig ist und die anderen werte, ist doch easy



  • blub² schrieb:

    WriteFile führt auch zu keinem Fehler, alles kein Problem, der Fehler muss irgendwie bei SetCommState liegen vermute ich.

    Wenn WriteFile zu keinem Fehler führt, dann kann SetCommState auch nicht der Fehler sein.

    Irgendwie beschreibst (und postest) Du nur die Hälfte des Problems.


  • Mod

    blub² schrieb:

    Neine, eine fertige Klasse möchte ich nicht, danke 😉

    Dann ist Dir allgemein kaum helfen. Warum willst Du das nicht?



  • Naja, soweit zu gehen, ihm zu sagen, ihm sei nicht mehr zu helfen, würde ich nicht wagen 😃

    Ernsthaft gibt es schon sinnvolle Erwägungen, die jemanden dazu bringen, keine vorgefertigten Klassen zu nehmen. Didaktisch, d.h. man möchte es durch selbermachen verstehen (laut Pädagogen und Didaktikern die besten Lernweise). Oder die Software darf keine 3rd-Party-Sachen enthalten, Stichwort Lizenzbindung an z.B. GPL oder ähnliches. Und selbst völlig freie Dinge dürfen nicht immer verwendet werden, manche Kunden möchten gerne alles neu und aus einer Hand haben.

    Manchmal muss man es einfach selbst machen...



  • blub² schrieb:

    // config Befüllen
       configuration.DCBlength = sizeof(DCB);
       configuration.BaudRate = baudRate;
       configuration.ByteSize = bytes;
       configuration.Parity = parity;
       configuration.StopBits = stopBits;
    

    Ich würde die DCB-Struktur grundsätzlich komplett neu definieren (also auch die anderen Members).
    Ansonsten hast Du hin und wieder gefährliche Stolperfallen, wenn Du beim Auslesen mit GetCommState() plötzlich "Handshake aktiviert" usw. in der Struktur vorfindest.

    Martin



  • mad_martin schrieb:

    Didaktisch, d.h. man möchte es durch selbermachen verstehen (laut Pädagogen und Didaktikern die besten Lernweise).

    Das meine ich 😃

    Ok, um mal mein Problem noch genauer zu beschreiben:
    Ich schreibe ein Programm das Daten in den Speicher einer
    Maschine schreibt. Mit der älteren Version funktioniert das wunderbar,
    mit der neueren nicht!
    Das komische: Ich schreibe mit beiden Versionen genau die
    gleichen Daten in die Schnittstelle (überprüft mit so einem Serial
    Port Monitor Tool). Allerdings kriege ich nur eine Antwort
    von der Maschine wenn ich die alte Version benutze.
    Die Write Methode ist > exakt < gleich geblieben (copy & paste ;)),
    nur die open Methode hat sich verändert durch das zerlegen in zwei
    Methoden.

    Naja, ich werd noch ein bisschen rumprobieren und mich nochmal melden.

    Gruß,

    Max

    PS: Danke Mmacher, werde ich noch implementieren!



  • blub² schrieb:

    Die Write Methode ist > exakt < gleich geblieben (copy & paste ;)),
    nur die open Methode hat sich verändert durch das zerlegen in zwei
    Methoden.

    Da kommt in mir der Verdacht auf, daß Du mit dem Handling von Variablen irgendwas falsch gemacht hast.
    Beispiele (in Anlehnung an Deine Quellcodes wieiter oben):
    -Gültigkeit der lokalen Variablen?
    -Übergebe ich wirklich einen Pointer zum String (und nicht etwa nur den ersten Buchstaben) an die Funktionen
    -Zeigt der Pointer auf einen gültigen Speicherbereich? Ist dieser Speicher auch reserviert?

    Martin

    P.S.: Was passiert eigentlich, wenn Du die beiden zerlegten Open-Funktionen wieder zu einer zusammenfügst? Gleiches Fehlerbild?



  • blub² schrieb:

    Die Write Methode ist > exakt < gleich geblieben (copy & paste), nur die open Methode hat sich verändert durch das zerlegen in zwei
    Methoden.

    Schon besser. Greift zwischen beiden Aufrufen ev. etwas auf den Port zu (Taskswitch reicht schon) ?



  • Taskswitch?wie soll er den denn verhindern



  • merker schrieb:

    blub² schrieb:

    Die Write Methode ist > exakt < gleich geblieben (copy & paste), nur die open Methode hat sich verändert durch das zerlegen in zwei
    Methoden.

    Schon besser. Greift zwischen beiden Aufrufen ev. etwas auf den Port zu (Taskswitch reicht schon) ?

    Ob das eine oder zwei Methoden sind, hat aber keinen Einfluss auf die Task Switschereil.



  • Europa4 schrieb:

    Taskswitch?wie soll er den denn verhindern

    Spezifisch auf die zitierte Frage: Thread Synchronisierungs Mechanismen.



  • ...
    Das Problem lag in der Read Methode.
    Sorry das ich euch mit dem Mist hier belästigt hab 😕
    Das Problem ist dass man ja bei ReadFile angeben muss
    wieviele Bytes man lesen will.
    Bzw, ich hab dass so verstanden dass ich die maximale
    Anzahl an Bytes angeben muss. Es tut allerdings nur richtig
    wenn ich maximal so viele Bytes angebe wie auf dem Input
    Buffer liegen! Weiß jemand wie ich auslesen kann wieviele
    Bytes darin liegen? Oder muss ich die ganze Zeit
    WaitCommEvent() laufen lassen?

    Danke,

    Max


Log in to reply