1 | ///////////////////////////////////////////////////////////////////////
|
2 | // SerComThread - Consolen-Application
|
3 | // Daten senden und empfangen mit Thread
|
4 | // Ein Thread liest Daten an RxD ein und sendet sie zurück
|
5 | ///////////////////////////////////////////////////////////////////////
|
6 | #include <windows.h>
|
7 | #include <stdio.h>
|
8 |
|
9 | #define PORTNAME "COM1"
|
10 | #define BAUDRATE 9600
|
11 | #define BYTESIZE 8
|
12 | #define PARITY NOPARITY
|
13 | #define STOPBITS ONESTOPBIT
|
14 |
|
15 | #define COM_BUFFER_SIZE 256 // Read- und Write-Buffer-Size
|
16 | #define QEVENT "QueueEvent"
|
17 | #define TIMELIMIT 150000 // ms
|
18 |
|
19 | // global struc contains parameter for threads
|
20 | typedef struct
|
21 | {
|
22 | volatile BOOL ThreadStoppen;
|
23 | volatile int iComPortNum;
|
24 | volatile DWORD dwMonitorThreadId;
|
25 | } PARAMS, *PPARAMS;
|
26 |
|
27 | HANDLE hCom = INVALID_HANDLE_VALUE;
|
28 | HANDLE hEvent;
|
29 | char COMMAND1[] = {(0x42), (0x49), (0x45), (0x42), (0x43)};
|
30 |
|
31 | // prototyping
|
32 | DWORD WINAPI ComThread (LPVOID lpParam);
|
33 |
|
34 |
|
35 | //--------------------------------------------------------------------
|
36 | // Erstellt einen Empfangs-Thread und schreibt Daten nach COMx
|
37 | //--------------------------------------------------------------------
|
38 | int main (void)
|
39 | {
|
40 | PARAMS p;
|
41 | DWORD dwComThreadId;
|
42 | HANDLE hComThread = NULL;
|
43 | DWORD dwState;
|
44 | DWORD iBytesWritten;
|
45 | BOOL bRet;
|
46 |
|
47 |
|
48 | printf ("\r\nCOM %s-Port read data on RxD for %d sec.",
|
49 | PORTNAME, TIMELIMIT / 1000);
|
50 | printf ("\r\nrunning .... \r\n");
|
51 |
|
52 | // "alten" Thread stoppen
|
53 | p.ThreadStoppen = TRUE;
|
54 | CloseHandle (hComThread); // "alten" Thread stoppen
|
55 | p.iComPortNum = (int)PORTNAME[3] - 0x30;
|
56 | // ComThread: Starten und Parameterstruct übergeben
|
57 | p.ThreadStoppen = FALSE;
|
58 | hComThread = CreateThread ( // Handle des Threads
|
59 | NULL, // no security attributes
|
60 | 0, // use default stack size
|
61 | ComThread, // thread function
|
62 | &p, // argument to thread function
|
63 | 0, // use default creation flags
|
64 | &dwComThreadId); // returns the thread identifier
|
65 |
|
66 | if (hComThread == NULL)
|
67 | printf ("\r\nCreateThread (ComThread) fehlgeschlagen");
|
68 |
|
69 | Sleep (1000);
|
70 |
|
71 | bRet = WriteFile (hCom, &COMMAND1, 5, &iBytesWritten, NULL); // Senden der Bytes
|
72 | if (bRet)
|
73 | { // Fehlerausgabe:
|
74 | LPVOID lpMsgBuf;
|
75 | FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
76 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
|
77 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
|
78 | MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: WriteFile", MB_OK | MB_ICONINFORMATION);
|
79 | LocalFree (lpMsgBuf);
|
80 | }
|
81 | else
|
82 | printf ("\r\n%d Bytes sent.", iBytesWritten);
|
83 |
|
84 | Sleep (TIMELIMIT); // der Thread und die Appl. leben nur TIMELIMIT sec.!
|
85 |
|
86 | printf ("\r\nReady\r\n");
|
87 | p.ThreadStoppen = TRUE;
|
88 |
|
89 | CloseHandle (hComThread); // ComThread beenden
|
90 |
|
91 | return 0;
|
92 | }
|
93 |
|
94 |
|
95 | //--------------------------------------------------------------------
|
96 | // Thread Funktion
|
97 | // Liest ununterbrochen die Daten an RxD ein
|
98 | //--------------------------------------------------------------------
|
99 | DWORD WINAPI ComThread (LPVOID lpParam)
|
100 | {
|
101 | long lTime;
|
102 | volatile PPARAMS pparams; // struct-Instanz
|
103 | pparams = (PPARAMS) lpParam; // Zuweisung zu lpParam
|
104 | int iPortNum = pparams->iComPortNum; // ...
|
105 | DWORD dwMonitorThreadId = pparams->dwMonitorThreadId; // ...
|
106 | char szPort[15];
|
107 | static OVERLAPPED o;
|
108 | // Maske für SetCommMask, die bestimmt, welche Ereignisse auftreten können
|
109 | DWORD dwEvtMaskIn = EV_CTS | EV_DSR | EV_BREAK | EV_RING | EV_RXCHAR |
|
110 | EV_RLSD | EV_ERR | EV_RXFLAG | EV_TXEMPTY;
|
111 | DWORD dwEvtMask = 0; // Maske, in die WaitCommEvent aktuelle Werte schreibt
|
112 | BOOL bRet;
|
113 | DCB dcb;
|
114 | COMMTIMEOUTS ct;
|
115 | unsigned char InString[COM_BUFFER_SIZE + 1];
|
116 | DWORD dwRead = 0;
|
117 | DWORD iBytesWritten;
|
118 |
|
119 |
|
120 | CloseHandle (hCom); // "alten" COM-Port schließen
|
121 |
|
122 | // Com Port öffnen
|
123 | wsprintf (szPort, "COM%d", iPortNum);
|
124 | hCom = CreateFile (szPort,
|
125 | GENERIC_READ | GENERIC_WRITE,
|
126 | 0, // exclusive access
|
127 | NULL, // no security attributes
|
128 | OPEN_EXISTING,
|
129 | FILE_FLAG_OVERLAPPED,
|
130 | NULL);
|
131 |
|
132 | if (hCom == INVALID_HANDLE_VALUE)
|
133 | {
|
134 | LPVOID lpMsgBuf;
|
135 | FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
136 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
137 | NULL, GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
138 | (LPTSTR) &lpMsgBuf, 0, NULL);
|
139 | MessageBox (NULL, (LPCTSTR)lpMsgBuf, TEXT("ComThread: error: CreateFile()"),
|
140 | MB_OK | MB_ICONINFORMATION);
|
141 | LocalFree (lpMsgBuf);
|
142 | pparams->ThreadStoppen = TRUE;
|
143 | }
|
144 | else
|
145 | {
|
146 | if (!SetCommMask (hCom, dwEvtMaskIn))
|
147 | MessageBox (NULL, "SetCommMask fehlgeschlagen", "COM Port:", MB_OK | MB_ICONSTOP);
|
148 |
|
149 | // Create an event object for use in WaitCommEvent.
|
150 | o.hEvent = CreateEvent (NULL, // no security attributes
|
151 | FALSE, // auto reset event
|
152 | FALSE, // not signaled
|
153 | NULL); // no name
|
154 | }
|
155 |
|
156 | dcb.DCBlength = sizeof(DCB); // Laenge des Blockes MUSS gesetzt sein!
|
157 | GetCommState (hCom, &dcb); // COM-Einstellungen holen und aendern
|
158 | dcb.BaudRate = BAUDRATE; // Baudrate
|
159 | dcb.ByteSize = BYTESIZE; // Datenbits
|
160 | dcb.Parity = PARITY; // Parität
|
161 | dcb.StopBits = STOPBITS; // Stopbits
|
162 | SetCommState (hCom, &dcb); // COM-Einstellungen speichern
|
163 |
|
164 | GetCommTimeouts (hCom, &ct);
|
165 | // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes
|
166 | ct.ReadIntervalTimeout = 1000 / BAUDRATE * (dcb.ByteSize +
|
167 | (dcb.Parity == PARITY ? 0 : 1) +
|
168 | (dcb.StopBits == STOPBITS ? 1 : 2)) * 2;
|
169 | ct.ReadTotalTimeoutMultiplier = 0; // [ms] wird mit Read-Buffer-Size multipliziert
|
170 | ct.ReadTotalTimeoutConstant = 50; // wird an ReadTotalTimeoutMultiplier angehängt
|
171 | ct.WriteTotalTimeoutMultiplier = 0;
|
172 | ct.WriteTotalTimeoutConstant = 0;
|
173 | SetCommTimeouts (hCom, &ct);
|
174 |
|
175 | // Zwischenspeicher des serial-Drivers einstellen (für read und write):
|
176 | SetupComm (hCom, COM_BUFFER_SIZE, COM_BUFFER_SIZE);
|
177 | printf ("\r\nComThread: %s geöffnet, warte auf Events ...", szPort);
|
178 |
|
179 | // Auf Events warten:
|
180 | while (!pparams->ThreadStoppen) // solange weitermachen bis TRUE
|
181 | {
|
182 | WaitCommEvent (hCom, &dwEvtMask, &o); // EventMask "scharf machen"
|
183 | // kommt der Event, ist auch die dwEvtMask geladen und es kann weitergehen
|
184 | if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
|
185 | {
|
186 | if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
|
187 | {
|
188 | bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL);
|
189 |
|
190 | if (!bRet)
|
191 | { // Fehlerausgabe:
|
192 | LPVOID lpMsgBuf;
|
193 | FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
194 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
|
195 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
196 | (LPTSTR) &lpMsgBuf, 0, NULL);
|
197 | MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: ReadFile",
|
198 | MB_OK | MB_ICONINFORMATION);
|
199 | LocalFree (lpMsgBuf);
|
200 | }
|
201 | else
|
202 | { // Ausgabe (oder Verarbeitung) der empfangenen Bytes:
|
203 | InString[dwRead] = '\0'; // in "zero-ended"-String verwandeln
|
204 | printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead, InString);
|
205 | WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL); // Senden der Bytes
|
206 | }
|
207 | }
|
208 |
|
209 | if (dwEvtMask & EV_ERR)
|
210 | {
|
211 | MessageBox (NULL, "Error empfangen", "Error: ReadFile", MB_OK);
|
212 | break; // Schleifen-Abbruch
|
213 | }
|
214 | } // end of: if (WAIT_OBJECT_0 == ...
|
215 | } // end of: while (...
|
216 |
|
217 | CloseHandle (o.hEvent);
|
218 | CloseHandle (hCom); // COM-Port schließen
|
219 |
|
220 | printf ("\r\nComThread: %s geschlossen", szPort);
|
221 |
|
222 | return (0);
|
223 | }
|