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 }

原文地址:https://www.cnblogs.com/tianqiang/p/9988459.html

时间: 2024-11-09 00:13:24

SerialPort.h SerialPort.cpp的相关文章

C++的.h和.cpp根据java来理解

因为要学习cocos2dx所以要学习c++开发然后在学习中看到.h 和 .cpp文件. .h文件进行接口定义,没有具体的实现.很明显跟java的interface一样的作用. .cpp文件是具体的代码实现.跟java类比就是具体的类实现上面定义的interface的类. 这种.h 和.cpp的方式是Opp编程体现吧. 用.h 和 java 用interface都拥有的好处: 抽象逻辑,抽象出层次,方便理解和维护代码.如果做对外开放api,对外可以公布接口,保留代码.这样做比较迅速快捷. 用接口抽

C++编译与链接(0)-.h与.cpp中的定义与声明

C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须在.cpp中定义,声明呢? *以下所有的讨论都是在全局命名空间中(即不定义自己的namespace)下进行的 函数 1.在.h中只能声明函数,在.cpp中可以声明与定义函数 如果在.h中声明并定义一个函数,则该函数只能被#include一次,否则则会出现重定义错误 比如 1.h #pragma on

include .h 以及.cpp的记录

VC include 路径解析要了解vc中使用#include命令包含头文件所搜寻的路径,必须先了解vc中的几种路径:1. 系统路径 系统路径在vc中是"Tools->Options->Directories"中"Include files"指定的路径. 打开此对话框会发现默认有这几条路径:C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE C:\Program Files\Microsoft Vi

c++ *.h和*.cpp在编译中的作用

首先,我们可以将所有东西都放在一个.cpp文件内.然后编译器就将这个.cpp编译成.obj,obj是什么东西?就是编译单元了. 一个程序,可以由一个编译单元组成,也可以有多个编译单元组成. 如果你不想让你的源代码变得很难阅读的话,就请使用多个编译单元吧.(一个函数不能放到两个编译单元里面,但两个以上就可以分别放在一个单元,也就是cpp里面)那么就是一个.cpp对应一个.obj,然后将所有的obj链接起来(通过一个叫链接器的程序),组成一个.exe,也就是程序了. 如果一个.cpp要用到另一个.c

VS 2010不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件

打开VS后不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件 点击右图红色指示显示所有文件夹按钮,就能恢复.

Qt Creator 中,如何更改h,cpp,ui的文件并不让ui失效

这个星期在使用qt,碰到一个很蛋疼的问题:创建对话框的时候,不小心输错了名字.而且是在很迟才发现的.这个时候对话框都已经布局差不多了,为了改名字,碰到更蛋疼的问题,改了名字后就无法使用转到槽的功能了.具体的错误显示如下: this application failed to start because - 经过一场大战,终于知道如何改名字,下面说下步骤: 1:更改h,cpp,ui的名字. 2:到ui文件中,把对象名字更改了.这里最好在右下角的属性框里改,更改后按下enter. 3:到cpp文件中

[hge] distort.h distort.cpp

荡漾   --写在开头 在两个文件组合起来要实现的功能就是使得一个画片图水波般荡漾 首先来看头文件中的东西 Chapter I: distort.h Part Ⅰ:attributes private: hgeDistortionMesh(); // 构造函数,话说放在 private 是为了屏蔽这个接口,使得初始化过程中必须有参数 static HGE *hge; // 引擎指针 hgeVertex *disp_array; // 顶点数组 int nRows, nCols; // 行数.列数

【C/C++学院】(5)面向对象编程练习--h和cpp分开编写

抽象一个点,一个圆,并判断点与圆的关系.(在圆内还是圆外) h文件进行类的声明: cpp文件为类的实现细节:主要注重的细节为: ================================================================================================================================= 工程代码如下: //MyCircle.h #pragma once #include"MyPoint.h&quo

61)普通类的.h和.cpp分离

1 //标头.h文件 2 3 //这个是在C中这样写 4 5 #ifndef HH_01//开始写小写 hh_01 然后选中这个 crtl+shift+u 就变成大写了 6 #define HH_01 7 8 9 #endif 10 11 12 13 //在C++这样写,防止文件被包含 14 #pragma once 15 #include<string> 16 #include<iostream> 17 using namespace std; 18 19 class perso