zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    时间加减天数
    时间加减秒数
    什么BOM?
    js 事件基础
    js 九九乘法
    CSS3 动画基础单词语法
    css3 3D转换 基础语法
    css3 2D 转换 基础语法
    js onchange案例
    js之冒泡排序
  • 原文地址:https://www.cnblogs.com/qiwu1314/p/8708841.html
Copyright © 2011-2022 走看看