Win32串口操作封装

#ifndef __SERIAL_H__
#define __SERIAL_H__

//#include "stdafx.h"
#include <windows.h>
#include <iostream>
//#include "mutex.h"

class CSerial
{
public:
	CSerial(void);
	virtual ~CSerial(void);

public:
	BOOL Open(WCHAR *sName, BOOL bOverlapped=FALSE);
	void Close(void);
	BOOL isValid(void);

public:
	int  Write(BYTE *pBuf, DWORD nSize);
	int  Read(BYTE *pBuf, DWORD nSize);
	void SetComm(DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits);
	void SetTimeOut(DWORD interval, DWORD rdmult, DWORD rdconst, DWORD wrmult, DWORD wrconst);	
protected:
	void ResetRx(void);
	void ResetTx(void);
protected:
	HANDLE _hCom;
	HANDLE _hRdEvt, _hWrEvt;
	BOOL   _bOvlap;
};


#endif


//#include "stdafx.h"
#include "Serial.h"


CSerial::CSerial(void)
{
	_bOvlap = FALSE;
	_hCom   = INVALID_HANDLE_VALUE;
	_hRdEvt = INVALID_HANDLE_VALUE;
	_hWrEvt = INVALID_HANDLE_VALUE;
}

BOOL CSerial::isValid(void)
{
	return (_hCom != INVALID_HANDLE_VALUE);
}

CSerial::~CSerial(void)
{
	Close();
}

BOOL CSerial::Open(WCHAR *name, BOOL bOverlapped)
{
	DWORD flag = 0;
	
	Close();

	if(bOverlapped)
	{
		_bOvlap = TRUE;
		flag    = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED;
	}

	_hCom = ::CreateFile(name,        //COM1口   
		GENERIC_READ|GENERIC_WRITE, //允许读和写   
		0,							//独占方式   
		NULL,  
		OPEN_EXISTING,				//打开而不是创建   
		flag,							//同步方式
		NULL);  

	if(_hCom == INVALID_HANDLE_VALUE)
		return FALSE;

	//设置缓冲区大小
	::SetupComm(_hCom,1200,1200);

	SetComm(115200, 8, NOPARITY, ONESTOPBIT);

	//SetTimeOut(MAXDWORD, 80, 10, 100, 500);
	SetTimeOut(200, 80, 10, 100, 500);

	if(_bOvlap)
	{
		_hRdEvt = ::CreateEvent(NULL,TRUE,FALSE,TEXT("read"));
		_hWrEvt = ::CreateEvent(NULL,TRUE,FALSE,TEXT("write"));

		if(_hRdEvt == INVALID_HANDLE_VALUE
			|| _hWrEvt == INVALID_HANDLE_VALUE)
		{
			Close();
			return FALSE;
		}
	}

	return TRUE;	 
}

void CSerial::Close(void)
{
	_bOvlap  = FALSE;

	if(_hCom != INVALID_HANDLE_VALUE)
	{
		::CloseHandle(_hCom);
		_hCom = INVALID_HANDLE_VALUE;
	}
	if(_hRdEvt != INVALID_HANDLE_VALUE)
	{
		::CloseHandle(_hRdEvt);
		_hRdEvt = INVALID_HANDLE_VALUE;
	}
	if(_hRdEvt != INVALID_HANDLE_VALUE)
	{
		::CloseHandle(_hWrEvt);
		_hWrEvt = INVALID_HANDLE_VALUE;
	}
}

void CSerial::ResetTx(void)
{
	if(isValid())
		::PurgeComm(_hCom, PURGE_TXABORT|PURGE_TXCLEAR); 
}

void CSerial::ResetRx(void)
{
	if(isValid())
		::PurgeComm(_hCom, PURGE_RXABORT|PURGE_RXCLEAR); 
}

void CSerial::SetComm(DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits)
{
	DCB dcb;  

	if(!isValid())
		return;

	::GetCommState(_hCom, &dcb);

	dcb.BaudRate  = BaudRate;	//波特率为9600   
	dcb.ByteSize  = ByteSize;	//每个字节有8位   
	dcb.Parity	  = Parity;		//无奇偶校验位   
	dcb.StopBits  = StopBits;	//两个停止位   

	::SetCommState(_hCom,&dcb);  

	ResetTx();

	ResetRx();
}


void CSerial::SetTimeOut(DWORD interval, DWORD rdmult, DWORD rdconst, DWORD wrmult, DWORD wrconst)
{
	COMMTIMEOUTS TimeOuts;  

	if(!isValid())
		return;

	//设定读超时   
	TimeOuts.ReadIntervalTimeout = interval;//MAXDWORD;  

	TimeOuts.ReadTotalTimeoutMultiplier = rdmult;//0;  
	TimeOuts.ReadTotalTimeoutConstant   = rdconst;//0;  

	//设定写超时   
	TimeOuts.WriteTotalTimeoutMultiplier = wrmult;  
	TimeOuts.WriteTotalTimeoutConstant   = wrconst;  

	::SetCommTimeouts(_hCom,&TimeOuts); //设置超时
}


/*
BOOL CSerial::WriteIO(BYTE *pBuf, DWORD nSize, DWORD *pWriteCnt, OVERLAPPED *lpOverlapped)
{
	COMSTAT		ComStat;
	DWORD		dwErrorFlags;
	BOOL		bWriteStat;

	if(!isValid())
		return FALSE;

	::ClearCommError(_hCom,&dwErrorFlags,&ComStat);

	bWriteStat = ::WriteFile(_hCom, pBuf, nSize, pWriteCnt, lpOverlapped);

	return bWriteStat;
}

BOOL CSerial::ReadIO(BYTE *pBuf, DWORD nSize, DWORD *pReadCnt, OVERLAPPED *lpOverlapped)
{
	COMSTAT		ComStat;
	DWORD       dwErrorFlags;
	BOOL		bReadStatus;

	if(!isValid())
		return FALSE;

	::ClearCommError(_hCom, &dwErrorFlags, &ComStat);
	//if(!ComStat.cbInQue)
	//	return 0;

	nSize = min(nSize, (DWORD)ComStat.cbInQue);

	bReadStatus = ::ReadFile(_hCom, pBuf, nSize, pReadCnt, lpOverlapped);

	return bReadStatus;
}
*/

int CSerial::Write(BYTE *pBuf, DWORD nSize)
{
	COMSTAT		ComStat;
	DWORD		dwErrorFlags;
	DWORD       dwBytesWritten;
	OVERLAPPED	osWrite;
	BOOL		bWriteStat;
	DWORD       dwEventStat;

	memset(&osWrite, 0, sizeof(OVERLAPPED));

	osWrite.hEvent = _hWrEvt;

	::ClearCommError(_hCom,&dwErrorFlags,&ComStat);

	bWriteStat = ::WriteFile(_hCom, pBuf, nSize, &dwBytesWritten, (_bOvlap ? (&osWrite) : NULL));
	if(!bWriteStat)
	{
		if(_bOvlap && GetLastError()==ERROR_IO_PENDING)
		{
			do{
				dwEventStat = ::WaitForSingleObject(osWrite.hEvent, 200);
			}while(isValid() && dwEventStat == WAIT_TIMEOUT);

			if(dwEventStat == WAIT_OBJECT_0) //write done.
			{
				if(::GetOverlappedResult(_hCom, &osWrite, &dwBytesWritten, TRUE))
				{
					return dwBytesWritten;
				}
			}			
		}

		//Reset Send Error.
		ResetTx();
		
		return 0;
	}

	return dwBytesWritten;
}

int CSerial::Read(BYTE *pBuf, DWORD nSize)
{
	COMSTAT		ComStat;
	DWORD       dwEventStat;
	DWORD       dwBytesRead;
	DWORD		dwErrorFlags;
	OVERLAPPED	osRead;
	BOOL		bReadStatus;

	if(!isValid())
		return -1;

	memset(&osRead,0,sizeof(OVERLAPPED));
	osRead.hEvent = _hRdEvt;

	::ClearCommError(_hCom,&dwErrorFlags,&ComStat);
	if(!_bOvlap && !ComStat.cbInQue)
		return 0;

	dwBytesRead = nSize;

	if(ComStat.cbInQue)
		dwBytesRead = min(nSize, (DWORD)ComStat.cbInQue);

	bReadStatus = ::ReadFile(_hCom, pBuf, dwBytesRead, &dwBytesRead, (_bOvlap ? (&osRead) : NULL));
	if(!bReadStatus) //如果ReadFile函数返回FALSE
	{
		if(_bOvlap && GetLastError()==ERROR_IO_PENDING)
		{
			do{
				dwEventStat = ::WaitForSingleObject(osRead.hEvent, 200);
			}while(isValid() && dwEventStat == WAIT_TIMEOUT);

			if(dwEventStat == WAIT_OBJECT_0) //write done.
			{
				if(::GetOverlappedResult(_hCom, &osRead, &dwBytesRead, TRUE))
				{
					return dwBytesRead;
				}
			}	
		}

		ResetTx();

		return 0;
	}

	return dwBytesRead;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值