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__
View Code

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
");
 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
");
 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.
Use Startmonitor to communicate.
", 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
");
426     return TRUE;    
427 }
428 //
429 // Restart the comm thread
430 //
431 BOOL CSerialPort::RestartMonitoring()
432 {
433     TRACE("Thread resumed
");
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
");
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: 
%s
Port: %d
", (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
", 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 }
View Code
原文地址:https://www.cnblogs.com/qiwu1314/p/8708841.html