Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1966012
  • 博文数量: 356
  • 博客积分: 8284
  • 博客等级: 中将
  • 技术积分: 4580
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-15 20:25
个人简介

天行健,君子以自强不息

文章分类

全部博文(356)

文章存档

2018年(1)

2016年(4)

2015年(13)

2014年(14)

2013年(2)

2012年(25)

2011年(43)

2010年(65)

2009年(189)

分类: C/C++

2015-10-17 19:50:27

c文件

点击(此处)折叠或打开

  1. /*
  2. **    FILENAME            CSerialPort.cpp
  3. **
  4. **    PURPOSE                This class can read, write and watch one serial port.
  5. **                        It sends messages to its owner when something happends on the port
  6. **                        The class creates a thread for reading and writing so the main
  7. **                        program is not blocked.
  8. **
  9. **    CREATION DATE        15-09-1997
  10. **    LAST MODIFICATION    12-11-1997
  11. **
  12. **    AUTHOR                Remon Spekreijse
  13. **
  14. **
  15. */

  16. #include "stdafx.h"
  17. #include "SerialPort.h"


  18. #include "mtype.h"
  19. #include "mqueue.h"

  20. #include <assert.h>
  21.  

  22. uint8 rcv_buf[1000];
  23. //uint8 snd_buf[1000];


  24. //
  25. // Constructor
  26. //
  27. CSerialPort::CSerialPort()
  28. {
  29.     m_hComm = NULL;

  30.     // initialize overlapped structure members to zero
  31.     m_ov.Offset = 0;
  32.     m_ov.OffsetHigh = 0;

  33.     // create events
  34.     m_ov.hEvent = NULL;
  35.     m_hWriteEvent = NULL;
  36.     m_hShutdownEvent = NULL;

  37.     m_szWriteBuffer = NULL;

  38.     m_bThreadAlive = FALSE;
  39.     m_bSerialPortIsOpen=FALSE;
  40. }

  41. //
  42. // Delete dynamic memory
  43. //
  44. CSerialPort::~CSerialPort()
  45. {
  46.     do
  47.     {
  48.         SetEvent(m_hShutdownEvent);
  49.     } while (m_bThreadAlive);

  50.     TRACE("Thread ended\n");

  51.     delete [] m_szWriteBuffer;
  52. }

  53. uint8 ReadFull(void)
  54. {

  55.     return 0;
  56. }

  57. uint8 ReadEmpty(void)
  58. {

  59.     return 0;
  60. }
  61. //
  62. // Initialize the port. This can be port 1 to 4.
  63. //
  64. BOOL CSerialPort::InitPort(CWnd* pPortOwner,    // the owner (CWnd) of the port (receives message)
  65.                          UINT portnr,        // portnumber (1..4)
  66.                          UINT baud,            // baudrate
  67.                          char parity,        // parity
  68.                          UINT databits,        // databits
  69.                          UINT stopbits,        // stopbits
  70.                          DWORD dwCommEvents,    // EV_RXCHAR, EV_CTS etc
  71.                          UINT writebuffersize)    // size to the writebuffer
  72. {
  73.     assert(portnr > 0 && portnr < 255);
  74.     assert(pPortOwner != NULL);

  75.     // if the thread is alive: Kill
  76.     if (m_bThreadAlive)
  77.     {
  78.         do
  79.         {
  80.             SetEvent(m_hShutdownEvent);
  81.         } while (m_bThreadAlive);
  82.         TRACE("Thread ended\n");
  83.     }
  84.     
  85.     //InitQueue(void)
  86.     

  87.     QueueCreate( (uint8 *)rcv_buf,sizeof(rcv_buf),sizeof(uint8),NULL,NULL);
  88. //    QueueCreate( (uint8 *)snd_buf,sizeof(snd_buf),sizeof(uint8),NULL,NULL);
  89.     
  90.     // create events
  91.     if (m_ov.hEvent != NULL)
  92.         ResetEvent(m_ov.hEvent);
  93.     m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  94.     if (m_hWriteEvent != NULL)
  95.         ResetEvent(m_hWriteEvent);
  96.     m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  97.     
  98.     if (m_hShutdownEvent != NULL)
  99.         ResetEvent(m_hShutdownEvent);
  100.     m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  101.     // initialize the event objects
  102.     m_hEventArray[0] = m_hShutdownEvent;    // highest priority
  103.     m_hEventArray[1] = m_ov.hEvent;
  104.     m_hEventArray[2] = m_hWriteEvent;

  105.     // initialize critical section
  106.     InitializeCriticalSection(&m_csCommunicationSync);
  107.     
  108.     // set buffersize for writing and save the owner
  109.     m_pOwner = pPortOwner;

  110.     if (m_szWriteBuffer != NULL)
  111.         delete [] m_szWriteBuffer;
  112.     m_szWriteBuffer = new char[writebuffersize];

  113.     m_nPortNr = portnr;

  114.     m_nWriteBufferSize = writebuffersize;
  115.     m_dwCommEvents = dwCommEvents;

  116.     BOOL bResult = FALSE;
  117.     char *szPort = new char[50];
  118.     char *szBaud = new char[50];

  119.     // now it
  120.     EnterCriticalSection(&m_csCommunicationSync);

  121.     // if the port is already opened: close it
  122.     if (m_hComm != NULL)
  123.     {
  124.         CloseHandle(m_hComm);
  125.         m_hComm = NULL;
  126.     }

  127.     // prepare port strings
  128.     sprintf(szPort, "COM%d", portnr);
  129.     sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);

  130.     // get a handle to the port
  131.     m_hComm = CreateFile(szPort,                        // communication port string (COMX)
  132.                      GENERIC_READ | GENERIC_WRITE,    // read/write types
  133.                      0,                                // comm devices must be opened with exclusive access
  134.                      NULL,                            // no security attributes
  135.                      OPEN_EXISTING,                    // comm devices must use OPEN_EXISTING
  136.                      FILE_FLAG_OVERLAPPED,            // Async I/O
  137.                      0);                            // template must be 0 for comm devices

  138.     if (m_hComm == INVALID_HANDLE_VALUE)
  139.     {
  140.         // port not found
  141.         delete [] szPort;
  142.         delete [] szBaud;

  143.         return FALSE;
  144.     }

  145.     // set the timeout values
  146.     m_CommTimeouts.ReadIntervalTimeout = 1000;
  147.     m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
  148.     m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
  149.     m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
  150.     m_CommTimeouts.WriteTotalTimeoutConstant = 1000;

  151.     // configure
  152.     if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
  153.     {                        
  154.         if (SetCommMask(m_hComm, dwCommEvents))
  155.         {
  156.             if (GetCommState(m_hComm, &m_dcb))
  157.             {
  158.                 m_dcb.fRtsControl = RTS_CONTROL_ENABLE;        // set RTS bit
  159.                 if (BuildCommDCB(szBaud, &m_dcb))
  160.                 {
  161.                     if (SetCommState(m_hComm, &m_dcb))
  162.                         ; // normal operation... continue
  163.                     else
  164.                         ProcessErrorMessage("SetCommState()");
  165.                 }
  166.                 else
  167.                     ProcessErrorMessage("BuildCommDCB()");
  168.             }
  169.             else
  170.                 ProcessErrorMessage("GetCommState()");
  171.         }
  172.         else
  173.             ProcessErrorMessage("SetCommMask()");
  174.     }
  175.     else
  176.         ProcessErrorMessage("SetCommTimeouts()");

  177.     delete [] szPort;
  178.     delete [] szBaud;

  179.     // flush the port
  180.     PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

  181.     // release critical section
  182.     LeaveCriticalSection(&m_csCommunicationSync);

  183.     TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);

  184.     return TRUE;
  185. }

  186. //
  187. // The CommThread Function.
  188. //
  189. UINT CSerialPort::CommThread(LPVOID pParam)
  190. {
  191.     // Cast the void pointer passed to the thread back to
  192.     // a pointer of CSerialPort class
  193.     CSerialPort *port = (CSerialPort*)pParam;
  194.     
  195.     // Set the status variable in the dialog class to
  196.     // TRUE to indicate the thread is running.
  197.     port->m_bThreadAlive = TRUE;    
  198.         
  199.     // Misc. variables
  200.     DWORD BytesTransfered = 0;
  201.     DWORD Event = 0;
  202.     DWORD CommEvent = 0;
  203.     DWORD dwError = 0;
  204.     COMSTAT comstat;
  205.     BOOL bResult = TRUE;
  206.         
  207.     // Clear comm buffers at startup
  208.     if (port->m_hComm)        // check if the port is opened
  209.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

  210.     // begin forever loop. This loop will run as long as the thread is alive.
  211.     for (;;)
  212.     {

  213.         // Make a call to WaitCommEvent(). This call will return immediatly
  214.         // because our port was created as an async port (FILE_FLAG_OVERLAPPED
  215.         // and an m_OverlappedStructerlapped structure specified). This call will cause the
  216.         // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to
  217.         // be placed in a non-signeled state if there are no bytes available to be read,
  218.         // or to a signeled state if there are bytes available. If this event handle
  219.         // is set to the non-signeled state, it will be set to signeled when a
  220.         // character arrives at the port.

  221.         // we do this for each

  222.         bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);

  223.         if (!bResult)
  224.         {
  225.             // If WaitCommEvent() returns FALSE, process the last error to determin
  226.             // the reason..
  227.             switch (dwError = GetLastError())
  228.             {
  229.             case ERROR_IO_PENDING:     
  230.                 {
  231.                     // This is a normal return value if there are no bytes
  232.                     // to read at the port.
  233.                     // Do nothing and continue
  234.                     break;
  235.                 }
  236.             case 87:
  237.                 {
  238.                     // Under Windows NT, this value is returned for some reason.
  239.                     // I have not investigated why, but it is also a valid reply
  240.                     // Also do nothing and continue.
  241.                     break;
  242.                 }
  243.             default:
  244.                 {
  245.                     // All other error codes indicate a serious error has
  246.                     // occured. Process this error.
  247.                     port->ProcessErrorMessage("WaitCommEvent()");
  248.                     break;
  249.                 }
  250.             }
  251.         }
  252.         else
  253.         {
  254.             // If WaitCommEvent() returns TRUE, check to be sure there are
  255.             // actually bytes in the buffer to read.
  256.             //
  257.             // If you are reading more than one byte at a time from the buffer
  258.             // (which this program does not do) you will have the situation occur
  259.             // where the first byte to arrive will cause the WaitForMultipleObjects()
  260.             // function to stop waiting. The WaitForMultipleObjects() function
  261.             // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
  262.             // as it returns.
  263.             //
  264.             // If in the time between the reset of this event and the call to
  265.             // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
  266.             // to the signeled state. When the call to ReadFile() occurs, it will
  267.             // read all of the bytes from the buffer, and the program will
  268.             // loop back around to WaitCommEvent().
  269.             //
  270.             // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
  271.             // but there are no bytes available to read. If you proceed and call
  272.             // ReadFile(), it will return immediatly due to the async port setup, but
  273.             // GetOverlappedResults() will not return until the next character arrives.
  274.             //
  275.             // It is not desirable for the GetOverlappedResults() function to be in
  276.             // this state. The thread shutdown event (event 0) and the WriteFile()
  277.             // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
  278.             //
  279.             // The solution to this is to check the buffer with a call to ClearCommError().
  280.             // This call will reset the event handle, and if there are no bytes to read
  281.             // we can loop back through WaitCommEvent() again, then proceed.
  282.             // If there are really bytes to read, do nothing and proceed.
  283.         
  284.             bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

  285.             if (comstat.cbInQue == 0)
  286.                 continue;
  287.         }    // end if bResult

  288.         // Main wait function. This function will normally block the thread
  289.         // until one of nine events occur that require action.
  290.         Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);

  291.         switch (Event)
  292.         {
  293.         case 0:
  294.             {
  295.                 // Shutdown event. This is event zero so it will be
  296.                 // the higest priority and be serviced first.

  297.                  port->m_bThreadAlive = FALSE;
  298.                 
  299.                 // Kill this thread. break is not needed, but makes me feel better.
  300.                 AfxEndThread(100);
  301.                 break;
  302.             }
  303.         case 1:    // read event
  304.             {
  305.                 GetCommMask(port->m_hComm, &CommEvent);
  306.                 if (CommEvent & EV_CTS)
  307.                     ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
  308.                 if (CommEvent & EV_RXFLAG)
  309.                     ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
  310.                 if (CommEvent & EV_BREAK)
  311.                     ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
  312.                 if (CommEvent & EV_ERR)
  313.                     ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
  314.                 if (CommEvent & EV_RING)
  315.                     ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
  316.                 
  317.                 if (CommEvent & EV_RXCHAR)
  318.                     // Receive character event from port.
  319.                     ReceiveChar(port, comstat);
  320.                     
  321.                 break;
  322.             }
  323.         case 2: // write event
  324.             {
  325.                 // Write character event from port
  326.                 WriteChar(port);
  327.                 break;
  328.             }

  329.         } // end switch

  330.     } // close forever loop

  331.     return 0;
  332. }

  333. //
  334. // start comm watching
  335. //
  336. BOOL CSerialPort::StartMonitoring()
  337. {
  338.     if (!(m_Thread = AfxBeginThread(CommThread, this)))
  339.         return FALSE;
  340.     TRACE("Thread started\n");
  341.     AfxBeginThread(SerialParseThread,this);
  342.     return TRUE;    
  343. }

  344. //
  345. // Restart the comm thread
  346. //
  347. BOOL CSerialPort::RestartMonitoring()
  348. {
  349.     TRACE("Thread resumed\n");
  350.     m_Thread->ResumeThread();
  351.     return TRUE;    
  352. }


  353. //
  354. // Suspend the comm thread
  355. //
  356. BOOL CSerialPort::StopMonitoring()
  357. {
  358.     TRACE("Thread suspended\n");
  359.     m_Thread->SuspendThread();
  360.     return TRUE;    
  361. }


  362. //
  363. // If there is a error, give the right message
  364. //
  365. void CSerialPort::ProcessErrorMessage(char* ErrorText)
  366. {
  367.     char *Temp = new char[200];
  368.     
  369.     LPVOID lpMsgBuf;

  370.     FormatMessage(
  371.         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  372.         NULL,
  373.         GetLastError(),
  374.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  375.         (LPTSTR) &lpMsgBuf,
  376.         0,
  377.         NULL
  378.     );

  379.     sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);
  380.     MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
  381.     printf("%s\r\n",Temp);

  382.     LocalFree(lpMsgBuf);
  383.     delete[] Temp;
  384. }

  385. //
  386. // Write a character.
  387. //
  388. void CSerialPort::WriteChar(CSerialPort* port)
  389. {
  390.     BOOL bWrite = TRUE;
  391.     BOOL bResult = TRUE;

  392.     DWORD BytesSent = 0;

  393.     ResetEvent(port->m_hWriteEvent);

  394.     // Gain ownership of the critical section
  395.     EnterCriticalSection(&port->m_csCommunicationSync);

  396.     if (bWrite)
  397.     {
  398.         // Initailize variables
  399.         port->m_ov.Offset = 0;
  400.         port->m_ov.OffsetHigh = 0;

  401.         // Clear buffer
  402.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
  403.         WORD wLen=5;//strlen((char*)port->m_szWriteBuffer);
  404.         bResult = WriteFile(port->m_hComm,                            // Handle to COMM Port
  405.                             port->m_szWriteBuffer,                    // Pointer to message buffer in calling finction
  406.                             wLen,                                    // Length of message to send
  407.                             &BytesSent,                                // Where to store the number of bytes sent
  408.                             &port->m_ov);                            // Overlapped structure

  409.         // deal with any error codes
  410.         if (!bResult)
  411.         {
  412.             DWORD dwError = GetLastError();
  413.             switch (dwError)
  414.             {
  415.                 case ERROR_IO_PENDING:
  416.                     {
  417.                         // continue to GetOverlappedResults()
  418.                         BytesSent = 0;
  419.                         bWrite = FALSE;
  420.                         break;
  421.                     }
  422.                 default:
  423.                     {
  424.                         // all other error codes
  425.                         port->ProcessErrorMessage("WriteFile()");
  426.                     }
  427.             }
  428.         }
  429.         else
  430.         {
  431.             LeaveCriticalSection(&port->m_csCommunicationSync);
  432.         }
  433.     } // end if(bWrite)

  434.     if (!bWrite)
  435.     {
  436.         bWrite = TRUE;
  437.     
  438.         bResult = GetOverlappedResult(port->m_hComm,    // Handle to COMM port
  439.                                      &port->m_ov,        // Overlapped structure
  440.                                      &BytesSent,        // Stores number of bytes sent
  441.                                      TRUE);             // Wait flag

  442.         LeaveCriticalSection(&port->m_csCommunicationSync);

  443.         // deal with the error code
  444.         if (!bResult)
  445.         {
  446.             port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
  447.         }    
  448.     } // end if (!bWrite)

  449.     // Verify that the data size send equals what we tried to send
  450.     if (BytesSent != strlen((char*)port->m_szWriteBuffer))
  451.     {
  452.         TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));
  453.     }
  454. }

  455. //
  456. // Character received. Inform the owner
  457. //
  458. void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
  459. {
  460.     BOOL bRead = TRUE;
  461.     BOOL bResult = TRUE;
  462.     DWORD dwError = 0;
  463.     DWORD BytesRead = 0;
  464.     unsigned char RXBuff;

  465.     for (;;)
  466.     {
  467.         // Gain ownership of the comm port critical section.
  468.         // This process guarantees no other part of this program
  469.         // is using the port object.
  470.         
  471.         EnterCriticalSection(&port->m_csCommunicationSync);

  472.         // ClearCommError() will update the COMSTAT structure and
  473.         // clear any other errors.
  474.         
  475.         bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

  476.         LeaveCriticalSection(&port->m_csCommunicationSync);

  477.         // start forever loop. I use this type of loop because I
  478.         // do not know at runtime how many loops this will have to
  479.         // run. My solution is to start a forever loop and to
  480.         // break out of it when I have processed all of the
  481.         // data available. Be careful with this approach and
  482.         // be sure your loop will exit.
  483.         // My reasons for this are not as clear in this sample
  484.         // as it is in my production code, but I have found this
  485.         // solutiion to be the most efficient way to do this.
  486.         
  487.         if (comstat.cbInQue == 0)
  488.         {
  489.             // break out when all bytes have been read
  490.             break;
  491.         }
  492.                         
  493.         EnterCriticalSection(&port->m_csCommunicationSync);

  494.         if (bRead)
  495.         {
  496.             bResult = ReadFile(port->m_hComm,        // Handle to COMM port
  497.                              &RXBuff,                // RX Buffer Pointer
  498.                              1,                    // Read one byte
  499.                              &BytesRead,            // Stores number of bytes read
  500.                              &port->m_ov);        // pointer to the m_ov structure
  501.             // deal with the error code
  502.             if (!bResult)
  503.             {
  504.                 switch (dwError = GetLastError())
  505.                 {
  506.                     case ERROR_IO_PENDING:     
  507.                         {
  508.                             // asynchronous i/o is still in progress
  509.                             // Proceed on to GetOverlappedResults();
  510.                             bRead = FALSE;
  511.                             break;
  512.                         }
  513.                     default:
  514.                         {
  515.                             // Another error has occured. Process this error.
  516.                             port->ProcessErrorMessage("ReadFile()");
  517.                             break;
  518.                         }
  519.                 }
  520.             }
  521.             else
  522.             {
  523.                 // ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
  524.                 bRead = TRUE;
  525.             }
  526.         } // close if (bRead)

  527.         if (!bRead)
  528.         {
  529.             bRead = TRUE;
  530.             bResult = GetOverlappedResult(port->m_hComm,    // Handle to COMM port
  531.                                          &port->m_ov,        // Overlapped structure
  532.                                          &BytesRead,        // Stores number of bytes read
  533.                                          TRUE);             // Wait flag

  534.             // deal with the error code
  535.             if (!bResult)
  536.             {
  537.                 port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
  538.             }    
  539.         } // close if (!bRead)
  540.                 
  541.         LeaveCriticalSection(&port->m_csCommunicationSync);

  542.         // notify parent that a byte was received
  543.         ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);

  544.         QueueWrite(rcv_buf,&RXBuff,1);

  545.         //printf("%02x\r\n",RXBuff);
  546.     } // end forever loop

  547. }

  548. //
  549. // Write a string to the port
  550. //
  551. void CSerialPort::WriteToPort(char* string)
  552. {        
  553.     assert(m_hComm != 0);

  554.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
  555.     strcpy(m_szWriteBuffer, string);

  556.     // set event for write
  557.     SetEvent(m_hWriteEvent);
  558. }

  559. void CSerialPort::WriteToPort(char *string, WORD wLen)
  560. {
  561.     assert(m_hComm != 0);

  562.     memset(m_szWriteBuffer, 0, wLen+1);
  563.     memcpy(m_szWriteBuffer,string,wLen);
  564.     // set event for write
  565.     SetEvent(m_hWriteEvent);
  566. }


  567. //
  568. // Return the device control block
  569. //
  570. DCB CSerialPort::GetDCB()
  571. {
  572.     return m_dcb;
  573. }

  574. //
  575. // Return the communication event masks
  576. //
  577. DWORD CSerialPort::GetCommEvents()
  578. {
  579.     return m_dwCommEvents;
  580. }

  581. //
  582. // Return the output buffer size
  583. //
  584. DWORD CSerialPort::GetWriteBufferSize()
  585. {
  586.     return m_nWriteBufferSize;
  587. }






  588. UINT CSerialPort::SerialParseThread(void *param)
  589. {
  590.     BYTE byrecv[100];
  591.     while (1)
  592.     {
  593.         DWORD dwLen;
  594.         dwLen=QueueNData(rcv_buf,1);
  595.         if(dwLen>=5)
  596.         {
  597.         
  598.             for (int ilp=0;ilp<dwLen;ilp++)
  599.             {
  600.                 if ( QueueRead(byrecv + ilp ,rcv_buf,1)!=QUEUE_OK )
  601.                 {
  602.                     break;
  603.                 }
  604.                 printf("%02x\t",byrecv[ilp]);
  605.             }
  606.             printf("\r\n");

  607.             QueueFlush(rcv_buf);
  608.             
  609.         }
  610.         Sleep(1);
  611.     }

  612.     return TRUE;
  613. }

  614. int CSerialPort::EnumAllComPort(CString *pStr)
  615. {
  616.     int i = 0;
  617.     CHAR Name[25];
  618.     UCHAR szPortName[25];
  619.     LONG Status;
  620.     DWORD dwIndex = 0;
  621.     DWORD dwName;
  622.     DWORD dwSizeofPortName;
  623.     DWORD Type;
  624.     HKEY hKey;
  625.     LPCTSTR data_Set = "HARDWARE\\DEVICEMAP\\SERIALCOMM\\";
  626.     long ret0 = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey));

  627.     do
  628.     {
  629.             dwName = sizeof(Name);
  630.             dwSizeofPortName = sizeof(szPortName);
  631.             Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type,
  632.                     szPortName, &dwSizeofPortName);

  633.             if ((Status == ERROR_SUCCESS) || (Status == ERROR_MORE_DATA))
  634.             {
  635.                     pStr[i] = CString(szPortName); // 串口字符串保存
  636.                     i++;// 串口计数
  637.             }
  638.     }
  639.     while ((Status == ERROR_SUCCESS) || (Status == ERROR_MORE_DATA));

  640.     RegCloseKey(hKey);
  641.     return i;

  642. }

  643. bool CSerialPort::OpenLastPort(CWnd* pPortOwner)
  644. {

  645.     CString strCom[5];
  646.     //InitSlider(1,80,10);
  647.     int exitingSerialNumber=EnumAllComPort(strCom);
  648.     
  649.     int ilpLatch;
  650.     if ( exitingSerialNumber>0 )
  651.     {
  652.     
  653.             DWORD dwComPort,dwMaxPortNumber=0;    
  654.             char szTmp[10];
  655.             
  656.             for(int i=0;i<exitingSerialNumber;i++)
  657.             {
  658.                 printf("%s\r\n",strCom[i]);
  659.                 strcpy(szTmp,strCom[i]);
  660.                 dwComPort=(DWORD)atoi(szTmp+3);
  661.                 
  662.                 if (dwMaxPortNumber<dwComPort)
  663.                 {
  664.                     dwMaxPortNumber=dwComPort;//锁存数值最大的串口号
  665.                     ilpLatch=i;
  666.                 
  667.                 }
  668.             
  669.             }
  670.             if(    InitPort(pPortOwner,dwMaxPortNumber, 115200) )
  671.             {
  672.                     printf("use %s\r\n",strCom[ilpLatch]);
  673.                     StartMonitoring();
  674.                     m_bSerialPortIsOpen=TRUE;
  675.             }
  676.             else
  677.             {
  678.                 printf("open %s error\r\n",strCom[ilpLatch]);
  679.             }
  680.     }
  681.     else
  682.     {
  683.         printf("no valid com exit\r\n");
  684.     }
  685.     
  686.     return TRUE;


  687. }
h文件

点击(此处)折叠或打开

  1. /*
  2. **    FILENAME            CSerialPort.h
  3. **
  4. **    PURPOSE                This class can read, write and watch one serial port.
  5. **                        It sends messages to its owner when something happends on the port
  6. **                        The class creates a thread for reading and writing so the main
  7. **                        program is not blocked.
  8. **
  9. **    CREATION DATE        15-09-1997
  10. **    LAST MODIFICATION    12-11-1997
  11. **
  12. **    AUTHOR                Remon Spekreijse
  13. **
  14. **
  15. */

  16. #ifndef __SERIALPORT_H__
  17. #define __SERIALPORT_H__

  18. #define WM_COMM_BREAK_DETECTED        WM_USER+1    // A break was detected on input.
  19. #define WM_COMM_CTS_DETECTED        WM_USER+2    // The CTS (clear-to-send) signal changed state.
  20. #define WM_COMM_DSR_DETECTED        WM_USER+3    // The DSR (data-set-ready) signal changed state.
  21. #define WM_COMM_ERR_DETECTED        WM_USER+4    // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
  22. #define WM_COMM_RING_DETECTED        WM_USER+5    // A ring indicator was detected.
  23. #define WM_COMM_RLSD_DETECTED        WM_USER+6    // The RLSD (receive-line-signal-detect) signal changed state.
  24. #define WM_COMM_RXCHAR                WM_USER+7    // A character was received and placed in the input buffer.
  25. #define WM_COMM_RXFLAG_DETECTED        WM_USER+8    // The event character was received and placed in the input buffer.
  26. #define WM_COMM_TXEMPTY_DETECTED    WM_USER+9    // The last character in the output buffer was sent.

  27. class CSerialPort
  28. {                                                        
  29. public:
  30.     bool OpenLastPort(CWnd* pPortOwner);
  31.     int EnumAllComPort(CString *pStr);
  32.     static UINT SerialParseThread(void *param);
  33.     BOOL m_bSerialPortIsOpen;
  34.     void WriteToPort(char* string,WORD wLen);
  35.     // contruction and destruction
  36.     CSerialPort();
  37.     virtual        ~CSerialPort();

  38.     // port initialisation                                            
  39.     BOOL        InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512);

  40.     // start/stop comm watching
  41.     BOOL        StartMonitoring();
  42.     BOOL        RestartMonitoring();
  43.     BOOL        StopMonitoring();

  44.     DWORD        GetWriteBufferSize();
  45.     DWORD        GetCommEvents();
  46.     DCB            GetDCB();

  47.     void        WriteToPort(char* string);

  48. protected:
  49.     // protected memberfunctions
  50.     void        ProcessErrorMessage(char* ErrorText);
  51.     static UINT    CommThread(LPVOID pParam);
  52.     static void    ReceiveChar(CSerialPort* port, COMSTAT comstat);
  53.     static void    WriteChar(CSerialPort* port);

  54.     // thread
  55.     CWinThread*            m_Thread;

  56.     // synchronisation objects
  57.     CRITICAL_SECTION    m_csCommunicationSync;
  58.     BOOL                m_bThreadAlive;

  59.     // handles
  60.     HANDLE                m_hShutdownEvent;
  61.     HANDLE                m_hComm;
  62.     HANDLE                m_hWriteEvent;

  63.     // Event array.
  64.     // One element is used for each event. There are two event handles for each port.
  65.     // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).
  66.     // There is a general shutdown when the port is closed.
  67.     HANDLE                m_hEventArray[3];

  68.     // structures
  69.     OVERLAPPED            m_ov;
  70.     COMMTIMEOUTS        m_CommTimeouts;
  71.     DCB                    m_dcb;

  72.     // owner window
  73.     CWnd*                m_pOwner;

  74.     // misc
  75.     UINT                m_nPortNr;
  76.     char*                m_szWriteBuffer;
  77.     DWORD                m_dwCommEvents;
  78.     DWORD                m_nWriteBufferSize;
  79. };

  80. #endif __SERIALPORT_H__

阅读(1480) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~