瀏覽代碼

采用异步读写串口;

scbc.sat2 5 年之前
父節點
當前提交
56da59cf88

+ 16 - 8
SATHelper/SATHelper/Device.cpp

@@ -9,17 +9,23 @@ CDevice::CDevice()
 
 CDevice::~CDevice()
 {
-	m_obj.CloseSerialPort();
+	m_obj.Close();
 }
 
 bool CDevice::Open()
 {
-	return m_obj.OpenSerialPort(m_iPort, m_iBaudrate, m_iDatabit, m_iParitybit, m_iStopbit, 0, 0);
+	if (m_obj.Open(m_iPort, m_iBaudrate, m_iDatabit, m_iParitybit, m_iStopbit, 0, TRUE))
+	{
+		m_obj.SetMask(EV_ERR | EV_RXCHAR);
+		return true;
+	}
+
+	return false;
 }
 
 void CDevice::Close()
 {
-	m_obj.CloseSerialPort();
+	m_obj.Close();
 }
 
 bool CDevice::IsOpen()
@@ -32,8 +38,9 @@ std::string CDevice::SendCommond(std::string cmd, int device_timeout)
 	if ( !m_obj.IsOpen() )
 		return std::string("串口未打开成功");
 
-	DWORD dwRet = m_obj.WriteComm((byte*)cmd.data(), cmd.size());
-	if ( dwRet != cmd.size() )
+	DWORD dwNumberOfBytesWritten = 0;
+	BOOL bRet = m_obj.WriteAsyn((byte*)cmd.data(), cmd.size(), dwNumberOfBytesWritten);
+	if (!bRet && dwNumberOfBytesWritten != cmd.size() )
 		return std::string("写串口失败");
 
 	/*
@@ -46,9 +53,10 @@ std::string CDevice::SendCommond(std::string cmd, int device_timeout)
 	*/
 
 	byte szData[1024 * 4] = {0};
-	dwRet = m_obj.ReadComm(szData, 1024 * 4, device_timeout);
-	if (dwRet == 0 )
+	DWORD dwNumberOfBytesRead = 0;
+	bRet = m_obj.ReadAsyn(szData, 1024 * 4, dwNumberOfBytesRead);
+	if (!bRet)
 		return std::string("读串口失败");
 
-	return std::string((char*)szData, dwRet);
+	return std::string((char*)szData, dwNumberOfBytesRead);
 }

+ 1 - 1
SATHelper/SATHelper/Device.h

@@ -6,7 +6,7 @@
 #pragma once
 class CDevice
 {
-	CSynSerial m_obj;
+	CBaseSerial m_obj;
 public:
 	CDevice();
 	~CDevice();

+ 2 - 2
SATHelper/SATHelper/MainFrm.cpp

@@ -993,7 +993,7 @@ void CMainFrame::RunDevice()
 		pdev->m_iDatabit = 8;
 		pdev->m_iPort = atoi(m_rscfg.chroma1.substr(3).c_str());
 		pdev->m_iParitybit = 0;
-		pdev->m_iStopbit = 1;
+		pdev->m_iStopbit = 0;
 		pdev->m_iID = 1;
 		pdev->m_strDeviceName = "Chroma22293";
 		pdev->m_iDeviceType = 1;
@@ -1014,7 +1014,7 @@ void CMainFrame::RunDevice()
 		pdev->m_iDatabit = 8;
 		pdev->m_iPort = atoi(m_rscfg.chroma2.substr(3).c_str());
 		pdev->m_iParitybit = 0;
-		pdev->m_iStopbit = 1;
+		pdev->m_iStopbit = 0;
 		pdev->m_iID = 2;
 		pdev->m_strDeviceName = "Chroma22293";
 		pdev->m_iDeviceType = 1;

+ 155 - 243
SATHelper/SATHelper/SynSerial.cpp

@@ -1,305 +1,217 @@
 #include "StdAfx.h"
 #include "SynSerial.h"
 
-CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
-, m_dwInQueue(1024)
-, m_dwOutQueue(1024)
+CBaseSerial::CBaseSerial(void) :m_hComm(INVALID_HANDLE_VALUE)
 {
-	memset(&m_dcb, 0, sizeof(DCB));
-	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
-	memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
+	memset(&m_ovWait, 0, sizeof(OVERLAPPED));
+	memset(&m_ovRead, 0, sizeof(OVERLAPPED));
+	memset(&m_ovWrite, 0, sizeof(OVERLAPPED));
 }
 
-CSynSerial::~CSynSerial(void)
+CBaseSerial::~CBaseSerial(void)
 {
-	CloseSerialPort();
+	Close();
+
+	if (m_ovWait.hEvent)
+		CloseHandle(m_ovWait.hEvent);
+
+	if (m_ovRead.hEvent)
+		CloseHandle(m_ovRead.hEvent);
+
+	if (m_ovWrite.hEvent)
+		CloseHandle(m_ovWrite.hEvent);
 }
 
-BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwBaudRate, IN CONST BYTE & bySize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST INT & nInterval)
+BOOL CBaseSerial::Open(LPCTSTR pszPort, BOOL bOverlapped /* = FALSE*/) throw()
 {
-	ASSERT(byCommPort);
-	CloseSerialPort();
+	// 关闭前句柄;
+	Close();
 
-	_stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
-	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
-	if (m_hSerialPort == INVALID_HANDLE_VALUE)
-	{
-		// 打开串口失败;
-		DWORD dwError = GetLastError();
-		return FALSE;
-	}
+	m_hComm = CreateFile(
+		pszPort,
+		GENERIC_READ | GENERIC_WRITE,
+		0,
+		NULL,
+		OPEN_EXISTING,
+		bOverlapped ? FILE_FLAG_OVERLAPPED : 0,
+		NULL);
 
-	BOOL bResult = FALSE;
-	// SetupComm设置缓冲区大小;
-	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
-	if (!bResult)
+	if (m_hComm != INVALID_HANDLE_VALUE)
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
-	}
-
-	// 在串口读写之前,清除缓冲区;
-	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
-	if (!bResult)
-	{
-		DWORD dwError = GetLastError();
-		return FALSE;
-	}
+		m_ovWait.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+		m_ovRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+		m_ovWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 
-	// GetCommState获取设备控制块状态;
-	memset(&m_dcb, 0, sizeof(DCB));
-	bResult = GetCommState(m_hSerialPort, &m_dcb);
-	if (!bResult)
-	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		return TRUE;
 	}
 
-	m_dcb.Parity = byParity;
-	if (m_dcb.Parity == NOPARITY)
-		m_dcb.fParity = FALSE;
-	else
-		m_dcb.fParity = TRUE;
+	return FALSE;
+}
 
-	m_dcb.BaudRate = dwBaudRate;
-	m_dcb.ByteSize = bySize;
-	m_dcb.StopBits = byStopBits;
-	if (m_dcb.ByteSize == 8)
-		m_dcb.StopBits = ONESTOPBIT;
+BOOL CBaseSerial::Open(int nPort, DWORD dwBaud /* = 9600 */, BYTE DataBits /* = 8 */, int parity /* = NoParity */, int stopBits /* = OneStopBit */,  int fc /* = NoFlowControl */, BOOL bOverlapped /* = FALSE */)
+{
+	CString sPort;
+	sPort.Format(_T("\\\\.\\COM%d"), nPort);
+	return Open(sPort, dwBaud,  DataBits, parity, stopBits, fc, bOverlapped);
+}
 
-	// SetCommState设置设备的控制块状态;
-	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
-	bResult = SetCommState(m_hSerialPort, &m_dcb);
-	if (!bResult)
-	{
-		DWORD dwError = GetLastError();
+BOOL CBaseSerial::Open(LPCTSTR pszPort, DWORD dwBaud /* = 9600 */,  BYTE DataBits /* = 8 */, int parity /* = NoParity */, int stopBits /* = OneStopBit */,  int fc /* = NoFlowControl */, BOOL bOverlapped /* = FALSE */) throw()
+{
+	if (!Open(pszPort, bOverlapped))
 		return FALSE;
-	}
 
-	// 获取设备的超时值;
-	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
-	if (!bResult)
+	//Get the current state prior to changing it
+	DCB dcb = { 0 };
+	dcb.DCBlength = sizeof(DCB);
+	if (!GetState(dcb))
 	{
-		DWORD dwError = GetLastError();
+		const DWORD dwLastError = GetLastError();
+		Close();
+		SetLastError(dwLastError);
 		return FALSE;
 	}
 
-	// 两字符之间最大的延时,设置0表示参数不起作用;
-	m_cts.ReadIntervalTimeout = 50;
-	m_cts.ReadTotalTimeoutMultiplier = 100;
-	m_cts.ReadTotalTimeoutConstant = 8000;
-	m_cts.WriteTotalTimeoutMultiplier = 100;
-	m_cts.WriteTotalTimeoutConstant = 5000;
+	//Setup the baud rate
+	dcb.BaudRate = dwBaud;
 
-	// 设置设备的超时值;
-	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
-	if (!bResult)
+	//Setup the Parity
+	switch (parity)
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+	case EvenParity:
+	{
+		dcb.Parity = EVENPARITY;
+		break;
 	}
-
-	return TRUE;
-}
-
-BOOL CSynSerial::ReOpenSerialPort()
-{
-	ASSERT(_tcslen(m_szSerialPort));
-	CloseSerialPort();
-
-	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
-	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	case MarkParity:
 	{
-		// 打开串口失败;
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.Parity = MARKPARITY;
+		break;
 	}
-
-	BOOL bResult = FALSE;
-	// SetupComm设置缓冲区大小;
-	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
-	if (!bResult)
+	case NoParity:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.Parity = NOPARITY;
+		break;
 	}
-
-	// 在串口读写之前,清除缓冲区;
-	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
-	if (!bResult)
+	case OddParity:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.Parity = ODDPARITY;
+		break;
 	}
-
-	// SetCommState设置设备的控制块状态;
-	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
-	bResult = SetCommState(m_hSerialPort, &m_dcb);
-	if (!bResult)
+	case SpaceParity:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.Parity = SPACEPARITY;
+		break;
 	}
-
-	// 设置设备的超时值;
-	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
-	if (!bResult)
+	default:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		ATLASSERT(FALSE);
+		break;
+	}
 	}
 
-	return TRUE;
-}
-
-void CSynSerial::CloseSerialPort()
-{
-	if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
-		CloseHandle(m_hSerialPort);
-	m_hSerialPort = NULL;
-}
-
-BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
-{
-	if (!IsOpen())
-		return FALSE;
+	//Setup the data bits
+	dcb.ByteSize = DataBits;
 
-	BOOL bResult = FALSE;
-	// GetCommState获取设备控制块状态;
-	memset(&m_dcb, 0, sizeof(DCB));
-	bResult = GetCommState(m_hSerialPort, &m_dcb);
-	if (!bResult)
+	//Setup the stop bits
+	switch (stopBits)
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+	case OneStopBit:
+	{
+		dcb.StopBits = ONESTOPBIT;
+		break;
 	}
-
-	m_dcb.Parity = byParity;
-	if (m_dcb.Parity == NOPARITY)
-		m_dcb.fParity = FALSE;
-	else
-		m_dcb.fParity = TRUE;
-
-	m_dcb.BaudRate = dwBaudRate;
-	m_dcb.ByteSize = byByteSize;
-	m_dcb.StopBits = byStopBits;
-	if (m_dcb.ByteSize == 8)
-		m_dcb.StopBits = ONESTOPBIT;
-
-	// SetCommState设置设备的控制块状态;
-	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
-	bResult = SetCommState(m_hSerialPort, &m_dcb);
-	if (!bResult)
+	case OnePointFiveStopBits:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.StopBits = ONE5STOPBITS;
+		break;
 	}
-
-	// 获取设备的超时值;
-	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
-	if (!bResult)
+	case TwoStopBits:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		dcb.StopBits = TWOSTOPBITS;
+		break;
 	}
-
-	// 两字符之间最大的延时,设置0表示参数不起作用;
-	m_cts.ReadIntervalTimeout = 50;
-	m_cts.ReadTotalTimeoutMultiplier = 100;
-	m_cts.ReadTotalTimeoutConstant = 8000;
-	m_cts.WriteTotalTimeoutMultiplier = 100;
-	m_cts.WriteTotalTimeoutConstant = 3000;
-
-	// 设置设备的超时值;
-	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
-	if (!bResult)
+	default:
 	{
-		DWORD dwError = GetLastError();
-		return FALSE;
+		ATLASSERT(FALSE);
+		break;
+	}
 	}
 
-	return TRUE;
-}
-
-void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
-{
-}
-
-void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
-{
-}
-
-DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
-{
-	if (!IsOpen())
-		return 0;
-
-	if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
+	//Setup the flow control
+	dcb.fDsrSensitivity = FALSE;
+	switch (fc)
+	{
+	case NoFlowControl:
 	{
-		return 0;
+		dcb.fOutxCtsFlow = FALSE;
+		dcb.fOutxDsrFlow = FALSE;
+		dcb.fOutX = FALSE;
+		dcb.fInX = FALSE;
+		break;
 	}
-	
-	DWORD dwErrorFlags;
-	DWORD dwBytesWritten = 0;	// 实际写入的字节数;
-	// 写前, 清除错误;
-	COMSTAT ComStat;
-	ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);	
-	// 写前,清空缓存区;
-	PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
-	if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, NULL) )
+	case CtsRtsFlowControl:
 	{
-		DWORD dwError = GetLastError();
-	}	
-
-	// 返回写入字节数;
-	return dwBytesWritten;
-}
-
-DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
-{
-	if (!IsOpen())
-		return 0;
-
-	if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
+		dcb.fOutxCtsFlow = TRUE;
+		dcb.fOutxDsrFlow = FALSE;
+		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+		dcb.fOutX = FALSE;
+		dcb.fInX = FALSE;
+		break;
+	}
+	case CtsDtrFlowControl:
 	{
-		return 0;
+		dcb.fOutxCtsFlow = TRUE;
+		dcb.fOutxDsrFlow = FALSE;
+		dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
+		dcb.fOutX = FALSE;
+		dcb.fInX = FALSE;
+		break;
 	}
-
-	DWORD dwBytesRead = 0;
-	DWORD dwErrorFlags = 0;
-	// ReadFile前,使用ClearCommError清除错误;
-	COMSTAT ComStat = {0};
-	DWORD dwLastLen = 0;
-	ULONGLONG ulTick = GetTickCount64();	
-	// 直到有数据为止,超时3秒;
-	while (true)
-	{// cbInQue表示输入缓冲区的字节数; 
-		Sleep(timeout);
-		if (GetTickCount64() - ulTick > 5000)
-			break;
-		ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
-		// 防止读一次没读完,再读一次;二次长度一样表示读完;
-		if (ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue)
-			break;
-		dwLastLen = ComStat.cbInQue;
+	case DsrRtsFlowControl:
+	{
+		dcb.fOutxCtsFlow = FALSE;
+		dcb.fOutxDsrFlow = TRUE;
+		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+		dcb.fOutX = FALSE;
+		dcb.fInX = FALSE;
+		break;
 	}
-
-	if (ComStat.cbInQue == 0)
+	case DsrDtrFlowControl:
 	{
-		// 串口超时,无数据返回;
-		return 0;
+		dcb.fOutxCtsFlow = FALSE;
+		dcb.fOutxDsrFlow = TRUE;
+		dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
+		dcb.fOutX = FALSE;
+		dcb.fInX = FALSE;
+		break;
 	}
-
-	dwBytesRead = ComStat.cbInQue;
-	if (dwReadSize < dwBytesRead)
+	case XonXoffFlowControl:
+	{
+		dcb.fOutxCtsFlow = FALSE;
+		dcb.fOutxDsrFlow = FALSE;
+		dcb.fOutX = TRUE;
+		dcb.fInX = TRUE;
+		dcb.XonChar = 0x11;
+		dcb.XoffChar = 0x13;
+		dcb.XoffLim = 100;
+		dcb.XonLim = 100;
+		break;
+	}
+	default:
 	{
-		dwBytesRead = dwReadSize;
+		ATLASSERT(FALSE);
+		break;
+	}
 	}
 
-	if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
+	//Now that we have all the settings in place, make the changes
+	if (!SetState(dcb))
 	{
-		return (INT)dwBytesRead;
+		const DWORD dwLastError = GetLastError();
+		Close();
+		SetLastError(dwLastError);
+		return FALSE;
 	}
 
-	return dwBytesRead;
-}
+	return TRUE;
+}

+ 447 - 55
SATHelper/SATHelper/SynSerial.h

@@ -1,6 +1,6 @@
 /************************************************************************/
 /*  Copyright (C), 2016-2020, [Home], 保留所有权利;
-/*  模 块 名:步串口模块;
+/*  模 块 名:步串口模块;
 /*  描    述:;
 /*
 /*  版    本:[V];
@@ -16,68 +16,460 @@
 /*  修改内容:;
 /************************************************************************/
 
-#ifndef __SYN_SERIAL__
-#define __SYN_SERIAL__
+#ifndef __BASE_SERIAL__
+#define __BASE_SERIAL__
 
 #pragma once
 
-#define MAX_PORT_LEN 10
-
-class CSynSerial
+class CBaseSerial
 {
 public:
-	CSynSerial(void);
-	virtual ~CSynSerial(void);
-
-private:
-	DCB		m_dcb;
-	HANDLE	m_hSerialPort;
-	COMMTIMEOUTS	m_cts;
+	//Enums
+	enum FlowControl
+	{
+		NoFlowControl,
+		CtsRtsFlowControl,
+		CtsDtrFlowControl,
+		DsrRtsFlowControl,
+		DsrDtrFlowControl,
+		XonXoffFlowControl
+	};
 
-	// 串口号(1~255);
-	TCHAR	m_szSerialPort[MAX_PORT_LEN];
-	// 输入缓存大小(byte);
-	DWORD	m_dwInQueue;
-	// 输出缓存大小(byte);
-	DWORD	m_dwOutQueue;
+	enum Parity
+	{
+		NoParity = 0,
+		OddParity = 1,
+		EvenParity = 2,
+		MarkParity = 3,
+		SpaceParity = 4
+	};
 
+	enum StopBits
+	{
+		OneStopBit,
+		OnePointFiveStopBits,
+		TwoStopBits
+	};
+protected:
+	HANDLE		m_hComm;
+	OVERLAPPED	m_ovWait;
+	OVERLAPPED	m_ovRead;
+	OVERLAPPED	m_ovWrite;
 public:
-	inline BOOL IsOpen() const {
-		return (m_hSerialPort == NULL || m_hSerialPort == INVALID_HANDLE_VALUE) ? FALSE : TRUE;
-	}
-
-	// 打开串口;
-	BOOL OpenSerialPort(
-		IN CONST BYTE& byCommPort,		// 串口号;
-		IN CONST DWORD& dwBaudRate,		// 波特率;
-		IN CONST BYTE& bySize,			// 数据位;
-		IN CONST BYTE& byParity,		// 校验位;
-		IN CONST BYTE& byStopBits,		// 停止位;
-		IN CONST BYTE& byStartAddr,		// 起始地址;
-		IN CONST INT& nInterval			// 间隔时间;
+	CBaseSerial(void);
+	virtual ~CBaseSerial(void);
+
+	BOOL IsOpen() const throw() // noexcept 
+	{
+		return m_hComm != INVALID_HANDLE_VALUE;
+	}
+
+	void Close() throw()  // noexcept  
+	{
+		if (IsOpen())
+		{
+			CloseHandle(m_hComm);
+			m_hComm = INVALID_HANDLE_VALUE;
+		}
+	}
+
+	BOOL Open(LPCTSTR pszPort, BOOL bOverlapped = FALSE) throw(); // noexcept 
+	BOOL Open(
+		int nPort, 
+		DWORD dwBaud = 9600, 
+		BYTE DataBits = 8, 
+		int parity = NoParity, 
+		int stopBits = OneStopBit,
+		int fc = NoFlowControl, 
+		BOOL bOverlapped = FALSE
 	);
-	// 重装打开串口;
-	BOOL ReOpenSerialPort();
-	// 关闭串口;
-	void CloseSerialPort();
-	// 设置串口参数;
-	BOOL SetSerialPort(
-		IN CONST DWORD& dwBaudRate,		// 波特率;
-		IN CONST BYTE& byByteSize,		// 数据位;
-		IN CONST BYTE& byParity,		// 校验位;
-		IN CONST BYTE& byStopBits,		// 停止位;
-		IN CONST BYTE& byStartAddr,		// 起始地址;
-		IN CONST DWORD& dwInQueue,		// 输入缓存;
-		IN CONST DWORD& dwOutQueue		// 输出缓存;
-		);
-
-	// 设置dcb参数;
-	void SetSerialDCB(IN CONST DCB &dcb);
-	// 设置commtimeouts参数;
-	void SetSerialCommTimeouts(IN CONST COMMTIMEOUTS &commTimeouts);
-
-	virtual DWORD WriteComm(IN BYTE *pWirteBuf, IN CONST INT32 nWriteSize);
-	virtual DWORD ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout = 300);
+	BOOL Open(
+		LPCTSTR pszPort, 
+		DWORD dwBaud = 9600, 
+		BYTE DataBits = 8, 		
+		int parity = NoParity, 
+		int stopBits = OneStopBit,
+		int fc = NoFlowControl, 
+		BOOL bOverlapped = FALSE
+	) throw(); // noexcept 
+
+	//////////////////////////////////////////////////////////////////////////
+	//Reading / Writing Methods
+	BOOL Read(void* lpBuffer, DWORD dwNumberOfBytesToRead, DWORD& dwBytesRead) throw()
+	{
+		ATLASSERT(IsOpen());
+		return ReadFile(m_hComm, lpBuffer, dwNumberOfBytesToRead, &dwBytesRead, NULL);
+	}
+
+	BOOL Read(void* lpBuffer, DWORD dwNumberOfBytesToRead, OVERLAPPED& overlapped, DWORD* lpNumberOfBytesRead = NULL) throw()
+	{
+		ATLASSERT(IsOpen());
+		return ReadFile(m_hComm, lpBuffer, dwNumberOfBytesToRead, lpNumberOfBytesRead, &overlapped);
+	}
+
+	BOOL ReadEx(LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) throw()
+	{
+		ATLASSERT(IsOpen());
+		return ReadFileEx(m_hComm, lpBuffer, dwNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
+	}
+
+	// 必须先启用:SetMask(EV_ERR | EV_RXCHAR),才能使用WaitCommEvent;
+	BOOL ReadAsyn(void* lpBuffer, DWORD dwNumberOfBytesToRead, DWORD& dwNumberOfBytesRead) throw()
+	{
+		ATLASSERT(IsOpen());
+		COMSTAT cs = { 0 };
+		DWORD dwErrors = 0;
+		DWORD dwEvtMask = 0;
+		DWORD dwNumberOfBytesTransferred;
+
+		m_ovWait.Offset = 0;
+		m_ovRead.Offset = 0;
+		BOOL Status = WaitCommEvent(m_hComm, &dwEvtMask, &m_ovWait);
+		// WaitCommEvent也是一个异步命令,所以需要等待
+		if (!Status && GetLastError() == ERROR_IO_PENDING)
+		{
+			// 如果缓存中无数据线程会停在此,如果hCom关闭会立即返回False
+			Status = ::GetOverlappedResult(m_hComm, &m_ovWait, &dwNumberOfBytesTransferred, TRUE);
+		}
+
+		ClearCommError(m_hComm, &dwErrors, &cs);
+		if (Status && dwEvtMask & EV_RXCHAR && cs.cbInQue > 0) //有数据
+		{
+			dwNumberOfBytesTransferred = 0;
+			memset(lpBuffer, 0, dwNumberOfBytesToRead);
+			// 数据已经到达缓存区,ReadFile不会当成异步命令,而是立即读取并返回True
+			Status = ReadFile(m_hComm, lpBuffer, dwNumberOfBytesToRead, &dwNumberOfBytesRead, &m_ovRead);
+			PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_RXABORT);
+		}
+
+		return Status;
+	}
+
+	BOOL Write(const void* lpBuffer, DWORD dwNumberOfBytesToWrite, DWORD& dwBytesWritten) throw()
+	{
+		ATLASSERT(IsOpen());
+		dwBytesWritten = 0;
+		return WriteFile(m_hComm, lpBuffer, dwNumberOfBytesToWrite, &dwBytesWritten, NULL);
+	}
+
+	BOOL Write(const void* lpBuffer, DWORD dwNumberOfBytesToWrite, OVERLAPPED& overlapped, DWORD* lpNumberOfBytesWritten = NULL) throw()
+	{
+		ATLASSERT(IsOpen());
+		return WriteFile(m_hComm, lpBuffer, dwNumberOfBytesToWrite, lpNumberOfBytesWritten, &overlapped);
+	}
+
+	// SetMask(EV_ERR | EV_RXCHAR);
+	BOOL WriteAsyn(const void* lpBuffer, DWORD dwNumberOfBytesToWrite, DWORD& dwNumberOfBytesWritten) throw()
+	{
+		ATLASSERT(IsOpen());
+		PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_TXABORT);
+
+		m_ovWait.Offset = 0;
+		BOOL bRet = WriteFile(m_hComm, lpBuffer, dwNumberOfBytesToWrite, &dwNumberOfBytesWritten, &m_ovWrite);
+
+		if (!bRet && GetLastError() == ERROR_IO_PENDING)//后台读取
+		{
+			//等待数据写入完成
+			if (FALSE == ::GetOverlappedResult(m_hComm, &m_ovWrite, &dwNumberOfBytesWritten, TRUE))
+			{
+				return FALSE;
+			}
+		}
+
+		return bRet;
+	}
+
+	BOOL WriteEx(LPCVOID lpBuffer, DWORD dwNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) throw()
+	{
+		ATLASSERT(IsOpen());
+		return WriteFileEx(m_hComm, lpBuffer, dwNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine);
+	}
+
+	BOOL TransmitChar(char cChar) throw()
+	{
+		ATLASSERT(IsOpen());
+		return TransmitCommChar(m_hComm, cChar);
+	}
+
+	BOOL GetOverlappedResult(OVERLAPPED& overlapped, DWORD& dwBytesTransferred, BOOL bWait) throw()
+	{
+		ATLASSERT(IsOpen());
+		return ::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransferred, bWait);
+	}
+
+	__if_exists(::GetOverlappedResultEx)
+	{
+		BOOL GetOverlappedResultEx(OVERLAPPED & overlapped, DWORD & dwBytesTransferred, DWORD dwMilliseconds, _In_ BOOL bAlertable) throw()
+		{
+			ATLASSERT(IsOpen());
+			return ::GetOverlappedResultEx(m_hComm, &overlapped, &dwBytesTransferred, dwMilliseconds, bAlertable);
+		}
+	}
+
+	BOOL CancelIo() throw()
+	{
+		ATLASSERT(IsOpen());
+		return ::CancelIo(m_hComm);
+	}
+
+	__if_exists(::CancelIoEx)
+	{
+		BOOL CancelIoEx(LPOVERLAPPED lpOverlapped = NULL) throw()
+		{
+			ATLASSERT(IsOpen());
+
+			return ::CancelIoEx(m_hComm, lpOverlapped);
+		}
+	}
+
+	BOOL BytesWaiting(DWORD& dwBytesWaiting) throw()
+	{
+		ATLASSERT(IsOpen());
+		//Check to see how many characters are unread
+		dwBytesWaiting = 0;
+		COMSTAT stat;
+		if (!GetStatus(stat))
+			return FALSE;
+		dwBytesWaiting = stat.cbInQue;
+		return TRUE;
+	}
+
+	//Configuration Methods
+	BOOL GetConfig(COMMCONFIG& config) throw()
+	{
+		ATLASSERT(IsOpen());
+
+		DWORD dwSize = sizeof(COMMCONFIG);
+		return GetCommConfig(m_hComm, &config, &dwSize);
+	}
+
+	static BOOL GetDefaultConfig(int nPort, COMMCONFIG& config)
+	{
+		CString sPort;
+		sPort.Format(_T("COM%d"), nPort);
+		//Delegate to the other version of the method
+		return GetDefaultConfig(sPort, config);
+	}
+
+	static BOOL GetDefaultConfig(LPCTSTR pszPort, COMMCONFIG& config) throw()
+	{
+		DWORD dwSize = sizeof(COMMCONFIG);
+		return GetDefaultCommConfig(pszPort, &config, &dwSize);
+	}
+
+	BOOL SetConfig(COMMCONFIG& config) throw()
+	{
+		ATLASSERT(IsOpen());
+		const DWORD dwSize = sizeof(COMMCONFIG);
+		return SetCommConfig(m_hComm, &config, dwSize);
+	}
+
+	static BOOL SetDefaultConfig(int nPort, COMMCONFIG& config)
+	{
+		CString sPort;
+		sPort.Format(_T("COM%d"), nPort);
+		//Delegate to the other version of the method
+		return SetDefaultConfig(sPort, config);
+	}
+
+	static BOOL SetDefaultConfig(LPCTSTR pszPort, COMMCONFIG& config) throw()
+	{
+		const DWORD dwSize = sizeof(COMMCONFIG);
+		return SetDefaultCommConfig(pszPort, &config, dwSize);
+	}
+
+	//Misc RS232 Methods
+	BOOL ClearBreak() throw()
+	{
+		ATLASSERT(IsOpen());
+		return ClearCommBreak(m_hComm);
+	}
+
+	BOOL SetBreak() throw()
+	{
+		ATLASSERT(IsOpen());
+		return SetCommBreak(m_hComm);
+	}
+
+	BOOL ClearError(DWORD& dwErrors) throw()
+	{
+		ATLASSERT(IsOpen());
+		return ClearCommError(m_hComm, &dwErrors, NULL);
+	}
+
+	BOOL GetStatus(COMSTAT& stat) throw()
+	{
+		ATLASSERT(IsOpen());
+		DWORD dwErrors = 0;
+		return ClearCommError(m_hComm, &dwErrors, &stat);
+	}
+
+	BOOL GetState(DCB& dcb) throw()
+	{
+		ATLASSERT(IsOpen());
+		return GetCommState(m_hComm, &dcb);
+	}
+
+	BOOL SetState(DCB& dcb) throw()
+	{
+		ATLASSERT(IsOpen());
+		return SetCommState(m_hComm, &dcb);
+	}
+
+	BOOL Escape(DWORD dwFunc) throw()
+	{
+		ATLASSERT(IsOpen());
+		return EscapeCommFunction(m_hComm, dwFunc);
+	}
+
+	BOOL ClearDTR() throw()
+	{
+		return Escape(CLRDTR);
+	}
+
+	BOOL ClearRTS() throw()
+	{
+		return Escape(CLRRTS);
+	}
+
+	BOOL SetDTR() throw()
+	{
+		return Escape(SETDTR);
+	}
+
+	BOOL SetRTS() throw()
+	{
+		return Escape(SETRTS);
+	}
+
+	BOOL SetXOFF() throw()
+	{
+		return Escape(SETXOFF);
+	}
+
+	BOOL SetXON() throw()
+	{
+		return Escape(SETXON);
+	}
+
+	BOOL GetProperties(COMMPROP& properties) throw()
+	{
+		ATLASSERT(IsOpen());
+		return GetCommProperties(m_hComm, &properties);
+	}
+
+	BOOL GetModemStatus(DWORD& dwModemStatus) throw()
+	{
+		ATLASSERT(IsOpen());
+		return GetCommModemStatus(m_hComm, &dwModemStatus);
+	}
+
+	//Timeouts
+	BOOL SetTimeouts(COMMTIMEOUTS& timeouts) throw()
+	{
+		ATLASSERT(IsOpen());
+		return SetCommTimeouts(m_hComm, &timeouts);
+	}
+
+	BOOL GetTimeouts(COMMTIMEOUTS& timeouts) throw()
+	{
+		ATLASSERT(IsOpen());
+		return GetCommTimeouts(m_hComm, &timeouts);
+	}
+
+	BOOL Set0Timeout() throw()
+	{
+		COMMTIMEOUTS Timeouts;
+		memset(&Timeouts, 0, sizeof(Timeouts));
+		Timeouts.ReadIntervalTimeout = MAXDWORD;
+		return SetTimeouts(Timeouts);
+	}
+
+	BOOL Set0WriteTimeout() throw()
+	{
+		COMMTIMEOUTS Timeouts;
+		GetTimeouts(Timeouts);
+		Timeouts.WriteTotalTimeoutMultiplier = 0;
+		Timeouts.WriteTotalTimeoutConstant = 0;
+		return SetTimeouts(Timeouts);
+	}
+
+	BOOL Set0ReadTimeout() throw()
+	{
+		COMMTIMEOUTS Timeouts;
+		GetTimeouts(Timeouts);
+		Timeouts.ReadIntervalTimeout = MAXDWORD;
+		Timeouts.ReadTotalTimeoutMultiplier = 0;
+		Timeouts.ReadTotalTimeoutConstant = 0;
+		return SetTimeouts(Timeouts);
+	}
+
+	//Event Methods
+	BOOL SetMask(DWORD dwMask) throw()
+	{
+		ATLASSERT(IsOpen());
+		return SetCommMask(m_hComm, dwMask);
+	}
+
+	BOOL GetMask(DWORD& dwMask) throw()
+	{
+		ATLASSERT(IsOpen());
+		return GetCommMask(m_hComm, &dwMask);
+	}
+
+	BOOL WaitEvent(DWORD& dwMask) throw()
+	{
+		ATLASSERT(IsOpen());
+		return WaitCommEvent(m_hComm, &dwMask, NULL);
+	}
+
+	BOOL WaitEvent(DWORD& dwMask, OVERLAPPED& overlapped) throw()
+	{
+		ATLASSERT(IsOpen());
+		ATLASSERT(overlapped.hEvent != NULL);
+
+		return WaitCommEvent(m_hComm, &dwMask, &overlapped);
+	}
+
+	//Queue Methods
+	BOOL Flush() throw()
+	{
+		ATLASSERT(IsOpen());
+		return FlushFileBuffers(m_hComm);
+	}
+
+	BOOL Purge(DWORD dwFlags) throw()
+	{
+		ATLASSERT(IsOpen());
+		return PurgeComm(m_hComm, dwFlags);
+	}
+
+	BOOL TerminateOutstandingWrites() throw()
+	{
+		return Purge(PURGE_TXABORT);
+	}
+
+	BOOL TerminateOutstandingReads() throw()
+	{
+		return Purge(PURGE_RXABORT);
+	}
+
+	BOOL ClearWriteBuffer() throw()
+	{
+		return Purge(PURGE_TXCLEAR);
+	}
+
+	BOOL ClearReadBuffer() throw()
+	{
+		return Purge(PURGE_RXCLEAR);
+	}
+
+	BOOL Setup(DWORD dwInQueue, DWORD dwOutQueue) throw()
+	{
+		ATLASSERT(IsOpen());
+		return SetupComm(m_hComm, dwInQueue, dwOutQueue);
+	}
+
 };
 
-#endif // __SYN_SERIAL__
+#endif // __ASYN_SERIAL__