Virtuellen COM-Port schnell auslesen
-
Ich habe einen virtuellen COM-Port über USB. Ich kann den COM-Port erfolgreich auf verschiedene Arten auslesen. Das Problem ist, dass die Datenrate zu langsam ist, ich komme nur auf ~160kb/s während Realterm (http://sourceforge.net/projects/realterm/) auf ~327kb/s kommt. Die höhere Datenrate ist für die Anwendung notwendig.
Es könnte an der Konfiguration liegen:
Da der COM-Port eigentlich ein USB-Port ist macht es keinen Unterschied welche Baud-Rate man bei SetCommState angibt (mit Realterm getestet, Baud-Rate von 300 ergibt trotzdem ~327kb/s) oder welche Buffergröße man bei SetupComm angibt (Der USB-Treiber ignoriert den Wert).
Es gibt noch einige Variablen, denen ich keinen sinnvollen Wert zuzuweisen weiß, wie zum Beispiel DTR-Control, XON-Char und ähnliche. Ich habe die Werte per COM-Sniffer von Realterm übernommen, ich denke der USB-Treiber ignoriert sie.Es könnte auch am Auslesen liegen:
Im Moment benutze ich overlapped IO um in einer Schleife ReadFile und GetOverlappedResult aufzurufen. Ich habe einen 1MB großen Buffer der nie voll läuft. Mehrere overlapped Operationen gleichzeitig funktionieren, erhöhen aber insgesamt die Datenrate nicht.ClearCommError liefert nie einen Fehler zurück, auch die IN-Queue ist immer leer.
Außerdem ist irritierenderweise GetCommMask immer leer. Zumindest ein EV_RXCHAR (A character was received and placed in the input buffer) sollte mal vorkommen, da ich ja Daten empfange. Ich habe auch mit SetCommMask alle Events aktiviert.Etwas Code:
HANDLE h = CreateFileA("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, //sharing 0, //security OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); assert(h != INVALID_HANDLE_VALUE); assert(SetupComm(h, 1024*1024, 16384)); DCB portInfo; //Device Control Block assert(GetCommState(h, &portInfo)); //set COM port info portInfo.ByteSize = 8; portInfo.Parity = NOPARITY; portInfo.StopBits = ONESTOPBIT; portInfo.fDtrControl = DTR_CONTROL_ENABLE; portInfo.XoffLim = 1024*1024; portInfo.XonLim = 0; portInfo.XonChar = 0x11; portInfo.BaudRate = CBR_256000; portInfo.ErrorChar = 0x0; portInfo.EofChar = 0x0; portInfo.EvtChar = 0x0; portInfo.fDsrSensitivity = false; portInfo.fTXContinueOnXoff = true; portInfo.fOutX = false; portInfo.fInX = false; portInfo.fErrorChar = false; portInfo.fNull = false; portInfo.fAbortOnError = false; assert(SetCommState(h, &portInfo)); COMMTIMEOUTS timeouts = {}; assert(GetCommTimeouts(h, &timeouts)); timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutConstant = 10; //habe auch 0 versucht timeouts.ReadTotalTimeoutMultiplier = 0; assert(SetCommTimeouts(h, &timeouts)); OVERLAPPED ov = {}; char buffer[1024*1024]; ReadFile(h, &buffer[0], sizeof buffer, 0, &ov); ... for(;;){ if (GetOverlappedResult(h, &ov, &transactionsize, 0)){ ReadFile(h, &buffer[0], sizeof buffer, 0, &ov); data += transactionsize; } } ...
Wenn jemand weiß wie es schneller geht bitte melden.