Pollen:
Am Anfang die Timeouts einstellen, z.B.: so:
1 | COMMTIMEOUTS ct;
|
2 | GetCommTimeouts (hCom, &ct);
|
3 | // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes
|
4 | ct.ReadIntervalTimeout = 1000 / BAUDRATE * (dcb.ByteSize +
|
5 | (dcb.Parity == NOPARITY ? 0 : 1) +
|
6 | (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2;
|
7 | ct.ReadTotalTimeoutMultiplier = 0; // [ms] wird mit Read-Buffer-Size multipliziert
|
8 | ct.ReadTotalTimeoutConstant = 50; // wird an ReadTotalTimeoutMultiplier angehängt
|
9 | ct.WriteTotalTimeoutMultiplier = 0;
|
10 | ct.WriteTotalTimeoutConstant = 0;
|
11 | SetCommTimeouts (hCom, &ct);
|
Ja, und dann in einer Schleife immer ReadFile aufrufen.
Das ist aber die schlechteste Variante, besser ist ein eigener Thread
(CreateThread), in dem man auf ein Read-Ereignis am Port wartet und dann
erst ReadFile aufruft. Weil ja dann auch ein Byte angekommen ist.
Zuerst wird eine Overlapped-Struct erstellt und mit einem Event
verknüpft.
1 | OVERLAPPED o;
|
2 | memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen
|
3 | o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Event setzten
|
dann eine Maske mit den Events, af die man warten möchte und eine, die
die eintreffenden Events aufnimmt, erstellt:
1 | DWORD dwSetMask = EV_RXCHAR | EV_ERR;
|
2 | DWORD dwEvtMask;
|
und dann wird in einer Endlosschleife auf die Events gewartet:
1 | do // in Endlos-Schleife auf Empfangssignale warten:
|
2 | {
|
3 | WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalen verknüpfen
|
4 |
|
5 | if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
|
6 | {
|
7 | if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
|
8 | {
|
9 | bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL);
|
10 | ...
|
11 | if (dwEvtMask & EV_ERR) // Zeichen an RxD empfangen:
|
12 | {
|
13 | ...
|
Naja, das Übliche mit DCB, Fehlerauswerten, Sende- und Empfangspuffer
setzen, Schließen von Thread und COm und Event usw. nicht vergessen.
Schreiben kann man aus jedem Thread heraus, sollte nicht im
Empfangsthread sein und wenn möglich, in einem eigenen Thread ablaufen,
wel man so ganz bequem feststellen kann, ob die Zeichen auch wirklich
raus sind (an den Treiber) und nicht der Puffer noch voll ist und man
Zeichen überschreibt.
Für das Öffnen, Schließen und Setzen der seriellen Ports und der
einzelnen Pins gibts es massig C/C++ -Code-Schnipsel und -Klassen. Aber
keine mir bekannte behandelt das Empfangen in einem Thread. Es wird
immer nur eine schön eingepackte ReadFile-Routine vorgestellt, aber wo
soll man die aufrufen?
Blackbird