?
Also das ist tatsächlich kompliziert, was in Linux ein einfaches read(...) ist, ist nun ein riesges Konstrukt.
Ich habe also OVERLAPPED aktiviert.
serial_port[aPort] = CreateFile(ser_devices[aPort].devicename, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
Nun habe ich
ReadFile(serial_port[aPort], rx_message, BUFSIZE, &len, &ov))
aufgerufen. Die kehrt natürlich sofort zurück. Liefert ReadFile TRUE zurück, lagen Daten bereit die direkt ausgelesen wurden. Liegen keine Daten zurück, wird FALSE zurück geliefert. Im Normalfall sollte nun GetLastError() auf ERROR_IO_PENDING stehen. Er wartet also auf eingehende Daten.
Also warte ich nun auf eingehende Daten:
GetOverlappedResult(serial_port[aPort], &ov, &len, TRUE))
Ich habe hier das wait Flag auf TRUE gesetzt. Damit wartet er an der Stelle. Was okay ist da ich einen eigenen Thread fürs lesen habe.
Nun hatte ich das Problem, dass auch dann nicht zurück gekehrt ist, wenn er bereits einen Teil eingelesen hat, der Buffer aber noch nicht voll ist. Also weniger als BUFSIZE Daten empfangen wurden. Daher habe ich Timeouts gesetzt:
COMMTIMEOUTS tTimeout;
tTimeout.ReadIntervalTimeout = MAXWORD;
tTimeout.ReadTotalTimeoutMultiplier = 0;
tTimeout.ReadTotalTimeoutConstant = 500;
tTimeout.WriteTotalTimeoutMultiplier = 0;
tTimeout.WriteTotalTimeoutConstant = 0;
// config the timeout
if( !SetCommTimeouts(serial_port[aPort],&tTimeout) )
{
//error setting serial port state
fprintf(stderr, "Error: Setting serial port timeouts of serial device '%s'\n", ser_devices[aPort].devicename);
return INVALID_HANDLE_VALUE;
}
Jetzt hat er aber andauernd abgebrochen und erneut ReadFile aufgerufen. Daher habe ich noch ein Event definiert:
SetCommMask(serial_port[aPort], EV_RXCHAR);
WaitCommEvent(serial_port[aPort], &evt, &ov);
Leider geht durch Overlapped auch WaitComm sofort mit FALSE zurück wenn keine Daten anliegen mit getLastError auf ERROR_IO_PENDING. Daher habe ich noch ein
WaitForSingleObject(ov.hEvent,INFINITE);
aufgerufen. Das kehrt erst zurück wenn wirklich Daten anliegen.
Kommt mir ja alles sehr sehr sehr umständlich vor, aber zumindestens läuft das. Habt ihr noch Anmerkungen? Ansonsten hilft dieser Thread vielleicht mal jemanden.
Hier noch der gesamte Code:
DWORD len = 0;
DWORD evt;
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
OVERLAPPED ov = {0};
ov.hEvent = hEvent;
// Wait for incomming data on serial port
SetCommMask(serial_port[aPort], EV_RXCHAR);
if (!WaitCommEvent(serial_port[aPort], &evt, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
system_log (0, "serial_read", "Error: WaitCommEvent failed on serial-port (%d)", aPort);
receivedBytes = -1;
}
else
{
// Wait for EV_RXCHAR event
WaitForSingleObject(ov.hEvent,INFINITE);
}
}
if(!ReadFile(serial_port[aPort], rx_message, BUFSIZE, &len, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
system_log (0, "serial_read", "Error: Reading serial-port (%d)", aPort);
receivedBytes = -1;
}
else
{
// Wait for the operation to complete before continuing.
if (GetOverlappedResult(serial_port[aPort], &ov, &len, TRUE))
receivedBytes = (int) len;
else
receivedBytes = -1;
}
}
else
{
// Operation has completed immediately.
receivedBytes = (int) len;
}
Und ein Link der ganz hilfreich ist:
http://www.codeproject.com/Articles/2682/Serial-Communication-in-Windows
Danke an euch!