SerialPort.h SerialPort.cpp
SerialPort.h

1 #ifndef __SERIALPORT_H__
2 #define __SERIALPORT_H__
3
4 #define WM_COMM_BREAK_DETECTED WM_USER+1 // A break was detected on input.
5 #define WM_COMM_CTS_DETECTED WM_USER+2 // The CTS (clear-to-send) signal changed state.
6 #define WM_COMM_DSR_DETECTED WM_USER+3 // The DSR (data-set-ready) signal changed state.
7 #define WM_COMM_ERR_DETECTED WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
8 #define WM_COMM_RING_DETECTED WM_USER+5 // A ring indicator was detected.
9 #define WM_COMM_RLSD_DETECTED WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state.
10 #define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer.
11 #define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character was received and placed in the input buffer.
12 #define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in the output buffer was sent.
13
14 class CSerialPort
15 {
16 public:
17 // contruction and destruction
18 CSerialPort(); // 构造函数
19 virtual ~CSerialPort(); //析构函数虚拟化了,是为了不同端口对象被消灭的时候,可以进行不同的收尾工作
20
21 // port initialisation
22 BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200,
23 char parity = 'N', UINT databits = 8, UINT stopsbits = 1,
24 DWORD dwCommEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512,
25
26 DWORD ReadIntervalTimeout = 1000,
27 DWORD ReadTotalTimeoutMultiplier = 1000,
28 DWORD ReadTotalTimeoutConstant = 1000,
29 DWORD WriteTotalTimeoutMultiplier = 1000,
30 DWORD WriteTotalTimeoutConstant = 1000);
31
32 // start/stop comm watching
33 BOOL StartMonitoring();
34 BOOL RestartMonitoring();
35 BOOL StopMonitoring();
36
37 DWORD GetWriteBufferSize();
38 DWORD GetCommEvents();
39 DCB GetDCB();
40
41 void WriteToPort(char* string);
42 void WriteToPort(char* string,int n); // add by mrlong 2007-12-25
43 void WriteToPort(LPCTSTR string); // add by mrlong 2007-12-25
44 void WriteToPort(BYTE* Buffer, int n);// add by mrlong
45 void ClosePort(); // add by mrlong 2007-12-2
46
47 void SendData(LPCTSTR lpszData, const int nLength); //串口发送函数 by mrlong 2008-2-15
48 BOOL RecvData(LPTSTR lpszData, const int nSize); //串口接收函数 by mrlong 2008-2-15
49
50 protected:
51 // protected memberfunctions
52 void ProcessErrorMessage(char* ErrorText);
53 static UINT CommThread(LPVOID pParam);
54 static void ReceiveChar(CSerialPort* port, COMSTAT comstat);
55 static void WriteChar(CSerialPort* port);
56
57 // thread
58 CWinThread* m_Thread;
59
60 // synchronisation objects
61 CRITICAL_SECTION m_csCommunicationSync;
62 BOOL m_bThreadAlive;
63
64 // handles
65 HANDLE m_hShutdownEvent; //stop发生的事件
66 HANDLE m_hComm; // read
67 HANDLE m_hWriteEvent; // write
68
69 // Event array.
70 // One element is used for each event. There are two event handles for each port.
71 // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).
72 // There is a general shutdown when the port is closed.
73 HANDLE m_hEventArray[3];
74
75 // structures
76 OVERLAPPED m_ov;
77 COMMTIMEOUTS m_CommTimeouts;
78 DCB m_dcb;
79
80 // owner window
81 CWnd* m_pOwner;
82
83 // misc
84 UINT m_nPortNr; //?????
85 char* m_szWriteBuffer;
86 DWORD m_dwCommEvents;
87 DWORD m_nWriteBufferSize;
88
89 int m_nWriteSize; //add by mrlong 2007-12-25
90 };
91
92 #endif __SERIALPORT_H__

SerialPort.cpp

1 #include "stdafx.h"
2 #include "SerialPort.h"
3
4 #include <assert.h>
5
6 //
7 // Constructor
8 //
9 CSerialPort::CSerialPort()
10 {
11 m_hComm = NULL;
12
13 // initialize overlapped structure members to zero
14 m_ov.Offset = 0;
15 m_ov.OffsetHigh = 0;
16
17 // create events
18 m_ov.hEvent = NULL;
19 m_hWriteEvent = NULL;
20 m_hShutdownEvent = NULL;
21
22 m_szWriteBuffer = NULL;
23
24 m_bThreadAlive = FALSE;
25 m_nWriteSize = 1;
26 }
27
28 //
29 // Delete dynamic memory
30 //
31 CSerialPort::~CSerialPort()
32 {
33 do
34 {
35 SetEvent(m_hShutdownEvent);
36 } while (m_bThreadAlive);
37
38 if (m_hComm != NULL)
39 {
40 CloseHandle(m_hComm);
41 m_hComm = NULL;
42 }
43 // Close Handles
44 if(m_hShutdownEvent!=NULL)
45 CloseHandle( m_hShutdownEvent);
46 if(m_ov.hEvent!=NULL)
47 CloseHandle( m_ov.hEvent );
48 if(m_hWriteEvent!=NULL)
49 CloseHandle( m_hWriteEvent );
50
51 TRACE("Thread ended\n");
52
53 delete [] m_szWriteBuffer;
54 }
55
56 //
57 // Initialize the port. This can be port 1 to 4.
58 //
59 //
60 //parity:
61 // n=none
62 // e=even
63 // o=odd
64 // m=mark
65 // s=space
66 //data:
67 // 5,6,7,8
68 //stop:
69 // 1,1.5,2
70 //
71 BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
72 UINT portnr,
73 UINT baud, // baudrate
74 char parity, // parity
75 UINT databits, // databits
76 UINT stopbits, // stopbits
77 DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
78 UINT writebuffersize,// size to the writebuffer
79
80 DWORD ReadIntervalTimeout,
81 DWORD ReadTotalTimeoutMultiplier,
82 DWORD ReadTotalTimeoutConstant,
83 DWORD WriteTotalTimeoutMultiplier,
84 DWORD WriteTotalTimeoutConstant )
85
86 {
87 //assert(portnr > 0 && portnr < 5);//Del by wl 20120612
88 assert(pPortOwner != NULL);
89
90 // if the thread is alive: Kill
91 if (m_bThreadAlive)
92 {
93 do
94 {
95 SetEvent(m_hShutdownEvent);
96 } while (m_bThreadAlive);
97 TRACE("Thread ended\n");
98 }
99
100 // create events
101 if (m_ov.hEvent != NULL)
102 ResetEvent(m_ov.hEvent);
103 else
104 m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
105
106 if (m_hWriteEvent != NULL)
107 ResetEvent(m_hWriteEvent);
108 else
109 m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
110
111 if (m_hShutdownEvent != NULL)
112 ResetEvent(m_hShutdownEvent);
113 else
114 m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
115
116 // initialize the event objects
117 m_hEventArray[0] = m_hShutdownEvent; // highest priority
118 m_hEventArray[1] = m_ov.hEvent;
119 m_hEventArray[2] = m_hWriteEvent;
120
121 // initialize critical section
122 InitializeCriticalSection(&m_csCommunicationSync);
123
124 // set buffersize for writing and save the owner
125 m_pOwner = pPortOwner;
126
127 if (m_szWriteBuffer != NULL)
128 delete [] m_szWriteBuffer;
129 m_szWriteBuffer = new char[writebuffersize];
130
131 m_nPortNr = portnr;
132
133 m_nWriteBufferSize = writebuffersize;
134 m_dwCommEvents = dwCommEvents;
135
136 BOOL bResult = FALSE;
137 char *szPort = new char[50];
138 char *szBaud = new char[50];
139
140 // now it critical!
141 EnterCriticalSection(&m_csCommunicationSync);
142
143 // if the port is already opened: close it
144 if (m_hComm != NULL)
145 {
146 CloseHandle(m_hComm);
147 m_hComm = NULL;
148 }
149
150 // prepare port strings
151 sprintf(szPort, "COM%d", portnr);
152 // stop is index 0 = 1 1=1.5 2=2
153 int mystop;
154 int myparity;
155 switch(stopbits)
156 {
157 case 0:
158 mystop = ONESTOPBIT;
159 break;
160 case 1:
161 mystop = ONE5STOPBITS;
162 break;
163 case 2:
164 mystop = TWOSTOPBITS;
165 break;
166 }
167 myparity = 0;
168 switch(parity)
169 {
170 case 'N':
171 myparity = 0;
172 break;
173 case 'E':
174 myparity = 1;
175 break;
176 case 'O':
177 myparity = 2;
178 break;
179 case 'M':
180 myparity = 3;
181 break;
182 case 'S':
183 myparity = 4;
184 break;
185 }
186 sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, mystop);
187
188 // get a handle to the port
189 m_hComm = CreateFile(szPort, // communication port string (COMX)
190 GENERIC_READ | GENERIC_WRITE, // read/write types
191 0, // comm devices must be opened with exclusive access
192 NULL, // no security attributes
193 OPEN_EXISTING, // comm devices must use OPEN_EXISTING
194 FILE_FLAG_OVERLAPPED, // Async I/O
195 0); // template must be 0 for comm devices
196
197 if (m_hComm == INVALID_HANDLE_VALUE)
198 {
199 // port not found
200 delete [] szPort;
201 delete [] szBaud;
202
203 return FALSE;
204 }
205
206 // set the timeout values
207 m_CommTimeouts.ReadIntervalTimeout = ReadIntervalTimeout * 1000;
208 m_CommTimeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier * 1000;
209 m_CommTimeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant * 1000;
210 m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier * 1000;
211 m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant * 1000;
212
213 // configure
214 if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
215 {
216 if (SetCommMask(m_hComm, dwCommEvents))
217 {
218 if (GetCommState(m_hComm, &m_dcb))
219 {
220 m_dcb.EvtChar = 'q';
221 m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
222 m_dcb.BaudRate = baud; // add by mrlong
223 m_dcb.Parity = myparity;
224 m_dcb.ByteSize = databits;
225 m_dcb.StopBits = mystop;
226
227 if (BuildCommDCB(szBaud, &m_dcb))
228 {
229 if (SetCommState(m_hComm, &m_dcb))
230 ; // normal operation... continue
231 else
232 ProcessErrorMessage("SetCommState()");
233 }
234 else
235 ProcessErrorMessage("BuildCommDCB()");
236 }
237 else
238 ProcessErrorMessage("GetCommState()");
239 }
240 else
241 ProcessErrorMessage("SetCommMask()");
242 }
243 else
244 ProcessErrorMessage("SetCommTimeouts()");
245
246 delete [] szPort;
247 delete [] szBaud;
248
249 // flush the port
250 PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
251
252 // release critical section
253 LeaveCriticalSection(&m_csCommunicationSync);
254
255 TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);
256
257 return TRUE;
258 }
259
260 //
261 // The CommThread Function.
262 //
263 UINT CSerialPort::CommThread(LPVOID pParam)
264 {
265 // Cast the void pointer passed to the thread back to
266 // a pointer of CSerialPort class
267 CSerialPort *port = (CSerialPort*)pParam;
268
269 // Set the status variable in the dialog class to
270 // TRUE to indicate the thread is running.
271 port->m_bThreadAlive = TRUE;
272
273 // Misc. variables
274 DWORD BytesTransfered = 0;
275 DWORD Event = 0;
276 DWORD CommEvent = 0;
277 DWORD dwError = 0;
278 COMSTAT comstat;
279 BOOL bResult = TRUE;
280 // Clear comm buffers at startup
281 if (port->m_hComm) // check if the port is opened
282 PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
283
284 // begin forever loop. This loop will run as long as the thread is alive.
285 for (;;)
286 {
287
288 // Make a call to WaitCommEvent(). This call will return immediatly
289 // because our port was created as an async port (FILE_FLAG_OVERLAPPED
290 // and an m_OverlappedStructerlapped structure specified). This call will cause the
291 // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to
292 // be placed in a non-signeled state if there are no bytes available to be read,
293 // or to a signeled state if there are bytes available. If this event handle
294 // is set to the non-signeled state, it will be set to signeled when a
295 // character arrives at the port.
296
297 // we do this for each port!
298
299 bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
300
301 if (!bResult)
302 {
303 // If WaitCommEvent() returns FALSE, process the last error to determin
304 // the reason..
305 switch (dwError = GetLastError())
306 {
307 case ERROR_IO_PENDING:
308 {
309 // This is a normal return value if there are no bytes
310 // to read at the port.
311 // Do nothing and continue
312 break;
313 }
314 case 87:
315 {
316 // Under Windows NT, this value is returned for some reason.
317 // I have not investigated why, but it is also a valid reply
318 // Also do nothing and continue.
319 break;
320 }
321 default:
322 {
323 // All other error codes indicate a serious error has
324 // occured. Process this error.
325 port->ProcessErrorMessage("WaitCommEvent()");
326 break;
327 }
328 }
329 }
330 else
331 {
332 // If WaitCommEvent() returns TRUE, check to be sure there are
333 // actually bytes in the buffer to read.
334 //
335 // If you are reading more than one byte at a time from the buffer
336 // (which this program does not do) you will have the situation occur
337 // where the first byte to arrive will cause the WaitForMultipleObjects()
338 // function to stop waiting. The WaitForMultipleObjects() function
339 // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
340 // as it returns.
341 //
342 // If in the time between the reset of this event and the call to
343 // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
344 // to the signeled state. When the call to ReadFile() occurs, it will
345 // read all of the bytes from the buffer, and the program will
346 // loop back around to WaitCommEvent().
347 //
348 // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
349 // but there are no bytes available to read. If you proceed and call
350 // ReadFile(), it will return immediatly due to the async port setup, but
351 // GetOverlappedResults() will not return until the next character arrives.
352 //
353 // It is not desirable for the GetOverlappedResults() function to be in
354 // this state. The thread shutdown event (event 0) and the WriteFile()
355 // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
356 //
357 // The solution to this is to check the buffer with a call to ClearCommError().
358 // This call will reset the event handle, and if there are no bytes to read
359 // we can loop back through WaitCommEvent() again, then proceed.
360 // If there are really bytes to read, do nothing and proceed.
361
362 bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
363
364 if (comstat.cbInQue == 0)
365 continue;
366 } // end if bResult
367
368 // Main wait function. This function will normally block the thread
369 // until one of nine events occur that require action.
370 Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
371
372 switch (Event)
373 {
374 case 0:
375 {
376 // Shutdown event. This is event zero so it will be
377 // the higest priority and be serviced first.
378
379 port->m_bThreadAlive = FALSE;
380
381 // Kill this thread. break is not needed, but makes me feel better.
382 AfxEndThread(100);
383 break;
384 }
385 case 1: // read event
386 {
387 GetCommMask(port->m_hComm, &CommEvent);
388 memset(&comstat, 0, sizeof(COMSTAT));
389 if (CommEvent & EV_RXCHAR) //接收到字符,并置于输入缓冲区中
390 ReceiveChar(port, comstat);
391
392 if (CommEvent & EV_CTS) //CTS信号状态发生变化
393 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
394 if (CommEvent & EV_RXFLAG) //接收到事件字符,并置于输入缓冲区中
395 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
396 if (CommEvent & EV_BREAK) //输入中发生中断
397 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
398 if (CommEvent & EV_ERR) //发生线路状态错误,线路状态错误包括CE_FRAME,CE_OVERRUN和CE_RXPARITY
399 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
400 if (CommEvent & EV_RING) //检测到振铃指示
401 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
402
403 break;
404 }
405 case 2: // write event
406 {
407 // Write character event from port
408 WriteChar(port);
409 break;
410 }
411
412 } // end switch
413
414 } // close forever loop
415
416 return 0;
417 }
418 //
419 // start comm watching
420 //
421 BOOL CSerialPort::StartMonitoring()
422 {
423 if (!(m_Thread = AfxBeginThread(CommThread, this)))
424 return FALSE;
425 TRACE("Thread started\n");
426 return TRUE;
427 }
428 //
429 // Restart the comm thread
430 //
431 BOOL CSerialPort::RestartMonitoring()
432 {
433 TRACE("Thread resumed\n");
434 m_Thread->ResumeThread();
435 return TRUE;
436 }
437
438
439 //
440 // Suspend the comm thread
441 //
442 BOOL CSerialPort::StopMonitoring()
443 {
444 TRACE("Thread suspended\n");
445 m_Thread->SuspendThread();
446 return TRUE;
447 }
448
449
450 //
451 // If there is a error, give the right message
452 //
453 void CSerialPort::ProcessErrorMessage(char* ErrorText)
454 {
455 char *Temp = new char[200];
456
457 LPVOID lpMsgBuf;
458
459 FormatMessage(
460 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
461 NULL,
462 GetLastError(),
463 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
464 (LPTSTR) &lpMsgBuf,
465 0,
466 NULL
467 );
468
469 sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);
470 MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
471
472 LocalFree(lpMsgBuf);
473 delete[] Temp;
474 }
475
476 //
477 // Write a character.
478 //
479 void CSerialPort::WriteChar(CSerialPort* port)
480 {
481 BOOL bWrite = TRUE;
482 BOOL bResult = TRUE;
483
484 DWORD BytesSent = 0;
485 DWORD SendLen = port->m_nWriteSize;
486 ResetEvent(port->m_hWriteEvent);
487
488
489 // Gain ownership of the critical section
490 EnterCriticalSection(&port->m_csCommunicationSync);
491
492 if (bWrite)
493 {
494 // Initailize variables
495 port->m_ov.Offset = 0;
496 port->m_ov.OffsetHigh = 0;
497
498 // Clear buffer
499 PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
500
501 bResult = WriteFile(port->m_hComm, // Handle to COMM Port
502 port->m_szWriteBuffer, // Pointer to message buffer in calling finction
503 SendLen, // add by mrlong
504 //strlen((char*)port->m_szWriteBuffer), // Length of message to send
505 &BytesSent, // Where to store the number of bytes sent
506 &port->m_ov); // Overlapped structure
507
508 // deal with any error codes
509 if (!bResult)
510 {
511 DWORD dwError = GetLastError();
512 switch (dwError)
513 {
514 case ERROR_IO_PENDING:
515 {
516 // continue to GetOverlappedResults()
517 BytesSent = 0;
518 bWrite = FALSE;
519 break;
520 }
521 default:
522 {
523 // all other error codes
524 port->ProcessErrorMessage("WriteFile()");
525 }
526 }
527 }
528 else
529 {
530 LeaveCriticalSection(&port->m_csCommunicationSync);
531 }
532 } // end if(bWrite)
533
534 if (!bWrite)
535 {
536 bWrite = TRUE;
537
538 bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
539 &port->m_ov, // Overlapped structure
540 &BytesSent, // Stores number of bytes sent
541 TRUE); // Wait flag
542
543 LeaveCriticalSection(&port->m_csCommunicationSync);
544
545 // deal with the error code
546 if (!bResult)
547 {
548 port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
549 }
550 } // end if (!bWrite)
551
552 // Verify that the data size send equals what we tried to send
553 if (BytesSent != SendLen /*strlen((char*)port->m_szWriteBuffer)*/) // add by
554 {
555 TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));
556 }
557 }
558
559 //
560 // Character received. Inform the owner
561 //
562 void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
563 {
564 BOOL bRead = TRUE;
565 BOOL bResult = TRUE;
566 DWORD dwError = 0;
567 DWORD BytesRead = 0;
568 unsigned char RXBuff;
569
570 for (;;)
571 {
572 //add by liquanhai 防止死锁
573 if(WaitForSingleObject(port->m_hShutdownEvent,0)==WAIT_OBJECT_0)
574 return;
575
576 // Gain ownership of the comm port critical section.
577 // This process guarantees no other part of this program
578 // is using the port object.
579
580 EnterCriticalSection(&port->m_csCommunicationSync);
581
582 // ClearCommError() will update the COMSTAT structure and
583 // clear any other errors.
584
585 bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
586
587 LeaveCriticalSection(&port->m_csCommunicationSync);
588
589 if (comstat.cbInQue == 0)
590 {
591 // break out when all bytes have been read
592 break;
593 }
594
595 EnterCriticalSection(&port->m_csCommunicationSync);
596
597 if (bRead)
598 {
599 bResult = ReadFile(port->m_hComm, // Handle to COMM port
600 &RXBuff, // RX Buffer Pointer
601 1, // Read one byte
602 &BytesRead, // Stores number of bytes read
603 &port->m_ov); // pointer to the m_ov structure
604 // deal with the error code
605 if (!bResult)
606 {
607 switch (dwError = GetLastError())
608 {
609 case ERROR_IO_PENDING:
610 {
611 // asynchronous i/o is still in progress
612 // Proceed on to GetOverlappedResults();
613 bRead = FALSE;
614 break;
615 }
616 default:
617 {
618 // Another error has occured. Process this error.
619 port->ProcessErrorMessage("ReadFile()");
620 break;
621 }
622 }
623 }
624 else
625 {
626 // ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
627 bRead = TRUE;
628 }
629 } // close if (bRead)
630
631 if (!bRead)
632 {
633 bRead = TRUE;
634 bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
635 &port->m_ov, // Overlapped structure
636 &BytesRead, // Stores number of bytes read
637 TRUE); // Wait flag
638
639 // deal with the error code
640 if (!bResult)
641 {
642 port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
643 }
644 } // close if (!bRead)
645
646 LeaveCriticalSection(&port->m_csCommunicationSync);
647
648 // notify parent that a byte was received
649 ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
650 } // end forever loop
651
652 }
653
654 //
655 // Write a string to the port
656 //
657 void CSerialPort::WriteToPort(char* string)
658 {
659 assert(m_hComm != 0);
660
661 memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
662 strcpy(m_szWriteBuffer, string);
663 m_nWriteSize=strlen(string); // add by mrlong
664 // set event for write
665 SetEvent(m_hWriteEvent);
666 }
667
668 //
669 // Return the device control block
670 //
671 DCB CSerialPort::GetDCB()
672 {
673 return m_dcb;
674 }
675
676 //
677 // Return the communication event masks
678 //
679 DWORD CSerialPort::GetCommEvents()
680 {
681 return m_dwCommEvents;
682 }
683
684 //
685 // Return the output buffer size
686 //
687 DWORD CSerialPort::GetWriteBufferSize()
688 {
689 return m_nWriteBufferSize;
690 }
691
692 void CSerialPort::ClosePort()
693 {
694 MSG message;
695 do
696 {
697 SetEvent(m_hShutdownEvent);
698 if(::PeekMessage(&message,m_pOwner->m_hWnd,0,0,PM_REMOVE))
699 {
700 ::TranslateMessage(&message);
701 ::DispatchMessage(&message);
702 }
703
704 } while (m_bThreadAlive);
705
706 // if the port is still opened: close it
707 if (m_hComm != NULL)
708 {
709 CloseHandle(m_hComm);
710 m_hComm = NULL;
711 }
712
713 // Close Handles
714 if(m_hShutdownEvent!=NULL)
715 ResetEvent(m_hShutdownEvent);
716 if(m_ov.hEvent!=NULL)
717 ResetEvent(m_ov.hEvent);
718 if(m_hWriteEvent!=NULL)
719 ResetEvent(m_hWriteEvent);
720
721 //delete [] m_szWriteBuffer;
722
723 }
724
725 void CSerialPort::WriteToPort(char* string,int n)
726 {
727 assert(m_hComm != 0);
728 memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
729 memcpy(m_szWriteBuffer, string, n);
730 m_nWriteSize = n;
731
732 // set event for write
733 SetEvent(m_hWriteEvent);
734 }
735
736 void CSerialPort::WriteToPort(LPCTSTR string)
737 {
738 assert(m_hComm != 0);
739 memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
740 strcpy(m_szWriteBuffer, string);
741 m_nWriteSize=strlen(string);
742 // set event for write
743 SetEvent(m_hWriteEvent);
744 }
745
746 void CSerialPort::WriteToPort(BYTE* Buffer, int n)
747 {
748 assert(m_hComm != 0);
749 memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));//清零
750 int i;
751 for(i=0; i<n; i++)
752 {
753 m_szWriteBuffer[i] = Buffer[i];//读缓存
754 }
755 m_nWriteSize=n;
756
757 // set event for write
758 SetEvent(m_hWriteEvent);//SetEvent/ResetEvent分别将EVENT置为这两种状态分别是发信号与不发信号
759 }
760
761
762 void CSerialPort::SendData(LPCTSTR lpszData, const int nLength)
763 {
764 assert(m_hComm != 0);
765 memset(m_szWriteBuffer, 0, nLength);
766 strcpy(m_szWriteBuffer, lpszData);
767 m_nWriteSize=nLength;
768 // set event for write
769 SetEvent(m_hWriteEvent);
770 }
771
772 BOOL CSerialPort::RecvData(LPTSTR lpszData, const int nSize)
773 {
774 //
775 //接收数据
776 //
777 assert(m_hComm!=0);
778 memset(lpszData,0,nSize);
779 DWORD mylen = 0;
780 DWORD mylen2 = 0;
781 while (mylen<nSize) {
782 if(!ReadFile(m_hComm,lpszData,nSize,&mylen2,NULL))
783 return FALSE;
784 mylen += mylen2;
785
786
787 }
788
789 return TRUE;
790 }

SerialPort.h SerialPort.cpp的更多相关文章
- template 不能分别在.h和.cpp中定义模板
先上代码: #ifndef SEQLIST_H #define SEQLIST_H #include <iostream> ; template <typename type> ...
- c++ *.h和*.cpp在编译中的作用
首先,我们可以将所有东西都放在一个.cpp文件内.然后编译器就将这个.cpp编译成.obj,obj是什么东西?就是编译单元了. 一个程序,可以由一个编译单元组成,也可以有多个编译单元组成. 如果你不想 ...
- VS 2010不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件
打开VS后不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件 点击右图红色指示显示所有文件夹按钮,就能恢复.
- include .h 以及.cpp的记录
VC include 路径解析要了解vc中使用#include命令包含头文件所搜寻的路径,必须先了解vc中的几种路径:1. 系统路径 系统路径在vc中是"Tools->Options- ...
- 新建ui文件及相应.h和.cpp文件
1.在Qt Creator中新建一个任意的项目(如untitled): 2.在该项目中添加QT设计师界面类: 3.将新建的3个文件(.ui..h..cpp)拷贝到目标项目文件夹中: 4.分别在目标 ...
- Qt Creator 中,如何更改h,cpp,ui的文件并不让ui失效
这个星期在使用qt,碰到一个很蛋疼的问题:创建对话框的时候,不小心输错了名字.而且是在很迟才发现的.这个时候对话框都已经布局差不多了,为了改名字,碰到更蛋疼的问题,改了名字后就无法使用转到槽的功能了. ...
- C++编译与链接(0)-.h与.cpp中的定义与声明
C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须 ...
- 当打开一个.h或.cpp文件时, Solution Explorer就自动展开文件所在的目录
当打开一个.h或.cpp文件时, Solution Explorer就自动展开文件所在的目录: 如果不想展开: Tools -> Options -&g ...
- 第三十一篇 -- 理一下.h和.cpp的关系
今天突然想到一个问题,我们平时写代码会将代码进行分类,写到不同的cpp里,然后要用到那个类里面的函数,就直接include .h文件就好了.然后今天就在想,.h里面都是一些声明,它是怎么链接到.cpp ...
随机推荐
- 中软高科WEB前端面试题
一个朋友面试的题目,百度了一下这个中软高科貌似是一个培训机构...以下答案是我本人的理解,仅供参考 HTML+CSS 1.你能解释一下css的盒子模型吗? 有两种盒子模型:IE盒子模型,W3C盒子模型 ...
- ionic 项目中,ng-bind-html会过滤掉内嵌样式的问题
一.引入$sce,转化一步即可 $scope.articlesdetail.info = $sce.trustAsHtml($scope.articlesdetail.info); 参考网址: htt ...
- jquery获取标签名,获取id
var elementId = $(this).attr("id"); var tagName = $(this)[0].tagName;
- LeanCloud数据存储相关问题
1.短信验证码 当注册用户的时候,会发现收不到短信验证码,打印e : That operation isn't allowed for clients. 含义 - 该操作无法从客户端发起.请检查该错误 ...
- 安卓界面之Toolbar上手
一.在配置文件采用自定义Style方法去除Actionbar <resources> <style name="MyTheme" parent="The ...
- Cookie的HttpOnly、secure、domain属性
Cookie主要属性 Cookie主要属性: path domain max-age expires:是expires的补充,现阶段有兼容性问题:IE低版本不支持,所以一般不单独使用 secure h ...
- [20171206]rman与truncate2.txt
[20171206]rman与truncate2.txt --//上午测试发现truncate的表在做rman备份时还要做8个extents的备份.--//不知道自己的猜测是否正确,选择一个使用UNI ...
- python第二十九天-----继续学习第三模块——前几天旅行去了
subprocess模块 import subprocess subprocess.getstatusoutput('dir')#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结 ...
- CTR预估中GBDT与LR融合方案
1. 背景 CTR预估(Click-Through Rate Prediction)是互联网计算广告中的关键环节,预估准确性直接影响公司广告收入.CTR预估中用的最多的模型是LR(Logistic R ...
- 阿里云搭建JAVA WEB环境(SQL Server + TomCat + 配置域名)
假期刚刚搭完,先写个提纲,今晚写完: 1.申请一个月的免费的云服务器ECS; 2.在云服务器上安装Java开发环境+Sql Server+Tomcat; 3.购买域名并认证,绑定服务器共有IP地址; ...