零贰'Blog

零贰'Blog - 记录日常点点滴滴..........

很方便的串口类 CComAccess

VC串口代码源码

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

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