很方便的串口类 CComAccess

       网上这方面三方类多如牛毛,真不知道用哪个好,不过不管用哪个,一定要在严格检查完善后再使用,不然给以后通信埋下隐患,只会让以后的调试会更痛苦!

ComAccess.h

  1. ////////////////////////////////////////////////////////////////////// 
  2. // 
  3. // ComAccess.h: interface for the CComAccess class. 
  4. // 
  5. ////////////////////////////////////////////////////////////////////// 
  6.  
  7. #if !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_) 
  8. #define AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_ 
  9.  
  10. #if _MSC_VER > 1000 
  11. #pragma once 
  12. #endif // _MSC_VER > 1000 
  13.  
  14.  
  15. class CComAccess  
  16. { 
  17. private: 
  18.  
  19.     HANDLE      m_hCom; // Device handle  
  20.  
  21.     OVERLAPPED  m_ov;   // A structure that contains informations which are 
  22.                         // used for asynchronous input and output operations 
  23.  
  24.     TCHAR       m_lpszErrorMessage[256]; 
  25.  
  26. public: 
  27.  
  28.     CComAccess(); 
  29.     CComAccess(LPCSTR lpszPortNum); 
  30.  
  31.     ~CComAccess(); 
  32.                                     // For more definitions see <winbase.h> 
  33.     BOOL    Open(LPCSTR lpszPortNum = "com1", 
  34.                  DWORD  dwBaudRate  = CBR_9600,  
  35.                  BYTE   byParity    = NOPARITY, 
  36.                  BYTE   byStopBits  = ONESTOPBIT, 
  37.                  BYTE   byByteSize  = 8); 
  38.  
  39.     VOID    Close(); 
  40.      
  41.     DWORD   WriteData(LPCVOID pdata, DWORD len); 
  42.     DWORD   ReadData(LPVOID  pdest, DWORD len, DWORD dwMaxWait = 500); 
  43.  
  44.     LPSTR   GetErrorMessage(VOID) { return m_lpszErrorMessage; } 
  45.  
  46. private: 
  47.  
  48.     VOID    ErrorToString(LPCSTR lpszMessage); 
  49.  
  50.     BOOL    IsNT(VOID); 
  51. }; 
  52.  
  53. #endif // !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_)

ComAccess.cpp

  1. ////////////////////////////////////////////////////////////////////// 
  2. // 
  3. // ComAccess.cpp: implementation of the CComAccess class. 
  4. // 
  5. ////////////////////////////////////////////////////////////////////// 
  6.  
  7. #include "stdafx.h" 
  8. #include "ComAccess.h" 
  9.  
  10. #ifdef _DEBUG 
  11. #undef THIS_FILE 
  12. static char THIS_FILE[]=__FILE__; 
  13. #define new DEBUG_NEW 
  14. #endif 
  15.  
  16. ////////////////////////////////////////////////////////////////////// 
  17. // Construction/Destruction 
  18. ////////////////////////////////////////////////////////////////////// 
  19.  
  20. CComAccess::CComAccess(VOID) 
  21. { 
  22.     m_hCom = 0; 
  23.     m_lpszErrorMessage[0] = '\0'; 
  24.     ZeroMemory(&m_ov, sizeof(m_ov)); 
  25. } 
  26.  
  27.  
  28. CComAccess::CComAccess(LPCSTR lpszPortNum) 
  29. {  
  30.     CComAccess::CComAccess(); 
  31.     CComAccess::Open(lpszPortNum);  
  32. } 
  33.  
  34. CComAccess::~CComAccess() 
  35. { 
  36.     Close(); 
  37. } 
  38.  
  39. //////////////////////////////////////////////////////////////////////////////////////// 
  40. //  
  41. //  Function:      Open(LPCSTR lpszPortNum, 
  42. //                      DWORD  dwBaudRate,  
  43. //                      BYTE   byParity, 
  44. //                      BYTE   byStopBits, 
  45. //                      BYTE   byByteSize) 
  46. // 
  47. //  Return value:  BOOL TRUE or FALSE 
  48. // 
  49.  
  50. BOOL CComAccess::Open(LPCSTR lpszPortNum,  
  51.                      DWORD  dwBaudRate,  
  52.                      BYTE   byParity, 
  53.                      BYTE   byStopBits, 
  54.                      BYTE   byByteSize) 
  55. { 
  56.     DCB  dcb; // structure that defines the control setting for a serial communications device 
  57.     BOOL bSuccess; 
  58.      
  59.     m_hCom = CreateFile(lpszPortNum,           // pointer to name of the file 
  60.                         GENERIC_READ|GENERIC_WRITE, // access mode 
  61.                         0,                     // comm devices must be opened w/exclusive-access  
  62.                         NULL,                  // no security attributs  
  63.                         OPEN_EXISTING,         // comm devices must use OPEN_EXISTING  
  64.                         FILE_FLAG_OVERLAPPED,  // overlapped I/O 
  65.                         NULL);                 // hTemplate must be NULL for comm devices  
  66.  
  67.     if ( m_hCom == INVALID_HANDLE_VALUE )  
  68.     { 
  69.         // handle the error 
  70.         CComAccess::ErrorToString("Open(): CreateFile() failed, invalid handle value"); 
  71.          
  72.         return FALSE; 
  73.     } 
  74.  
  75.     // 
  76.     // Omit the call to SetupComm to use the default queue sizes. 
  77.     // Get the current configuration. 
  78.     // 
  79.   
  80.     bSuccess = GetCommState(m_hCom, &dcb); 
  81.  
  82.     if ( ! bSuccess )  
  83.     { 
  84.         // Handle the error. 
  85.         CComAccess::ErrorToString("Open(): GetCommState() failed"); 
  86.         CComAccess::Close(); 
  87.  
  88.         return FALSE; 
  89.     } 
  90.  
  91.     // 
  92.     // Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit are default parameters 
  93.     // 
  94.  
  95.     dcb.BaudRate = dwBaudRate; 
  96.     dcb.ByteSize = byByteSize; 
  97.     dcb.Parity   = byParity; 
  98.     dcb.StopBits = byStopBits; 
  99.      
  100.     bSuccess = SetCommState(m_hCom, &dcb); 
  101.  
  102.     if ( ! bSuccess )  
  103.     { 
  104.         // Handle the error.  
  105.         CComAccess::ErrorToString("Open(): SetCommState() failed"); 
  106.         CComAccess::Close(); 
  107.  
  108.         return FALSE; 
  109.     } 
  110.  
  111.     return TRUE; 
  112. } 
  113.  
  114.  
  115. //////////////////////////////////////////////////////////////////////////////////////// 
  116. //  
  117. //  Function:      Close(VOID) 
  118. // 
  119. //  Return value:  VOID 
  120. // 
  121.  
  122. VOID CComAccess::Close() 
  123. { 
  124.     if ( m_hCom > 0 ) 
  125.     { 
  126.         CloseHandle(m_hCom); 
  127.     } 
  128.  
  129.     m_hCom = 0;  
  130. } 
  131.  
  132. //////////////////////////////////////////////////////////////////////////////////////// 
  133. //  
  134. //  Function:     WriteData(LPCVOID pdata,  
  135. //                          DWORD   len) 
  136. // 
  137. //  Return value:  DWORD -1 failed, above, num written bytes 
  138. // 
  139.  
  140. DWORD CComAccess::WriteData(LPCVOID pdata,  
  141.                            DWORD   len) 
  142. { 
  143.     BOOL  bSuccess; 
  144.     DWORD written = 0; 
  145.  
  146.     if ( len < 1 ) 
  147.         return(0); 
  148.  
  149.     // create event for overlapped I/O 
  150.     m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes  
  151.                               FALSE,   // flag for manual-reset event  
  152.                               FALSE,  // flag for initial state  
  153.                               "");    // pointer to event-object name  
  154.  
  155.     if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) 
  156.     { 
  157.         // Handle the error. 
  158.         CComAccess::ErrorToString("WriteData(): CreateEvent() failed"); 
  159.        
  160.         return(-1); 
  161.     } 
  162.  
  163.     bSuccess = WriteFile(m_hCom,   // handle to file to write to   
  164.                          pdata,    // pointer to data to write to file  
  165.                          len,      // number of bytes to write  
  166.                          &written, // pointer to number of bytes written  
  167.                          &m_ov);   // pointer to structure needed for overlapped I/O 
  168.  
  169.  
  170.     if ( CComAccess::IsNT() ) 
  171.     { 
  172.         bSuccess = GetOverlappedResult(m_hCom, &m_ov, &written, TRUE); 
  173.  
  174.         if ( ! bSuccess ) 
  175.         { 
  176.             // Handle the error. 
  177.             CloseHandle(m_ov.hEvent); 
  178.             CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed"); 
  179.  
  180.             return(-1); 
  181.         } 
  182.     } 
  183.     else
  184.     if ( len != written ) 
  185.     { 
  186.         // Handle the error. 
  187.         CloseHandle(m_ov.hEvent); 
  188.         CComAccess::ErrorToString("WriteData(): WriteFile() failed"); 
  189.  
  190.         return(-1); 
  191.     } 
  192.  
  193.     CloseHandle(m_ov.hEvent); 
  194.  
  195.     return written; 
  196. } 
  197.  
  198. //////////////////////////////////////////////////////////////////////////////////////// 
  199. //  
  200. //  Function:      ReadData(LPVOID pdest,  
  201. //                          DWORD  len,  
  202. //                          DWORD  dwMaxWait) 
  203. // 
  204. //  Return value:  DWORD -1 failed, above, num read bytes        
  205. // 
  206.  
  207. DWORD CComAccess::ReadData(LPVOID pdest,  
  208.                           DWORD  len,  
  209.                           DWORD  dwMaxWait) 
  210. { 
  211.     BOOL  bSuccess; 
  212.     DWORD result = 0, 
  213.           read   = 0, // num read bytes 
  214.           mask   = 0; // a 32-bit variable that receives a mask  
  215.                       // indicating the type of event that occurred 
  216.  
  217.     if ( len < 1 ) return(0); 
  218.  
  219.     // create event for overlapped I/O 
  220.  
  221.     m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes  
  222.                               FALSE,   // flag for manual-reset event  
  223.                               FALSE,  // flag for initial state  
  224.                               "");    // pointer to event-object name  
  225.  
  226.     if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) 
  227.     { 
  228.         // Handle the error. 
  229.         CComAccess::ErrorToString("ReadData(): CreateEvent() failed"); 
  230.        
  231.         return(-1); 
  232.     } 
  233.  
  234.     // Specify here the event to be enabled 
  235.  
  236.     bSuccess = SetCommMask(m_hCom, EV_RXCHAR); 
  237.  
  238.     if ( ! bSuccess ) 
  239.     { 
  240.         // Handle the error. 
  241.         CloseHandle(m_ov.hEvent); 
  242.         CComAccess::ErrorToString("ReadData(): SetCommMask() failed"); 
  243.        
  244.         return(-1); 
  245.     } 
  246.  
  247.      
  248.     // WaitForSingleObject 
  249.  
  250.     bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov); 
  251.  
  252.     if ( ! bSuccess ) 
  253.     { 
  254.         int err = GetLastError(); 
  255.  
  256.         if ( err == ERROR_IO_PENDING) 
  257.         { 
  258.             result = WaitForSingleObject(m_ov.hEvent, dwMaxWait);  //wait dwMaxWait 
  259.                                                 // milli seconds before returning 
  260.             if ( result == WAIT_FAILED ) 
  261.             { 
  262.                 // Handle the error. 
  263.                 CloseHandle(m_ov.hEvent); 
  264.                 CComAccess::ErrorToString("ReadData(): WaitForSingleObject() failed"); 
  265.        
  266.                 return(-1); 
  267.             } 
  268.         } 
  269.     } 
  270.      
  271.     // The specified event occured? 
  272.      
  273.     if ( mask & EV_RXCHAR)  
  274.     { 
  275.         bSuccess = ReadFile(m_hCom, // handle of file to read  
  276.                             pdest,  // address of buffer that receives data  
  277.                             len,    // number of bytes to read  
  278.                             &read,  // address of number of bytes read  
  279.                             &m_ov); // address of structure for data  
  280.  
  281.         if ( CComAccess::IsNT() ) 
  282.         { 
  283.             bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE); 
  284.  
  285.             if ( ! bSuccess ) 
  286.             { 
  287.                 // Handle the error. 
  288.                 CloseHandle(m_ov.hEvent); 
  289.                 CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed"); 
  290.  
  291.                 return(-1); 
  292.             } 
  293.         } 
  294.         else
  295.         if ( ! bSuccess ) 
  296.         { 
  297.             // Handle the error. 
  298.             CloseHandle(m_ov.hEvent); 
  299.             CComAccess::ErrorToString("ReadData(): ReadFile() failed"); 
  300.  
  301.             return(-1); 
  302.         } 
  303.     } 
  304.     else
  305.     { 
  306.         // Handle the error. 
  307.         CloseHandle(m_ov.hEvent); 
  308.         wsprintf(m_lpszErrorMessage, "Error ReadData(): No EV_RXCHAR occured\n"); 
  309.  
  310.         return(-1); 
  311.     } 
  312.      
  313.     CloseHandle(m_ov.hEvent); 
  314.      
  315.     return read; 
  316. } 
  317.  
  318. //////////////////////////////////////////////////////////////////////////////////////// 
  319. //  
  320. //  Function:      ErrorToString(LPCSTR lpszMessage) 
  321. // 
  322. //  Return value:  VOID 
  323. // 
  324.  
  325. VOID CComAccess::ErrorToString(LPCSTR lpszMessage) 
  326. { 
  327.     LPVOID lpMessageBuffer; 
  328.     DWORD  error = GetLastError(); 
  329.  
  330.     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  331.                   FORMAT_MESSAGE_FROM_SYSTEM,      // source and processing options 
  332.                   NULL,                            // pointer to message source 
  333.                   error,                           // requested message identifie 
  334.                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language. 
  335.                   (LPTSTR) &lpMessageBuffer,       // pointer to message buffer 
  336.                   0,                               // maximum size of message buffer 
  337.                   NULL);                           // address of array of message inserts  
  338.  
  339.     // and copy it in our error string 
  340.     wsprintf(m_lpszErrorMessage,"%s: (%d) %s\n", lpszMessage, error, lpMessageBuffer); 
  341.  
  342.     LocalFree(lpMessageBuffer); 
  343. } 
  344.  
  345. //////////////////////////////////////////////////////////////////////////////////////// 
  346. //  
  347. //  Function:     IsNT(VOID) 
  348. // 
  349. //  Return value: BOOL True or False 
  350. // 
  351.  
  352. BOOL CComAccess::IsNT(VOID) 
  353. { 
  354.     OSVERSIONINFO osvi; 
  355.      
  356.     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
  357.      
  358.     GetVersionEx(&osvi); 
  359.  
  360.     if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)  
  361.     { 
  362.         return TRUE; 
  363.     } 
  364.     else
  365.     { 
  366.         return FALSE; 
  367.     } 
  368. }