ReadFile mit Timeout
-
Hi,
Ich suche heute schon den ganzen Tag nach einer Lösung, wie ich bei einer Seriellen Schnittstelle bei einem "ReadFile(...)" ein Timeout setzen kann.Unter Linux geht das ganz einfach mit "select", doch Windows behandelt die Comm Schnittstelle nicht als gewöhnlichen Filedescriptor.
Ich habe mir schon gedacht mit COMMTIMEOUTS Zeiten zu setzen, aber das Funktioniert nicht. So wie ich es Verstehe, wird dort erst ein timeout aktiv, wenn mindestens ein char schon empfangen ist!
Ich moechte aber so etwas ähnliches haben wie:
//Schaue, ob etwas passiert (in linux "select(hcom, &fdset, NULL, NULL, &timeval) if /*wenn etwas kommt*/ { ReadFile(hcom, &buff, strlen(buff), &X, NULL); }
Oder vielleicht geht es ja doch mit den COMMTIMEOUTS, nur habe ich da etwas nicht so richtig kapiert.
Bin jedenfalls um jede Hilfe sehr dankbar
Grüße
lberger
-
Mit dem unteren kanst du Abfragen wievile Bytes im RS232 Puffer sind.
Du wartest einfach solange bis genug Bytes im Puffer sind oder der
Timeout abläuft.Du könntes auch mit WaitCommEvent(?,EV_RXCHAR,?) und einem eigene Thread arbeiten.
//***************************************************************************** //* //* ComGetReadCount //* //***************************************************************************** // Ergibt die Anzahl der Bytes die im Lesepuffer der Schnittstelle sind // hHandle : Ist das Hande für das Com-Port (siehe ComOpen) // Ergibt die Anzahl der Bytes im Buffer int ComGetReadCount(HANDLE hHandle) { COMSTAT sComStat; DWORD dwErrorFlags; dwErrorFlags=0; if(!ClearCommError(hHandle,&dwErrorFlags, &sComStat))return 0; return sComStat.cbInQue; }
Meine Homepage
[url]
http://members.inode.at/anton.zechner/az/index.html
[/url]
-
COMMTIMEOUTS myTimeouts; myTimeouts.ReadIntervalTimeout = 0xFFFFFFFF; myTimeouts.ReadTotalTimeoutMultiplier = 0xFFFFFFFF; myTimeouts.ReadTotalTimeoutConstant = getTimeoutRead(); //z.B. 1500 für 1.5s myTimeouts.WriteTotalTimeoutMultiplier = 0xFFFFFFFF; myTimeouts.WriteTotalTimeoutConstant = getTimeoutWrite(); SetCommTimeouts(m_ComPortHnd, &myTimeouts
Code setzt also eine Timeout für z.B. 1.5s.
ReadFile reagiert nun so:
FallA: Wenn keine Daten innerhalb 1.5s ankommen, wird true zurückgegeben, aber in der Variable für die Anzahl empfangenen Daten steht dann 0. (4. Argument von ReadFile).FallB: Wenn Daten ankommen, dass wird true zurückgegeben und in der geleseBytes-Variable steht 1. D.h. wird ein Byte empfangen, wird ReadFile sofort beendet! In diesem Fall müsste man also nochmals ReadFile auslesen un die restlichen Bytes auslesen.
Achtung: ReadFile sollte eignetlich immer true zurückgeben, sonst stimmt etwas mit dem Handle oder dem ComPort nicht!!
-
Ist nix mehr im Empfangsbuffer bleibt ReadFile bei mir stehen.
if (!ReadFile ((HANDLE) fd, data, maxlen, &ret, NULL) || ret == 0) break;
Gibt es eine Loesung, das ReadFile trotzdem durchlaufen wird?
mfg Olli.
-
testuser schrieb:
Ist nix mehr im Empfangsbuffer bleibt ReadFile bei mir stehen.
if (!ReadFile ((HANDLE) fd, data, maxlen, &ret, NULL) || ret == 0) break;
Gibt es eine Loesung, das ReadFile trotzdem durchlaufen wird?
mfg Olli.
ReadFile wird in der Regel IMMER durchlaufen, ausser es ist irgendwie ein Systemfehler aufgetreten (z.B. kein gültiges HANDLE usw.)
lies nochmals die MSDN dazu.
-
ReadFile wird in der Regel IMMER durchlaufen,
schreibe ich mit WriteFile "WIEDER", wird ReadFile "WIEDER" durchlaufen,
also ist mit den Handle alles in Ordnung.mfg Olli.
-
Hier ist mal ein Beispiel Code, so wie er aussehen koennte.
Nach den 10. Schreiben bleibt der bei ReadFile haengen, solange bis
man wieder mit WriteFile schreibt. ReadFile soll aber weiterhin pruefen
ob Zeichen anliegen.#include <stdio.h> #include <windows.h> HANDLE watch_dog[2]; char data[1] = "\0"; int maxlen = 1; int pipe(HANDLE Handle[2]) { SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (! CreatePipe(&Handle[0], &Handle[1], &saAttr, 0)) return(EOF); return(TRUE); } int WritePipe(void) { DWORD ret = 0; static int task = 0; if (task < 10) { if (! WriteFile(watch_dog[1], data, maxlen, &ret, NULL) || ret == 0) return(FALSE); ++task; } return(ret); } int ReadPipe(void) { DWORD ret = 0; if (! ReadFile(watch_dog[0], data, maxlen, &ret, NULL) || ret == 0) return(FALSE); return(ret); } DWORD main(void) { DWORD ret = 0; if (pipe(watch_dog) < 0) { printf("Pipe konnte nicht erstellt werden\n"); return(FALSE); } while(1) { Sleep(1000); printf("Schreibe Wert: %d\n", ret = WritePipe()); ret = 0; printf("Lese Wert: %d\n", ret = ReadPipe()); } return(FALSE); }
Der Code soll spaeter fuer ein watchdog dienen.
mfg Olli.
-
testuser schrieb:
....ReadFile soll aber weiterhin pruefen
ob Zeichen anliegen.Wenn ReadFile nur prüfen muss, dann hilft dir vielleicht dieser Code weiter:
// gibt die anzahl bytes zürück, die im internen buffer sind. int getBufferBytes(){ COMSTAT sComStat; DWORD dwErrorFlags = 0; ClearCommError(m_ComPortHnd, &dwErrorFlags, &sComStat); return sComStat.cbInQue; } if(getBufferBytes()){ // jetzt lesen.. ReadFile(...); }
-
COMSTAT sComStat;
Benutze PIPE keine COM-Schnittstellen, trotzdem danke fuer den Tipp.