author: 零贰
title: 很方便的串口类 CComAccess
date: 2009-01-20 12:49:38
category: [编程代码]
tags: [VC,串口,代码,源码]
feature: http://image.cool02.com/blogimages/code.jpg
<p> 网上这方面三方类多如牛毛,真不知道用哪个好,不过不管用哪个,一定要在严格检查完善后再使用,不然给以后通信埋下隐患,只会让以后的调试会更痛苦!<!--more-->
</p> <p>ComAccess.h</p> <pre><ol><li>////////////////////////////////////////////////////////////////////// <li>// <li>// ComAccess.h: interface for the CComAccess class. <li>// <li>////////////////////////////////////////////////////////////////////// <li> <li>#if !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_) <li>#define AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_ <li> <li>#if _MSC_VER > 1000 <li>#pragma once <li>#endif // _MSC_VER > 1000 <li> <li> <li>class CComAccess <li>{ <li>private: <li> <li> HANDLE m_hCom; // Device handle <li> <li> OVERLAPPED m_ov; // A structure that contains informations which are <li> // used for asynchronous input and output operations <li> <li> TCHAR m_lpszErrorMessage[256]; <li> <li>public: <li> <li> CComAccess(); <li> CComAccess(LPCSTR lpszPortNum); <li> <li> ~CComAccess(); <li> // For more definitions see <winbase.h> <li> BOOL Open(LPCSTR lpszPortNum = "com1", <li> DWORD dwBaudRate = CBR_9600, <li> BYTE byParity = NOPARITY, <li> BYTE byStopBits = ONESTOPBIT, <li> BYTE byByteSize = 8); <li> <li> VOID Close(); <li> <li> DWORD WriteData(LPCVOID pdata, DWORD len); <li> DWORD ReadData(LPVOID pdest, DWORD len, DWORD dwMaxWait = 500); <li> <li> LPSTR GetErrorMessage(VOID) { return m_lpszErrorMessage; } <li> <li>private: <li> <li> VOID ErrorToString(LPCSTR lpszMessage); <li> <li> BOOL IsNT(VOID); <li>}; <li> <li>#endif // !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_) </li></ol></pre>
<p>ComAccess.cpp</p>
<ol><li>////////////////////////////////////////////////////////////////////// <li>// <li>// ComAccess.cpp: implementation of the CComAccess class. <li>// <li>////////////////////////////////////////////////////////////////////// <li> <li>#include "stdafx.h" <li>#include "ComAccess.h" <li> <li>#ifdef _DEBUG <li>#undef THIS_FILE <li>static char THIS_FILE[]=__FILE__; <li>#define new DEBUG_NEW <li>#endif <li> <li>////////////////////////////////////////////////////////////////////// <li>// Construction/Destruction <li>////////////////////////////////////////////////////////////////////// <li> <li>CComAccess::CComAccess(VOID) <li>{ <li> m_hCom = 0; <li> m_lpszErrorMessage[0] = '0'; <li> ZeroMemory(&m_ov, sizeof(m_ov)); <li>} <li> <li> <li>CComAccess::CComAccess(LPCSTR lpszPortNum) <li>{ <li> CComAccess::CComAccess(); <li> CComAccess::Open(lpszPortNum); <li>} <li> <li>CComAccess::~CComAccess() <li>{ <li> Close(); <li>} <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: Open(LPCSTR lpszPortNum, <li>// DWORD dwBaudRate, <li>// BYTE byParity, <li>// BYTE byStopBits, <li>// BYTE byByteSize) <li>// <li>// Return value: BOOL TRUE or FALSE <li>// <li> <li>BOOL CComAccess::Open(LPCSTR lpszPortNum, <li> DWORD dwBaudRate, <li> BYTE byParity, <li> BYTE byStopBits, <li> BYTE byByteSize) <li>{ <li> DCB dcb; // structure that defines the control setting for a serial communications device <li> BOOL bSuccess; <li> <li> m_hCom = CreateFile(lpszPortNum, // pointer to name of the file <li> GENERIC_READ|GENERIC_WRITE, // access mode <li> 0, // comm devices must be opened w/exclusive-access <li> NULL, // no security attributs <li> OPEN_EXISTING, // comm devices must use OPEN_EXISTING <li> FILE_FLAG_OVERLAPPED, // overlapped I/O <li> NULL); // hTemplate must be NULL for comm devices <li> <li> if ( m_hCom == INVALID_HANDLE_VALUE ) <li> { <li> // handle the error <li> CComAccess::ErrorToString("Open(): CreateFile() failed, invalid handle value"); <li> <li> return FALSE; <li> } <li> <li> // <li> // Omit the call to SetupComm to use the default queue sizes. <li> // Get the current configuration. <li> // <li> <li> bSuccess = GetCommState(m_hCom, &dcb); <li> <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CComAccess::ErrorToString("Open(): GetCommState() failed"); <li> CComAccess::Close(); <li> <li> return FALSE; <li> } <li> <li> // <li> // Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit are default parameters <li> // <li> <li> dcb.BaudRate = dwBaudRate; <li> dcb.ByteSize = byByteSize; <li> dcb.Parity = byParity; <li> dcb.StopBits = byStopBits; <li> <li> bSuccess = SetCommState(m_hCom, &dcb); <li> <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CComAccess::ErrorToString("Open(): SetCommState() failed"); <li> CComAccess::Close(); <li> <li> return FALSE; <li> } <li> <li> return TRUE; <li>} <li> <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: Close(VOID) <li>// <li>// Return value: VOID <li>// <li> <li>VOID CComAccess::Close() <li>{ <li> if ( m_hCom > 0 ) <li> { <li> CloseHandle(m_hCom); <li> } <li> <li> m_hCom = 0; <li>} <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: WriteData(LPCVOID pdata, <li>// DWORD len) <li>// <li>// Return value: DWORD -1 failed, above, num written bytes <li>// <li> <li>DWORD CComAccess::WriteData(LPCVOID pdata, <li> DWORD len) <li>{ <li> BOOL bSuccess; <li> DWORD written = 0; <li> <li> if ( len < 1 ) <li> return(0); <li> <li> // create event for overlapped I/O <li> m_ov.hEvent = CreateEvent(NULL, // pointer to security attributes <li> FALSE, // flag for manual-reset event <li> FALSE, // flag for initial state <li> ""); // pointer to event-object name <li> <li> if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) <li> { <li> // Handle the error. <li> CComAccess::ErrorToString("WriteData(): CreateEvent() failed"); <li> <li> return(-1); <li> } <li> <li> bSuccess = WriteFile(m_hCom, // handle to file to write to <li> pdata, // pointer to data to write to file <li> len, // number of bytes to write <li> &written, // pointer to number of bytes written <li> &m_ov); // pointer to structure needed for overlapped I/O <li> <li> <li> if ( CComAccess::IsNT() ) <li> { <li> bSuccess = GetOverlappedResult(m_hCom, &m_ov, &written, TRUE); <li> <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed"); <li> <li> return(-1); <li> } <li> } <li> else <li> if ( len != written ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("WriteData(): WriteFile() failed"); <li> <li> return(-1); <li> } <li> <li> CloseHandle(m_ov.hEvent); <li> <li> return written; <li>} <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: ReadData(LPVOID pdest, <li>// DWORD len, <li>// DWORD dwMaxWait) <li>// <li>// Return value: DWORD -1 failed, above, num read bytes <li>// <li> <li>DWORD CComAccess::ReadData(LPVOID pdest, <li> DWORD len, <li> DWORD dwMaxWait) <li>{ <li> BOOL bSuccess; <li> DWORD result = 0, <li> read = 0, // num read bytes <li> mask = 0; // a 32-bit variable that receives a mask <li> // indicating the type of event that occurred <li> <li> if ( len < 1 ) return(0); <li> <li> // create event for overlapped I/O <li> <li> m_ov.hEvent = CreateEvent(NULL, // pointer to security attributes <li> FALSE, // flag for manual-reset event <li> FALSE, // flag for initial state <li> ""); // pointer to event-object name <li> <li> if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) <li> { <li> // Handle the error. <li> CComAccess::ErrorToString("ReadData(): CreateEvent() failed"); <li> <li> return(-1); <li> } <li> <li> // Specify here the event to be enabled <li> <li> bSuccess = SetCommMask(m_hCom, EV_RXCHAR); <li> <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("ReadData(): SetCommMask() failed"); <li> <li> return(-1); <li> } <li> <li> <li> // WaitForSingleObject <li> <li> bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov); <li> <li> if ( ! bSuccess ) <li> { <li> int err = GetLastError(); <li> <li> if ( err == ERROR_IO_PENDING) <li> { <li> result = WaitForSingleObject(m_ov.hEvent, dwMaxWait); //wait dwMaxWait <li> // milli seconds before returning <li> if ( result == WAIT_FAILED ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("ReadData(): WaitForSingleObject() failed"); <li> <li> return(-1); <li> } <li> } <li> } <li> <li> // The specified event occured? <li> <li> if ( mask & EV_RXCHAR) <li> { <li> bSuccess = ReadFile(m_hCom, // handle of file to read <li> pdest, // address of buffer that receives data <li> len, // number of bytes to read <li> &read, // address of number of bytes read <li> &m_ov); // address of structure for data <li> <li> if ( CComAccess::IsNT() ) <li> { <li> bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE); <li> <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed"); <li> <li> return(-1); <li> } <li> } <li> else <li> if ( ! bSuccess ) <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> CComAccess::ErrorToString("ReadData(): ReadFile() failed"); <li> <li> return(-1); <li> } <li> } <li> else <li> { <li> // Handle the error. <li> CloseHandle(m_ov.hEvent); <li> wsprintf(m_lpszErrorMessage, "Error ReadData(): No EV_RXCHAR occuredn"); <li> <li> return(-1); <li> } <li> <li> CloseHandle(m_ov.hEvent); <li> <li> return read; <li>} <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: ErrorToString(LPCSTR lpszMessage) <li>// <li>// Return value: VOID <li>// <li> <li>VOID CComAccess::ErrorToString(LPCSTR lpszMessage) <li>{ <li> LPVOID lpMessageBuffer; <li> DWORD error = GetLastError(); <li> <li> FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | <li> FORMAT_MESSAGE_FROM_SYSTEM, // source and processing options <li> NULL, // pointer to message source <li> error, // requested message identifie <li> MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language. <li> (LPTSTR) &lpMessageBuffer, // pointer to message buffer <li> 0, // maximum size of message buffer <li> NULL); // address of array of message inserts <li> <li> // and copy it in our error string <li> wsprintf(m_lpszErrorMessage,"%s: (%d) %sn", lpszMessage, error, lpMessageBuffer); <li> <li> LocalFree(lpMessageBuffer); <li>} <li> <li>//////////////////////////////////////////////////////////////////////////////////////// <li>// <li>// Function: IsNT(VOID) <li>// <li>// Return value: BOOL True or False <li>// <li> <li>BOOL CComAccess::IsNT(VOID) <li>{ <li> OSVERSIONINFO osvi; <li> <li> osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); <li> <li> GetVersionEx(&osvi); <li> <li> if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) <li> { <li> return TRUE; <li> } <li> else <li> { <li> return FALSE; <li> } <li>} </li></ol>