zoukankan      html  css  js  c++  java
  • MFC串口编程——使用标准SerialCom类

    附件为实现visual studio C++串口通讯的类

    使用方法,定义一个类:CSerialCom m_serialCom;

    然后使用

    m_serialCom.InitPort(this, nPort, nBaud, 'E');
    m_serialCom.StartMonitoring();

    开始监控报文

    使用

    m_serialCom.ClosePort();

    关闭串口

    同时需要定义一个串口数据消息回调接收函数

    ON_MESSAGE(WM_COMM_RXCHAR, &OnReceiveData)

    1 LRESULT CVS_CCO_FOR_UpgradeDlg::OnReceiveData(WPARAM wParam, LPARAM lParam)
    2 {
    3     Uart_Has_RecOneByte = TRUE;
    4     uart_time_count = 0;
    5     ringq_push(&ringq_rbuff, (BYTE)wParam);
    6     
    7     return 0;
    8 }

    附件:SerialCom.cpp

      1 #include "stdafx.h"
      2 #include "SerialCom.h"
      3 #include <assert.h>
      4 //
      5 // Constructor
      6 //
      7 #pragma warning(disable:4996)
      8 CSerialCom::CSerialCom()
      9 {
     10     m_hComm = NULL;
     11     // initialize overlapped structure members to zero
     12     m_ov.Offset = 0;
     13     m_ov.OffsetHigh = 0;
     14     // create events
     15     m_ov.hEvent = NULL;
     16     m_hWriteEvent = NULL;
     17     m_hShutdownEvent = NULL;
     18     m_szWriteBuffer = NULL;
     19     m_nWriteSize = 1;
     20     m_bThreadAlive = FALSE;
     21 }
     22 //
     23 // Delete dynamic memory
     24 //
     25 CSerialCom::~CSerialCom()
     26 {
     27     do
     28     {
     29         SetEvent(m_hShutdownEvent);
     30     } while (m_bThreadAlive);
     31 
     32     TRACE("Thread ended/n");
     33     delete[] m_szWriteBuffer;
     34 }
     35 //
     36 // Initialize the port. This can be port 1 to 4.
     37 //
     38 BOOL CSerialCom::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
     39     UINT  portnr,  // portnumber (1..8)
     40     UINT  baud,   // baudrate
     41     char  parity,  // parity 
     42     UINT  databits,  // databits 
     43     UINT  stopbits,  // stopbits 
     44     DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
     45     UINT  writebuffersize) // size to the writebuffer
     46 {
     47     assert(portnr > 0 && portnr < 20);
     48     assert(pPortOwner != NULL);
     49     // if the thread is alive: Kill
     50     if (m_bThreadAlive)
     51     {
     52         do
     53         {
     54             SetEvent(m_hShutdownEvent);
     55         } while (m_bThreadAlive);
     56         TRACE("Thread ended/n");
     57     }
     58     // create events
     59     if (m_ov.hEvent != NULL)
     60         ResetEvent(m_ov.hEvent);
     61     m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     62     if (m_hWriteEvent != NULL)
     63         ResetEvent(m_hWriteEvent);
     64     m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     65 
     66     if (m_hShutdownEvent != NULL)
     67         ResetEvent(m_hShutdownEvent);
     68     m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     69     // initialize the event objects
     70     m_hEventArray[0] = m_hShutdownEvent; // highest priority
     71     m_hEventArray[1] = m_hWriteEvent;
     72     m_hEventArray[2] = m_ov.hEvent;
     73     // initialize critical section
     74     InitializeCriticalSection(&m_csCommunicationSync);
     75 
     76     // set buffersize for writing and save the owner
     77     m_pOwner = pPortOwner;
     78     if (m_szWriteBuffer != NULL)
     79         delete[] m_szWriteBuffer;
     80     m_szWriteBuffer = new char[writebuffersize];
     81     m_nPortNr = portnr;
     82     m_nWriteBufferSize = writebuffersize;
     83     m_dwCommEvents = dwCommEvents;
     84     BOOL bResult = FALSE;
     85     char *szPort = new char[50];
     86     char *szBaud = new char[50];
     87     // now it critical!
     88     EnterCriticalSection(&m_csCommunicationSync);
     89     // if the port is already opened: close it
     90     if (m_hComm != NULL)
     91     {
     92         CloseHandle(m_hComm);
     93         m_hComm = NULL;
     94     }
     95     // prepare port strings
     96     sprintf(szPort, "COM%d", portnr);
     97     sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
     98     // get a handle to the port
     99     m_hComm = CreateFileA(szPort,      // communication port string (COMX)
    100         GENERIC_READ | GENERIC_WRITE, // read/write types
    101         0,        // comm devices must be opened with exclusive access
    102         NULL,       // no security attributes
    103         OPEN_EXISTING,     // comm devices must use OPEN_EXISTING
    104         FILE_FLAG_OVERLAPPED,   // Async I/O
    105         0);       // template must be 0 for comm devices
    106     if (m_hComm == INVALID_HANDLE_VALUE)
    107     {
    108         // port not found
    109         delete[] szPort;
    110         delete[] szBaud;
    111         return FALSE;
    112     }
    113     // set the timeout values
    114     m_CommTimeouts.ReadIntervalTimeout = 1000;
    115     m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
    116     m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
    117     m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
    118     m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
    119     // configure
    120     if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
    121     {
    122         if (SetCommMask(m_hComm, dwCommEvents))
    123         {
    124             if (GetCommState(m_hComm, &m_dcb))
    125             {
    126                 m_dcb.EvtChar = 'q';
    127                 m_dcb.fRtsControl = RTS_CONTROL_ENABLE;  // set RTS bit high!
    128                 if (BuildCommDCBA(szBaud, &m_dcb))
    129                 {
    130                     if (SetCommState(m_hComm, &m_dcb))
    131                         ; // normal operation... continue
    132                     else
    133                         ProcessErrorMessage("SetCommState()");
    134                 }
    135                 else
    136                     ProcessErrorMessage("BuildCommDCB()");
    137             }
    138             else
    139                 ProcessErrorMessage("GetCommState()");
    140         }
    141         else
    142             ProcessErrorMessage("SetCommMask()");
    143     }
    144     else
    145         ProcessErrorMessage("SetCommTimeouts()");
    146     delete[] szPort;
    147     delete[] szBaud;
    148     // flush the port
    149     PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
    150     // release critical section
    151     LeaveCriticalSection(&m_csCommunicationSync);
    152     TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);
    153     return TRUE;
    154 }
    155 //
    156 //  The CommThread Function.
    157 //
    158 UINT CSerialCom::CommThread(LPVOID pParam)
    159 {
    160     // Cast the void pointer passed to the thread back to
    161     // a pointer of CSerialCom class
    162     CSerialCom *port = (CSerialCom*)pParam;
    163 
    164     // Set the status variable in the dialog class to
    165     // TRUE to indicate the thread is running.
    166     port->m_bThreadAlive = TRUE;
    167 
    168     // Misc. variables
    169     DWORD BytesTransfered = 0;
    170     DWORD Event = 0;
    171     DWORD CommEvent = 0;
    172     DWORD dwError = 0;
    173     COMSTAT comstat;
    174     memset(&comstat, 0, sizeof(COMSTAT));
    175     BOOL  bResult = TRUE;
    176 
    177     // Clear comm buffers at startup
    178     if (port->m_hComm)  // check if the port is opened
    179         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
    180     // begin forever loop.  This loop will run as long as the thread is alive.
    181     for (;;)
    182     {
    183         // Make a call to WaitCommEvent().  This call will return immediatly
    184         // because our port was created as an async port (FILE_FLAG_OVERLAPPED
    185         // and an m_OverlappedStructerlapped structure specified).  This call will cause the 
    186         // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to 
    187         // be placed in a non-signeled state if there are no bytes available to be read,
    188         // or to a signeled state if there are bytes available.  If this event handle 
    189         // is set to the non-signeled state, it will be set to signeled when a 
    190         // character arrives at the port.
    191         // we do this for each port!
    192         bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
    193         if (!bResult)
    194         {
    195             // If WaitCommEvent() returns FALSE, process the last error to determin
    196             // the reason..
    197             switch (dwError = GetLastError())
    198             {
    199             case ERROR_IO_PENDING:
    200             {
    201                 // This is a normal return value if there are no bytes
    202                 // to read at the port.
    203                 // Do nothing and continue
    204                 break;
    205             }
    206             case 87:
    207             {
    208                 // Under Windows NT, this value is returned for some reason.
    209                 // I have not investigated why, but it is also a valid reply
    210                 // Also do nothing and continue.
    211                 break;
    212             }
    213             default:
    214             {
    215                 // All other error codes indicate a serious error has
    216                 // occured.  Process this error.
    217                 port->ProcessErrorMessage("WaitCommEvent()");
    218                 break;
    219             }
    220             }
    221         }
    222         else
    223         {    /*
    224             // If WaitCommEvent() returns TRUE, check to be sure there are
    225             // actually bytes in the buffer to read.  
    226             //
    227             // If you are reading more than one byte at a time from the buffer 
    228             // (which this program does not do) you will have the situation occur 
    229             // where the first byte to arrive will cause the WaitForMultipleObjects() 
    230             // function to stop waiting.  The WaitForMultipleObjects() function 
    231             // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
    232             // as it returns.  
    233             //
    234             // If in the time between the reset of this event and the call to 
    235             // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
    236             // to the signeled state. When the call to ReadFile() occurs, it will 
    237             // read all of the bytes from the buffer, and the program will
    238             // loop back around to WaitCommEvent().
    239             // 
    240             // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
    241             // but there are no bytes available to read.  If you proceed and call
    242             // ReadFile(), it will return immediatly due to the async port setup, but
    243             // GetOverlappedResults() will not return until the next character arrives.
    244             //
    245             // It is not desirable for the GetOverlappedResults() function to be in 
    246             // this state.  The thread shutdown event (event 0) and the WriteFile()
    247             // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
    248             //
    249             // The solution to this is to check the buffer with a call to ClearCommError().
    250             // This call will reset the event handle, and if there are no bytes to read
    251             // we can loop back through WaitCommEvent() again, then proceed.
    252             // If there are really bytes to read, do nothing and proceed.
    253             */
    254             bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
    255             if (comstat.cbInQue == 0)
    256                 continue;
    257         } // end if bResult
    258           // Main wait function.  This function will normally block the thread
    259           // until one of nine events occur that require action.
    260         Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
    261         switch (Event)
    262         {
    263         case 0:
    264         {
    265             // Shutdown event.  This is event zero so it will be
    266             // the higest priority and be serviced first.
    267             CloseHandle(port->m_hComm);
    268             port->m_hComm = NULL;
    269             port->m_bThreadAlive = FALSE;
    270 
    271             // Kill this thread.  break is not needed, but makes me feel better.
    272             AfxEndThread(100);
    273             break;
    274         }
    275         case 2: // read event
    276         {
    277             GetCommMask(port->m_hComm, &CommEvent);
    278             if (CommEvent & EV_RXCHAR)
    279                 // Receive character event from port.
    280                 ReceiveChar(port, comstat);
    281             if (CommEvent & EV_CTS)
    282                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);
    283             if (CommEvent & EV_BREAK)
    284                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);
    285             if (CommEvent & EV_ERR)
    286                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);
    287             if (CommEvent & EV_RING)
    288                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);
    289 
    290             if (CommEvent & EV_RXFLAG)
    291                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)port->m_nPortNr);
    292 
    293             break;
    294         }
    295         case 1: // write event
    296         {
    297             // Write character event from port
    298             WriteChar(port);
    299             break;
    300         }
    301         } // end switch
    302     } // close forever loop
    303     return 0;
    304 }
    305 //
    306 // start comm watching
    307 //
    308 BOOL CSerialCom::StartMonitoring()
    309 {
    310     if (!(m_Thread = AfxBeginThread(CommThread, this)))
    311         return FALSE;
    312     TRACE("Thread started/n");
    313     return TRUE;
    314 }
    315 //
    316 // Restart the comm thread
    317 //
    318 BOOL CSerialCom::RestartMonitoring()
    319 {
    320     TRACE("Thread resumed/n");
    321     m_Thread->ResumeThread();
    322     return TRUE;
    323 }
    324 
    325 //
    326 // Suspend the comm thread
    327 //
    328 BOOL CSerialCom::StopMonitoring()
    329 {
    330     TRACE("Thread suspended/n");
    331     m_Thread->SuspendThread();
    332     return TRUE;
    333 }
    334 
    335 //
    336 // If there is a error, give the right message
    337 //
    338 void CSerialCom::ProcessErrorMessage(char* ErrorText)
    339 {
    340     char *Temp = new char[200];
    341 
    342     LPVOID lpMsgBuf;
    343     FormatMessage(
    344         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    345         NULL,
    346         GetLastError(),
    347         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    348         (LPTSTR)&lpMsgBuf,
    349         0,
    350         NULL
    351         );
    352     sprintf(Temp, "WARNING:  %s Failed with the following error: /n%s/nPort: %d/n", ErrorText, (char*)lpMsgBuf, m_nPortNr);
    353     MessageBoxA(NULL, Temp, "Application Error", MB_ICONSTOP);
    354     LocalFree(lpMsgBuf);
    355     delete[] Temp;
    356 }
    357 //
    358 // Write a character.
    359 //
    360 void CSerialCom::WriteChar(CSerialCom* port)
    361 {
    362     BOOL bWrite = TRUE;
    363     BOOL bResult = TRUE;
    364     DWORD BytesSent = 0;
    365     ResetEvent(port->m_hWriteEvent);
    366     // Gain ownership of the critical section
    367     EnterCriticalSection(&port->m_csCommunicationSync);
    368     if (bWrite)
    369     {
    370         // Initailize variables
    371         port->m_ov.Offset = 0;
    372         port->m_ov.OffsetHigh = 0;
    373         // Clear buffer
    374         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
    375         bResult = WriteFile(port->m_hComm,       // Handle to COMM Port
    376             port->m_szWriteBuffer,     // Pointer to message buffer in calling finction
    377                                        //       strlen((char*)port->m_szWriteBuffer), // Length of message to send
    378             port->m_nWriteSize, // Length of message to send
    379             &BytesSent,        // Where to store the number of bytes sent
    380             &port->m_ov);       // Overlapped structure
    381                                 // deal with any error codes
    382         if (!bResult)
    383         {
    384             DWORD dwError = GetLastError();
    385             switch (dwError)
    386             {
    387             case ERROR_IO_PENDING:
    388             {
    389                 // continue to GetOverlappedResults()
    390                 BytesSent = 0;
    391                 bWrite = FALSE;
    392                 break;
    393             }
    394             default:
    395             {
    396                 // all other error codes
    397                 port->ProcessErrorMessage("WriteFile()");
    398             }
    399             }
    400         }
    401         else
    402         {
    403             LeaveCriticalSection(&port->m_csCommunicationSync);
    404         }
    405     } // end if(bWrite)
    406     if (!bWrite)
    407     {
    408         bWrite = TRUE;
    409 
    410         bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port 
    411             &port->m_ov,  // Overlapped structure
    412             &BytesSent,  // Stores number of bytes sent
    413             TRUE);    // Wait flag
    414         LeaveCriticalSection(&port->m_csCommunicationSync);
    415         // deal with the error code 
    416         //  if (!bResult)  
    417         {
    418             //   port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
    419         }
    420     } // end if (!bWrite)
    421       // Verify that the data size send equals what we tried to send
    422       // if (BytesSent != strlen((char*)port->m_szWriteBuffer))
    423     {
    424         //  TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d/n", BytesSent, strlen((char*)port->m_szWriteBuffer));
    425     }
    426     // ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
    427     ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED, 0, (LPARAM)port->m_nPortNr);
    428 }
    429 //
    430 // Character received. Inform the owner
    431 //
    432 void CSerialCom::ReceiveChar(CSerialCom* port, COMSTAT comstat)
    433 {
    434     BOOL  bRead = TRUE;
    435     BOOL  bResult = TRUE;
    436     DWORD dwError = 0;
    437     DWORD BytesRead = 0;
    438     unsigned char RXBuff;
    439     for (;;)
    440     {
    441         // Gain ownership of the comm port critical section.
    442         // This process guarantees no other part of this program 
    443         // is using the port object. 
    444 
    445         EnterCriticalSection(&port->m_csCommunicationSync);
    446         // ClearCommError() will update the COMSTAT structure and
    447         // clear any other errors.
    448 
    449         bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
    450         LeaveCriticalSection(&port->m_csCommunicationSync);
    451         // start forever loop.  I use this type of loop because I
    452         // do not know at runtime how many loops this will have to
    453         // run. My solution is to start a forever loop and to
    454         // break out of it when I have processed all of the
    455         // data available.  Be careful with this approach and
    456         // be sure your loop will exit.
    457         // My reasons for this are not as clear in this sample 
    458         // as it is in my production code, but I have found this 
    459         // solutiion to be the most efficient way to do this.
    460 
    461         if (comstat.cbInQue == 0)
    462         {
    463             // break out when all bytes have been read
    464             break;
    465         }
    466 
    467         EnterCriticalSection(&port->m_csCommunicationSync);
    468         if (bRead)
    469         {
    470             bResult = ReadFile(port->m_hComm,  // Handle to COMM port 
    471                 &RXBuff,    // RX Buffer Pointer
    472                 1,     // Read one byte
    473                 &BytesRead,   // Stores number of bytes read
    474                 &port->m_ov);  // pointer to the m_ov structure
    475                                // deal with the error code 
    476             if (!bResult)
    477             {
    478                 switch (dwError = GetLastError())
    479                 {
    480                 case ERROR_IO_PENDING:
    481                 {
    482                     // asynchronous i/o is still in progress 
    483                     // Proceed on to GetOverlappedResults();
    484                     bRead = FALSE;
    485                     break;
    486                 }
    487                 default:
    488                 {
    489                     // Another error has occured.  Process this error.
    490                     port->ProcessErrorMessage("ReadFile()");
    491                     break;
    492                 }
    493                 }
    494             }
    495             else
    496             {
    497                 // ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
    498                 bRead = TRUE;
    499             }
    500         }  // close if (bRead)
    501         if (!bRead)
    502         {
    503             bRead = TRUE;
    504             bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port 
    505                 &port->m_ov,  // Overlapped structure
    506                 &BytesRead,  // Stores number of bytes read
    507                 TRUE);    // Wait flag
    508                           // deal with the error code 
    509             if (!bResult)
    510             {
    511                 port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
    512             }
    513         }  // close if (!bRead)
    514 
    515         LeaveCriticalSection(&port->m_csCommunicationSync);
    516         // notify parent that a byte was received
    517         ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM)RXBuff, (LPARAM)port->m_nPortNr);//发送消息,对应的消息函数接收数据
    518     } // end forever loop
    519 }
    520 //
    521 // Write a string to the port
    522 //
    523 void CSerialCom::WriteToPort(char* string)
    524 {
    525     assert(m_hComm != 0);
    526 
    527     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
    528     strcpy(m_szWriteBuffer, string);
    529     m_nWriteSize = strlen(string);
    530     // set event for write
    531     SetEvent(m_hWriteEvent);
    532 }
    533 
    534 void CSerialCom::WriteToPort(char* string, int n)
    535 {
    536     assert(m_hComm != 0);
    537     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
    538     // memset(m_szWriteBuffer, 0, n);
    539     // strncpy(m_szWriteBuffer, string, n);
    540     memcpy(m_szWriteBuffer, string, n);
    541     m_nWriteSize = n;
    542     // set event for write
    543     SetEvent(m_hWriteEvent);
    544 }
    545 
    546 
    547 #if 0
    548 void CSerialCom::WriteToPort(LPCTSTR string)
    549 {
    550     assert(m_hComm != 0);
    551     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
    552     strcpy(m_szWriteBuffer, string);
    553     m_nWriteSize = strlen(string);
    554     // set event for write
    555     SetEvent(m_hWriteEvent);
    556 }
    557 #endif
    558 void CSerialCom::WriteToPort(LPCTSTR string, int n)
    559 {
    560     assert(m_hComm != 0);
    561     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
    562     // strncpy(m_szWriteBuffer, string, n);
    563     memcpy(m_szWriteBuffer, string, n);
    564     m_nWriteSize = n;
    565     // set event for write
    566     SetEvent(m_hWriteEvent);
    567 }
    568 //
    569 // Return the device control block
    570 //
    571 DCB CSerialCom::GetDCB()
    572 {
    573     return m_dcb;
    574 }
    575 //
    576 // Return the communication event masks
    577 //
    578 DWORD CSerialCom::GetCommEvents()
    579 {
    580     return m_dwCommEvents;
    581 }
    582 //
    583 // Return the output buffer size
    584 //
    585 DWORD CSerialCom::GetWriteBufferSize()
    586 {
    587     return m_nWriteBufferSize;
    588 }
    589 
    590 void CSerialCom::ClosePort()
    591 {
    592     SetEvent(m_hShutdownEvent);
    593 }
    594 
    595 void CSerialCom::EnumerateSerialPorts(CUIntArray& ports)
    596 {
    597     ports.RemoveAll();    //Make sure we clear out any elements which may already be in the array
    598 
    599                         //Determine what OS we are running on
    600     OSVERSIONINFO osvi;
    601     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    602     BOOL bGetVer = GetVersionEx(&osvi);
    603 
    604     //On NT use the QueryDosDevice API
    605     if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT))
    606     {
    607         //Use QueryDosDevice to look for all devices of the form COMx. This is a better
    608         //solution as it means that no ports have to be opened at all.
    609         TCHAR szDevices[65535];
    610         DWORD dwChars = QueryDosDevice(NULL, szDevices, 65535);
    611         if (dwChars) {
    612             int i = 0;
    613             for (;;) {
    614                 TCHAR* pszCurrentDevice = &szDevices[i];    //Add the port number to the array which will be returned
    615                                                             //If it looks like "COMX" then
    616                                                             //add it to the array which will be returned
    617                 int nLen = _tcslen(pszCurrentDevice);
    618                 if (nLen > 3 && _tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0) {
    619                     int nPort = _ttoi(&pszCurrentDevice[3]);    //Work out the port number
    620                     ports.Add(nPort);        //clear out com_0
    621                 }
    622                 // Go to next NULL character
    623                 while (szDevices[i] != _T('')) i++;
    624                 i++;    // Bump pointer to the next string
    625                         // The list is double-NULL terminated, so if the character is
    626                         // now NULL, we're at the end
    627                 if (szDevices[i] == _T('')) break;
    628             }
    629         }
    630         else TRACE(_T("Failed in call to QueryDosDevice, GetLastError:%d
    "), GetLastError());
    631     }
    632     else {
    633         //On 95/98 open up each port to determine their existence
    634         //Up to 255 COM ports are supported so we iterate through all of them seeing
    635         //if we can open them or if we fail to open them, get an access denied or general error error.
    636         //Both of these cases indicate that there is a COM port at that number. 
    637         for (UINT i = 1; i<256; i++)
    638         {
    639             //Form the Raw device name
    640             CString sPort;
    641             sPort.Format(_T("\\.\COM%d"), i);
    642 
    643             //Try to open the port
    644             BOOL bSuccess = FALSE;
    645             HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    646             if (hPort == INVALID_HANDLE_VALUE)
    647             {
    648                 DWORD dwError = GetLastError();
    649                 //Check to see if the error was because some other app had the port open or a general failure
    650                 if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE)
    651                     bSuccess = TRUE;
    652             }
    653             else {
    654                 bSuccess = TRUE;    //The port was opened successfully                
    655                 CloseHandle(hPort);    //Don't forget to close the port, since we are going to do nothing with it anyway
    656             }
    657             if (bSuccess) ports.Add(i);    //Add the port number to the array which will be returned
    658         }
    659     }
    660 }

    SerialCom.h

     1 #pragma once
     2 
     3 #define WM_COMM_BREAK_DETECTED  WM_USER+1 // A break was detected on input.
     4 #define WM_COMM_CTS_DETECTED  WM_USER+2 // The CTS (clear-to-send) signal changed state. 
     5 #define WM_COMM_DSR_DETECTED  WM_USER+3 // The DSR (data-set-ready) signal changed state. 
     6 #define WM_COMM_ERR_DETECTED  WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 
     7 #define WM_COMM_RING_DETECTED  WM_USER+5 // A ring indicator was detected. 
     8 #define WM_COMM_RLSD_DETECTED  WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state. 
     9 #define WM_COMM_RXCHAR    WM_USER+7 // A character was received and placed in the input buffer. 
    10 #define WM_COMM_RXFLAG_DETECTED  WM_USER+8 // The event character was received and placed in the input buffer.  
    11 #define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in the output buffer was sent. 
    12 class CSerialCom
    13 {
    14 public:
    15     int m_nWriteSize;
    16     void ClosePort();
    17     // contruction and destruction
    18     CSerialCom();
    19     virtual  ~CSerialCom();
    20     // port initialisation           
    21     BOOL  InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 9600, char parity = 'N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);
    22     HANDLE    m_hComm;
    23     // start/stop comm watching
    24     BOOL  StartMonitoring();
    25     BOOL  RestartMonitoring();
    26     BOOL  StopMonitoring();
    27     DWORD  GetWriteBufferSize();
    28     DWORD  GetCommEvents();
    29     DCB   GetDCB();
    30     void  WriteToPort(char* string);
    31     void  WriteToPort(char* string, int n);
    32     void  WriteToPort(LPCTSTR string);
    33     void  WriteToPort(LPCTSTR string, int n);
    34     void EnumerateSerialPorts(CUIntArray& ports);
    35 protected:
    36     // protected memberfunctions
    37     void  ProcessErrorMessage(char* ErrorText);
    38     static UINT CommThread(LPVOID pParam);
    39     static void ReceiveChar(CSerialCom* port, COMSTAT comstat);
    40     static void WriteChar(CSerialCom* port);
    41     // thread
    42     CWinThread*   m_Thread;
    43     // synchronisation objects
    44     CRITICAL_SECTION m_csCommunicationSync;
    45     BOOL    m_bThreadAlive;
    46     // handles
    47     HANDLE    m_hWriteEvent;
    48     HANDLE    m_hShutdownEvent;
    49     // Event array. 
    50     // One element is used for each event. There are two event handles for each port.
    51     // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).
    52     // There is a general shutdown when the port is closed. 
    53     HANDLE    m_hEventArray[3];
    54     // structures
    55     OVERLAPPED   m_ov;
    56     COMMTIMEOUTS  m_CommTimeouts;
    57     DCB     m_dcb;
    58     // owner window
    59     CWnd*    m_pOwner;
    60     // misc
    61     UINT    m_nPortNr;
    62     char*    m_szWriteBuffer;
    63     DWORD    m_dwCommEvents;
    64     DWORD    m_nWriteBufferSize;    
    65 };
  • 相关阅读:
    [做题记录]数学#1
    [鸽鸽]
    有关VHDL中null, 在Verilog HDL 中的表示方法 YB
    有关Quartus如何自动生成 .pof 文件 YB
    javac、java命令如何编译运行目标类以及其类引入的外部jar包
    虚拟机装 CentOs 7 黑屏解决办法
    curl 访问https
    游戏命中判定:圆桌算法和程序实现
    Unity3d与dll文件
    C++异步网络库workflow及基于workflow实现的网络框架wfrest的安装使用心得
  • 原文地址:https://www.cnblogs.com/codecamel/p/6420454.html
Copyright © 2011-2022 走看看