Quellcode durchsuchen

串口通信类示例;

sat23 vor 4 Jahren
Ursprung
Commit
1c341e03c5

+ 20 - 0
Serail-Demo/Demo.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo\Demo.vcproj", "{69DDDE72-42F8-4F78-BF71-D70E22CE0675}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{69DDDE72-42F8-4F78-BF71-D70E22CE0675}.Debug|Win32.ActiveCfg = Debug|Win32
+		{69DDDE72-42F8-4F78-BF71-D70E22CE0675}.Debug|Win32.Build.0 = Debug|Win32
+		{69DDDE72-42F8-4F78-BF71-D70E22CE0675}.Release|Win32.ActiveCfg = Release|Win32
+		{69DDDE72-42F8-4F78-BF71-D70E22CE0675}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 37 - 0
Serail-Demo/Demo/Demo.cpp

@@ -0,0 +1,37 @@
+// Demo.cpp : 定义控制台应用程序的入口点。
+//
+
+#include "stdafx.h"
+#include "Demo.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 唯一的应用程序对象
+
+CWinApp theApp;
+
+using namespace std;
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		// TODO: 在此处为应用程序的行为编写代码。
+		CBaseSerial sb;
+		sb.Open(23, _T("baud=115200 parity=N data=8 stop=1") );
+	}
+
+	return nRetCode;
+}

+ 3 - 0
Serail-Demo/Demo/Demo.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#include "resource.h"

+ 69 - 0
Serail-Demo/Demo/Demo.rc

@@ -0,0 +1,69 @@
+//Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#include "afxres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+   IDS_APP_TITLE       "Demo"
+END
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED

+ 247 - 0
Serail-Demo/Demo/Demo.vcproj

@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Demo"
+	ProjectGUID="{69DDDE72-42F8-4F78-BF71-D70E22CE0675}"
+	RootNamespace="Demo"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Demo.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Serial.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Demo.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Serial.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\Demo.rc"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 40 - 0
Serail-Demo/Demo/ReadMe.txt

@@ -0,0 +1,40 @@
+========================================================================
+    控制台应用程序:Demo 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 Demo 应用程序。
+
+本文件概要介绍组成 Demo 应用程序的
+的每个文件的内容。
+
+
+Demo.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+Demo.cpp
+    这是主应用程序源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+Demo.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 Demo.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 17 - 0
Serail-Demo/Demo/Resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Demo.rc
+//
+
+#define IDS_APP_TITLE			103
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE	101
+#define _APS_NEXT_COMMAND_VALUE		40001
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#endif
+#endif

+ 349 - 0
Serail-Demo/Demo/Serial.cpp

@@ -0,0 +1,349 @@
+#include "stdafx.h"
+#include "Serial.h"
+
+DCB *CBaseSerial::GetState()
+{
+	return IsOpen() && ::GetCommState(_hCommHandle, &_DCB) == TRUE ? &_DCB : NULL;
+}
+
+bool CBaseSerial::SetState(DCB *pdcb /*= NULL*/)
+{
+	return IsOpen() ? ::SetCommState(_hCommHandle, pdcb == NULL ? &_DCB : pdcb) == TRUE : false;
+}
+
+bool CBaseSerial::SetState(TCHAR *lpszSetStr /* = _T("baud=115200 parity=N data=8 stop=1") */)
+{
+	if (lpszSetStr && lpszSetStr[0] != '\0' && IsOpen())
+	{
+		if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
+			return false;
+		// COMx[:][baud=b][parity=p][data=d][stop=s][to={on|off}][xon={on|off}][odsr={on|off}][octs={on|off}][dtr={on|off|hs}][rts={on|off|hs|tg}][idsr={on|off}]
+		if (::BuildCommDCB(lpszSetStr, &_DCB) != TRUE)
+			return false;
+		return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
+	}
+
+	return false;
+}
+
+bool CBaseSerial::SetState(DWORD dwBaudRate, DWORD dwByteSize /* = 8 */, DWORD dwParity /* = NOPARITY */, DWORD dwStopBits /* = ONESTOPBIT */)
+{
+	if (!IsOpen()) return false;
+
+	if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
+		return false;
+
+	_DCB.BaudRate = dwBaudRate;
+	_DCB.ByteSize = (BYTE)dwByteSize;
+	_DCB.Parity = (BYTE)dwParity;
+	_DCB.StopBits = (BYTE)dwStopBits;
+	return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
+}
+
+LPCOMMTIMEOUTS CBaseSerial::GetTimeouts()
+{
+	return IsOpen() && ::GetCommTimeouts(_hCommHandle, &_CO) == TRUE ? &_CO : NULL;
+}
+
+bool CBaseSerial::SetTimeouts(COMMTIMEOUTS CO)
+{
+	return IsOpen() ? ::SetCommTimeouts(_hCommHandle, &CO) == TRUE : false;
+}
+
+bool CBaseSerial::SetTimeouts(LPCOMMTIMEOUTS lpCO)
+{
+	return IsOpen() ? ::SetCommTimeouts(_hCommHandle, lpCO) == TRUE : false;
+}
+
+bool CBaseSerial::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
+{
+	// SetupComm设置输入输出缓冲区大小;
+	return IsOpen() ? ::SetupComm(_hCommHandle, dwInputSize, dwOutputSize) == TRUE : false;
+}
+
+void CBaseSerial::SetMaskEvent(DWORD dwEvent /* = DEFAULT_COM_MASK_EVENT */)
+{
+	_dwMaskEvent = dwEvent;
+}
+
+int CBaseSerial::GetInputSize()
+{
+	COMSTAT Stat;
+	DWORD dwError;
+	return ::ClearCommError(_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;
+}
+
+bool CBaseSerial::Open(DWORD dwPort)
+{
+	return Open(dwPort, 19200);
+}
+
+bool CBaseSerial::Open(DWORD dwPort, DWORD dwBaudRate)
+{
+	if (dwPort < 1 || dwPort > 1024)
+		return false;
+
+	BindCommPort(dwPort);
+	if (!OpenCommPort())
+		return false;
+	if (!SetupPort())
+		return false;
+
+	return SetState(dwBaudRate);
+}
+
+bool CBaseSerial::Open(DWORD dwPort, TCHAR *lpszSetStr /* = _T("baud/* =115200 parity/* =N data/* =8 stop/* =1") */ )
+{
+	if (dwPort < 1 || dwPort > 1024)
+		return false;
+
+	BindCommPort(dwPort);
+	if (!OpenCommPort())
+		return false;
+	if (!SetupPort())
+		return false;
+
+	return SetState(lpszSetStr);
+}
+
+DWORD CBaseSerial::Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime /* = 10 */)
+{
+	if (!IsOpen())
+		return 0;
+
+	COMSTAT Stat;
+	DWORD dwError;
+	if (::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0)
+	{
+		::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);	// 清空输入缓冲区(PURGE_RXCLEAR)
+		return 0;
+	}
+
+#if 0 
+	// 暂时保留:要视机器情况而定,有些响应慢缓冲区会暂时性无数据;
+	if (!Stat.cbInQue)
+		return 0; // 缓冲区无数据
+#endif
+
+	unsigned long uReadLength = 0;
+	// dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength;//会越界;
+	if (!::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, &_ReadOverlapped)) // 可能Buffer不够大,装不完;
+	{
+		if (::GetLastError() == ERROR_IO_PENDING)
+		{
+			WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime);
+			// 结束异步I/O
+			if (!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped, &uReadLength, false))
+			{
+				if (::GetLastError() != ERROR_IO_INCOMPLETE)
+					uReadLength = 0;
+			}
+		}
+		else
+			uReadLength = 0;
+	}
+
+	return uReadLength;
+}
+
+char* CBaseSerial::ReadString(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime /* = 20 */)
+{
+	unsigned long uReadLength = Read(szBuffer, dwBufferLength - 1, dwWaitTime);
+	szBuffer[uReadLength] = '\0';
+	return szBuffer;
+}
+
+DWORD CBaseSerial::Write(LPVOID Buffer, DWORD dwBufferLength)
+{
+	if (!IsOpen())
+		return 0;
+
+	DWORD dwError;
+	if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
+		::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
+	
+	unsigned long uWriteLength = 0;
+	if (!::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, &_WriteOverlapped)) {
+		if (::GetLastError() != ERROR_IO_PENDING) {			
+			uWriteLength = 0;
+		}
+	}
+
+	return uWriteLength;
+}
+
+DWORD CBaseSerial::Write(const TCHAR *szBuffer)
+{
+	assert(szBuffer);
+	return Write((void *)szBuffer, _tclen(szBuffer));
+}
+
+DWORD CBaseSerial::ReadSync(LPVOID Buffer, DWORD dwBufferLength)
+{
+	if (!IsOpen())
+		return 0;
+	
+	DWORD dwError;
+	if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
+	{
+		::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);	// 清空输入缓冲区(PURGE_RXCLEAR)
+		return 0;
+	}
+
+	DWORD uReadLength = 0;
+	::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL);
+
+	return uReadLength;
+}
+
+DWORD CBaseSerial::WriteSync(LPVOID Buffer, DWORD dwBufferLength)
+{
+	if (!IsOpen())
+		return 0;
+	
+	DWORD dwError;
+	if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
+		::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
+	
+	unsigned long uWriteLength = 0;
+	::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL);
+
+	return uWriteLength;
+}
+
+DWORD CBaseSerial::Write(TCHAR *szBuffer, DWORD dwBufferLength, TCHAR *szFormat, ...)
+{
+	if (!IsOpen())
+		return 0;
+	
+	va_list va;
+	va_start(va, szFormat);
+#if _MSC_VER < 1500
+	_vsnprintf(szBuffer, dwBufferLength, szFormat, va);
+#endif
+#if _MSC_VER >=1500 // VC9.0以上版本;
+	//_vsntprintf(szBuffer, dwBufferLength, szFormat, va);
+	_vsntprintf_s(szBuffer, dwBufferLength, _TRUNCATE, szFormat, va);
+#endif
+	va_end(va);
+
+	return Write(szBuffer);
+}
+
+DWORD CBaseSerial::Write(TCHAR *szBuffer, TCHAR *szFormat, ...)
+{
+	if (!IsOpen()) 
+		return 0;
+	
+	va_list va;
+	va_start(va, szFormat);
+#if _MSC_VER < 1500       
+	vsprintf(szBuffer, szFormat, va);
+#endif
+#if _MSC_VER >=1500 // VC9.0以上版本;    
+	_vstprintf(szBuffer, szFormat, va);
+#endif
+	va_end(va);
+
+	return Write(szBuffer);
+}
+
+void CBaseSerial::Close()
+{
+	if (!IsOpen()) return;
+
+	PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
+	::CloseHandle(_hCommHandle);
+	_hCommHandle = INVALID_HANDLE_VALUE;
+}
+
+bool CBaseSerial::SetDTR(bool OnOrOff)
+{
+	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) : false;
+}
+
+bool CBaseSerial::SetRTS(bool OnOrOff)
+{
+	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) : false;
+}
+
+bool CBaseSerial::SetBreak(bool OnOrOff)
+{
+	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) : false;
+}
+
+void CBaseSerial::Init()
+{
+	memset(_szCommStr, 0, 20*sizeof(TCHAR));
+	memset(&_DCB, 0, sizeof(_DCB));
+	_DCB.DCBlength = sizeof(_DCB);
+	_hCommHandle = INVALID_HANDLE_VALUE;
+
+	memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
+	memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
+	_ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+	assert(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);
+	_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+	assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);
+
+	_hNotifyWnd = NULL;
+	_dwNotifyNum = 0;
+	_dwMaskEvent = DEFAULT_COM_MASK_EVENT;
+
+	memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
+	_WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+	assert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);
+}
+
+void CBaseSerial::UnInit()
+{
+	if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
+		CloseHandle(_ReadOverlapped.hEvent);
+	if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
+		CloseHandle(_WriteOverlapped.hEvent);
+	if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
+		CloseHandle(_WaitOverlapped.hEvent);
+}
+
+void CBaseSerial::BindCommPort(DWORD dwPort)
+{
+	assert(dwPort >= 1 && dwPort <= 1024);
+	TCHAR p[5] = {0};
+	_dwPort = dwPort;
+	_tcscpy_s(_szCommStr, _T("\\\\.\\COM"));
+	_ltot_s(_dwPort, p, 10);
+	_tcscat_s(_szCommStr, p);
+}
+
+bool CBaseSerial::OpenCommPort()
+{
+	if (IsOpen())
+		Close();
+	_hCommHandle = ::CreateFile(_szCommStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | _dwIOMode, NULL);
+	return IsOpen();
+}
+
+bool CBaseSerial::SetupPort()
+{
+	if (!IsOpen())
+		return false;
+	// SetupComm设置输入输出缓冲区大小;
+	if (!::SetupComm(_hCommHandle, 8192, 8192))
+		return false;
+	if (!::GetCommTimeouts(_hCommHandle, &_CO))
+		return false;
+
+	_CO.ReadIntervalTimeout = 0;
+	_CO.ReadTotalTimeoutMultiplier = 10;
+	_CO.ReadTotalTimeoutConstant = 1500;
+	_CO.WriteTotalTimeoutMultiplier = 10;
+	_CO.WriteTotalTimeoutConstant = 1500;
+	if (!::SetCommTimeouts(_hCommHandle, &_CO))
+		return false;
+
+	// 清空输入输出缓冲区;
+	if (!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
+		return false;
+
+	return true;
+}

+ 176 - 0
Serail-Demo/Demo/Serial.h

@@ -0,0 +1,176 @@
+/*
+Comm Base Library(WIN98/NT/2000) ver 1.1
+Compile by: BC++ 5; C++ BUILDER 4, 5, 6, X; VC++ 5, 6; VC.NET; GCC;
+copyright(c) 2004.5 - 2005.8 llbird wushaojian@21cn.com
+*/
+#ifndef _CN_COMM_H_
+#define _CN_COMM_H_
+
+#pragma warning(disable : 4530)
+#pragma warning(disable : 4786)
+#pragma warning(disable : 4800)
+#pragma warning(disable:  4996)
+
+#include <assert.h>
+#include <stdio.h>
+#include <windows.h>
+
+//送到窗口的消息 WPARAM 端口号
+#define ON_COM_RECEIVE WM_USER + 618
+#define ON_COM_CTS WM_USER + 619 //LPARAM 1 valid
+#define ON_COM_DSR WM_USER + 621 //LPARAM 1 valid
+#define ON_COM_RING WM_USER + 623
+#define ON_COM_RLSD WM_USER + 624
+#define ON_COM_BREAK WM_USER + 625
+#define ON_COM_TXEMPTY WM_USER + 626
+#define ON_COM_ERROR WM_USER + 627 //LPARAM save Error ID
+#define DEFAULT_COM_MASK_EVENT EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD
+
+class CBaseSerial
+{
+public:
+    // 参数为IO方式 阻塞方式(0)/ 异步重叠方式(默认)
+    CBaseSerial(DWORD dwIOMode = FILE_FLAG_OVERLAPPED) : _dwIOMode(dwIOMode)
+    {
+        Init();
+    }
+    
+    virtual ~CBaseSerial()
+    {
+        Close();
+        UnInit();
+    }
+    
+public:
+    // 判断串口是否打开
+    inline bool IsOpen() { return _hCommHandle != INVALID_HANDLE_VALUE; }
+    // 判断串口是否打开
+    operator bool() { return _hCommHandle != INVALID_HANDLE_VALUE; }
+    // 获得串口句炳
+    inline HANDLE GetHandle() { return _hCommHandle; }
+    // 获得串口句炳
+    operator HANDLE() { return _hCommHandle; }
+    
+    // 获得串口参数 DCB
+    DCB *GetState();    
+    // 设置串口参数 DCB
+    bool SetState(DCB *pdcb = NULL);      
+    // 设置串口参数:波特率,停止位,等 支持设置字符串 "9600, 8, n, 1"
+    bool SetState(TCHAR *lpszSetStr = _T("baud=115200 parity=N data=8 stop=1"));
+    // 设置串口参数:波特率,停止位,等
+    bool SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity = NOPARITY, DWORD dwStopBits = ONESTOPBIT);
+    
+    // 获得超时结构
+    LPCOMMTIMEOUTS GetTimeouts(void);    
+    // 设置超时
+	bool SetTimeouts(COMMTIMEOUTS CO /*= {0, 10, 1500, 10, 1500}*/);
+    bool SetTimeouts(LPCOMMTIMEOUTS lpCO);
+    // 设置串口的I/O缓冲区大小
+    bool SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize);
+
+    // 关联消息的窗口句柄
+    inline void SetWnd(HWND hWnd)
+    {
+        assert(::IsWindow(hWnd));
+        _hNotifyWnd = hWnd;
+    }
+    
+    // 设定发送通知, 接受字符最小值
+    inline void SetNotifyNum(DWORD dwNum) { _dwNotifyNum = dwNum; }
+    
+    // 设置要监视的事件, 打开前设置有效
+    void SetMaskEvent(DWORD dwEvent = DEFAULT_COM_MASK_EVENT);
+    // 获得读缓冲区的字符数
+    int GetInputSize();
+    
+    // 打开串口 缺省 9600, 8, n, 1
+    bool Open(DWORD dwPort);
+    // 打开串口 缺省 baud_rate, 8, n, 1
+    bool Open(DWORD dwPort, DWORD dwBaudRate);    
+    // 打开串口, 使用类似"9600, 8, n, 1"的设置字符串设置串口
+	bool Open(DWORD dwPort, TCHAR *lpszSetStr = _T("baud=115200 parity=N data=8 stop=1") );
+    
+    // 读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据
+    DWORD Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 10);    
+    // 读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯
+    char *ReadString(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime = 20);    
+    // 写串口 可写任意数据 "abcd" or "\x0\x1\x2"
+    DWORD Write(LPVOID Buffer, DWORD dwBufferLength);
+    // 写串口 写ANSI C 模式字符串指针
+    DWORD Write(const TCHAR *szBuffer);
+    // 读串口 同步应用
+    DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength);
+    // 写串口 同步应用
+    DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength);
+    // 写串口 szBuffer 可以输出格式字符串 包含缓冲区长度
+    DWORD Write(TCHAR *szBuffer, DWORD dwBufferLength, TCHAR *szFormat, ...);
+    // 写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出
+    DWORD Write(TCHAR *szBuffer, TCHAR *szFormat, ...);
+    // 关闭串口 同时也关闭关联线程
+    virtual void Close();
+    // DTR 电平控制
+    bool SetDTR(bool OnOrOff);
+    // RTS 电平控制
+    bool SetRTS(bool OnOrOff);
+    // 设置信号状态为中断;
+    bool SetBreak(bool OnOrOff);
+
+protected:
+    volatile DWORD _dwPort;                             // 串口号
+    volatile HANDLE _hCommHandle;                       // 串口句柄
+    TCHAR _szCommStr[20];                               // 保存COM1类似的字符串
+    DCB _DCB;                                           // 波特率,停止位,等
+    COMMTIMEOUTS _CO;                                   // 超时结构
+    DWORD _dwIOMode;                                    // 0 同步 默认 FILE_FLAG_OVERLAPPED重叠I/O异步
+    OVERLAPPED _ReadOverlapped, _WriteOverlapped;       // 重叠I/O
+    volatile HWND _hNotifyWnd;                          // 通知窗口
+    volatile DWORD _dwNotifyNum;                        // 接受多少字节(>=_dwNotifyNum)发送通知消息
+    volatile DWORD _dwMaskEvent;                        // 监视的事件
+    OVERLAPPED _WaitOverlapped;                         // WaitCommEvent use
+
+    // 初始化
+    void Init();
+    // 析构
+    void UnInit();
+    // 绑定串口
+    void BindCommPort(DWORD dwPort);
+    // 打开串口
+    virtual bool OpenCommPort();
+    // 设置串口
+    virtual bool SetupPort();
+
+private:
+    CBaseSerial(const CBaseSerial &);
+    CBaseSerial &operator=(const CBaseSerial &);
+};
+
+/*
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <wtypes.h>
+
+#define BUFFCOUNT (10)
+
+void FormatOutput(LPCWSTR formatstring, ...)
+{
+	int nSize = 0;
+	wchar_t buff[BUFFCOUNT];
+	memset(buff, 0, sizeof(buff));
+	va_list args;
+	va_start(args, formatstring);
+	// Note: _vsnwprintf is deprecated; consider vsnwprintf_s instead
+	nSize = _vsnwprintf(buff, BUFFCOUNT - 1, formatstring, args); // C4996
+	wprintf(L"nSize: %d, buff: %ls\n", nSize, buff);
+	va_end(args);
+}
+
+int main() {
+	FormatOutput(L"%ls %ls", L"Hi", L"there");
+	FormatOutput(L"%ls %ls", L"Hi", L"there!");
+	FormatOutput(L"%ls %ls", L"Hi", L"there!!");
+}
+
+*/
+#endif //_CN_COMM_H_

+ 8 - 0
Serail-Demo/Demo/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// Demo.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 32 - 0
Serail-Demo/Demo/stdafx.h

@@ -0,0 +1,32 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+#include "Serial.h"
+
+
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
Serail-Demo/Demo/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif