Datenübertragung Win7 <-> µC



  • Hallo,

    ich hab derzeit so meine Probleme mit der Funktion WriteFile. Aber mal etwas im Detail.

    In meinem C++ Programm auf einem Win7 Rechner errechne ich Fahrbefehle für einen Roboter, diese will ich über USB->UART an den µC senden damit dieser die ausführt.
    Ein Befehl besteht im grunde nur aus 3 Integerzahlen, die beiden Geschwindigkeiten für die Motoren und die Distanz. Dafür nutz ich derzeit WriteFile. Dabei erzeuge ich ein CString der die 3 Zahlen enthält und übergebe diesen CString an WriteFile.

    Der Code sieht so aus:

    bool CComPort::WriteCOM(HANDLE hFile, CString x)
    {
    	DWORD dwBytesWritten;
    	DWORD dwBytesToWrite;
    	LPSTR lpByte;
    	BOOL fWriteStat;
    
    	dwBytesToWrite = x.GetLength( );
    	lpByte = x.GetBuffer(dwBytesToWrite);
    
    	fWriteStat = WriteFile(hFile, lpByte, dwBytesToWrite, &dwBytesWritten, NULL);
    
    	return fWriteStat;
    }
    

    Das funktioniert alles auch soweit es gibt nur ein Problem, WriteFile braucht viel zu lange für das was ich tun will. Ich hab die Zeitmessung wie lang es dauert WriteFile auszuführen mit den QueryPerformanceCounter gemacht, die Ergebnisse sind sehr unterschiedlich. Mal dauert es 6,6ms mal aber auch >800ms, meist aber so zwischen 200-400ms. Für mich akzeptabel wären 50ms bis 100ms, da ich eigentlich eine Regelung des Roboters machen möchte.

    Leider bin ich auf dem Gebiet der Datenübertragung kein Experte, hat daher jemand eine Idee oder ein Anhaltspunkt, woran es liegt dass es doch so lange dauert 3 Zahlen zu übertragen? Oder wie man das Problem umgehen könnte, alternative Funktionen die schneller sind?



  • Was genau dauert denn so lange, der komplette WriteCOM Aufruf oder tatsächlich nur der WriteFile Aufruf?



  • WriteFile schmeisst die Daten erstmal nur in einen internen Puffer, der dann asynchron über die COM Schnittstelle rausgehämmert wird. Wenn der Puffer voll ist, dann wird gewartet. Und das kann dann recht lange dauern, weil die "wie viel ist noch frei im Puffer" Information vermutlich nicht bytegenau upgedated wird.

    Probier mal nach dem WriteFile Aufruf ein FlushFileBuffers zu machen. Wenn ich mich richtig erinnere, sollte das dazu führen, dass er dann bei jedem WriteCOM Aufruf wartet, bis die Daten wirklich über die serielle Schnittstelle rausgeschickt wurden.

    Dadurch sammelt sich im Puffer nix mehr an, dadurch wird der Puffer nie mehr voll. D.h. die unverhältnismässig langen Pausen dürften dann nicht mehr auftreten.

    @DocShoe
    Der WriteFile Aufruf dauert so lange -- sonst ist da ja nichts was lange dauern könnte.



  • so ich bins nochmal, erstmal danke an DocShoe und hustbaer dass ihr euch mit meinem Problem beschäftigt habt.

    @DocShoe es war wirklich der WriteFile-Aufruf.

    @hustbaer ich hab das FlushFileBuffers mit eingebaut, aber was war nicht die Ursache.

    Die Ursache für mein Problem lag ganz wo anders. Ich hate noch einen Thread im Hintergrund laufen, der nur damit beschäftigt war die Schnittstelle auszulesen, ob der µC einprogrammierte Infos zurücksendet die vom C++ Programm dann verarbeitet werden müssen je nach Info die zurück geliefert wird.

    Ich denke dass so wie der Thread programmiert war sich das Lesen und Schreiben am Port gegenseitig behindert hat und ne Art Flaschenhals entstanden ist. Das hab ich mitlerweile behoben.

    Allerdings hab ich noch eine letzte Frage. Wenn ich mit ReadFile über den Thread auslese und dort ist nix zum auslesen weil der µC nix zu senden hat. Dann benötigt ReadFile immer so 17-24ms bis es aufhört was lesen zu wollen und blockiert in der Zeit denk ich das WriteFile. Hingegen wenn es was zum auslesen gibt dauert es gerade mal 24-40µs, also deutlich schneller. Kann man irgendwie dafür sorgen dass ReadFile schneller "aufgiebt" etwas zu lesen?

    die timeouts für dem COM hab ich wie folgt festgelegt:

    m_CommTimeouts.ReadIntervalTimeout = 1;
    m_CommTimeouts.ReadTotalTimeoutMultiplier = 1;
    m_CommTimeouts.ReadTotalTimeoutConstant = 1;
    m_CommTimeouts.WriteTotalTimeoutMultiplier = 1;
    m_CommTimeouts.WriteTotalTimeoutConstant = 1;
    

Anmelden zum Antworten