Comport: zeitkritische timeouts



  • Hi,

    versuche seit einigen Tagen ein zeitbasiertes Protokoll auf RS232 zu
    implementieren, allerdings machen diverse Timeouts tierischen Stress:

    Aufeinanderfolgende Bytes innerhalb eines Datenblocks haben max. 8 Millisekunden Abstand, von Datenblock zu Datenblock vergehen 12 < t < 50 ms.

    Laut Analyzer vergehen im konkreten Fall ca. 40 ms zwischen zwei Datenblöcken,
    aber im Idealfall sollte das Programm auch mit 12 zurecht kommen.

    Das Problem besteht darin, dass RX und TX über die selbe Leitung laufen und
    daher das TX nur zwischen zwei Blöcken erfolgen kann.

    So wie ich's bisher verstanden hab, hab ich also genau 4ms Zeit, um
    den "Interblock Gap" zu erkennen (nach Definition) bzw. 32ms im konkreten Fall.

    Mit meinem Latein bin ich inzwischen am Ende...

    Laufen soll das ganze unter WinXP.
    Meine erste Vermutung war, dass es nicht geht, weil win nicht Echtzeitfähig ist.
    Aber auf dem selben Rechner läuft Software für eine ähnliche Geschichte und da
    haben zwei Datenblöcke laut Sniffer sogar nur 18 Millisekunden Abstand.
    Und funktionieren tut's trotzdem perfekt...

    CreateFile (str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    SetupComm(hComm, 132, 1024);
    SetCommState(hComm, &dcb); // DCB erzeugt mittels BuildCommDCB(L"baud=200  Parity=N data=8 stop=1", &dcb)
    
    COMMTIMEOUTS cto;
    cto.ReadIntervalTimeout = 30;
    cto.ReadTotalTimeoutMultiplier = 11;
    cto.ReadTotalTimeoutConstant = 50;
    cto.WriteTotalTimeoutMultiplier = 0;
    cto.WriteTotalTimeoutConstant = 0;
    SetCommTimeouts(hComm, &cto); 
    
    // Kommunikationsaufbau
    //----------------------
    // Ein Byte senden
    // Warten
    // Umschalten auf 9600 Baud
    // 3 Byte empfangen 
    // Antwort senden
    
    // Kommunikation ist eröffnet
    //--------------------
    // externes Gerät sendet jetzt alle t=40ms  (12ms < t < 50ms) Daten  (max. 132 Byte);
    
    // Wenn der Rechner eine Anfrage stellt, muss er das zwischen zwei Datenblöcken machen.
    // Und wie findet man jetzt dieses "Loch"?
    
    // das hab ich aus bestehender Software abgekupfert:
    
    // 1) Timeouts in cto auf (13, 11, 50, 0, 0) setzten
    // 2) in einer while-Schleife solange einzelne Byte empfangen bis ein Timeout auftritt.
    //    für jedes Empfangene Byte den Lesepuffer leeren:
    // 2.1 Timeouts auf (MAXWORD, 0, 0, 0, 0) setzten, dann blockiert ReadFile nicht mehr
    // 2.2 in Schleife solange lesen, bis nichts mehr empfangen wird
    // 23. Timeouts zurücksetzen
    // 3) nach der Whileschleife:Das nächste empfangene Byte ist der Beginn des nächsten Blocks
    // 4) Timeouts auf (50, 11, 50, 0, 0) setzten
    // 5) das nächste empfangene Byte soll der Beginn eines Blocks sein. Diese Byte gibt die Länge des
    //   Blocks an
    // 6) Restliche Bytes des Blocks empfangen
    
    // JETZT sind wir zwischen zwei Blöcken:
    // ---> Anfrage senden
    

    Problem:
    entweder wird bei 5) oder 6) ein Timeout erkannt, oder wenn doch mal was auf die Leitung rausgeht,
    dann völlig unkontrolliert und i. d. R. nicht in dem Zeitfenster zwischen zwei Blöcken.

    Folge: Anfrage schlägt fehl

    Hab auch schon an den Timeouts gedreht, weil meiner Meinung nach müssten die eher (8, 0, 0, 0, 0) lauten,
    aber das allerselbe Trauerspiel.

    Oder als alternativ mal mittels WaitCommEvent() auf die Daten gewartet und mittels timeGetTime() die
    Abstände zwischen den Bytes ermittelt. Aber die kommen da irgendwie völlig unkontrolliert rein...

    Ähnliches gilt für aktives Polling der Funktion ReadFile(): die meisten Bytes haben 0ms Abstand (laut Analyzer
    aber 3-4) und mittendrin sind wieder welche mit 15 - 63ms dabei.
    Aber da hat vermutlich der Billy schuld...

    Sollte jemand bis hierher gelesen haben: danke und hoffentlich kannst du mir einen Tipp geben.

    mfg
    Martin

    PS:
    Hab auch schon die Quellcodes der funktionierenden Software verwendet (im Prinzip selbes Protokoll, nur sind einige Statusbytes anders).
    Aber auch die machen in meinem Programm immer den selben Ärger.

    Leider kann ich das funktionierende Programm nicht übersetzten, weil das noch einige Abhängigkeiten hat, die
    mir allerdings nicht vorliegen...
    Wär schon mal interessant, ob das dann noch laufen würde...


Anmelden zum Antworten