串口类

// SerialPort.h: interface for the CSerialPort class.
//
//

#if !defined(AFX_SERIALPORT_H__BCE7D852_C6B1_4AEE_925C_1485DBF44011__INCLUDED_)
#define AFX_SERIALPORT_H__BCE7D852_C6B1_4AEE_925C_1485DBF44011__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxmt.h>

typedef struct
{
	DWORD	dwPortNum;			/*  端口号		 */
	DWORD	dwBaudRate;			/*  波特率		 */
	BOOL	bParity;			/*  奇偶校验类型 */
	DWORD	dwNumberOfDataBit;	/*  数据位数目	 */
	DWORD	dwNumberOfStopBit;	/*  停止位数目	 */
	BOOL	bFluxControlType;	/*  流控方式	 */
}SerialPortInfo;

class CSerialPort  
{
	public:
		CEvent				m_EventComPort;
		CEvent				m_EventPurge;
		CCriticalSection	m_SectionLock;
	public:
		CSerialPort();
	
		//初始化串口
		BOOL Init(SerialPortInfo* stPortInfo);

		//取得串口当前配置
		void  GetState(DCB& dcb);
		//配置串口
		void  SetState(DCB& dcb);

		//打开串口
		BOOL OpenPort(SerialPortInfo* stPortInfo);
		//关闭串口
		BOOL ClosePort();

		BOOL Purge();

		//下发数据
		BOOL Write(BYTE* pInBuf,DWORD dwBufLen,DWORD* pdwStatus);
		//接收数据
		BOOL Read(BYTE* pOutBuf,DWORD dwBufLen,DWORD *pdwRealLen,DWORD* pdwStatus);

		DWORD	GetAvailableDataLen();
		BOOL	BeginListenCommEvent();
		BOOL	WaiteForAEvent();

		//获取最近一个错误码
		BOOL GetPortStatus()
		{
			return m_bPortStatus;
		}

		//设置串口状态
		void SetPortStatus(BOOL bPortStatus)
		{
			m_bPortStatus = bPortStatus;
		}

		//获取串口状态
		DWORD GetLastErrorCode()
		{
			return m_dwLastErrorCode;
		}
	
		virtual ~CSerialPort();
	private:
		
		HANDLE m_hPortHandle;

		DWORD m_dwLastErrorCode;
		BOOL m_bPortStatus;
};

#endif // !defined(AFX_SERIALPORT_H__BCE7D852_C6B1_4AEE_925C_1485DBF44011__INCLUDED_)

// SerialPort.cpp: implementation of the CSerialPort class.
//
//

#include "stdafx.h"
#include "PortAccess.h"
#include "SerialPort.h"
#include "GloableDefine.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//
// Construction/Destruction
//

CSerialPort::CSerialPort()
{
	m_dwLastErrorCode = ERROR_CODE_NO_ERROR;
	m_bPortStatus = FALSE;
	m_hPortHandle = NULL;
}

CSerialPort::~CSerialPort()
{
	if (m_hPortHandle)
	{
		CloseHandle(m_hPortHandle);
	}
}

BOOL CSerialPort:: Init(SerialPortInfo* stPortInfo)
{
	BOOL bRet = TRUE;

	CString strPortName = "";
	strPortName.Format("\\\\.\\COM%d", stPortInfo->dwPortNum);
	try
	{
		m_hPortHandle = CreateFile(	strPortName,
									GENERIC_READ|GENERIC_WRITE,
									0,
									NULL,
									OPEN_EXISTING,
									FILE_FLAG_OVERLAPPED,
									NULL);
		if (INVALID_HANDLE_VALUE == m_hPortHandle)
		{
			m_dwLastErrorCode = ERROR_CODE_INIT_PORT_FAILD;
			bRet = FALSE;
		}
		
		SetCommMask(m_hPortHandle, EV_RXCHAR);
		
		DCB dcb;
		GetState(dcb);
		
		dcb.BaudRate		= stPortInfo->dwBaudRate;
		dcb.Parity			= NOPARITY;
		dcb.ByteSize		= 8;
		dcb.StopBits		= ONESTOPBIT;
		dcb.fDsrSensitivity = FALSE;
		dcb.fOutxCtsFlow	= FALSE;
		dcb.fOutxDsrFlow	= FALSE;
		dcb.fOutX			= FALSE;
		dcb.fInX			= FALSE;
		
		SetState(dcb);
	}
	catch (DWORD dwError)
	{
		m_dwLastErrorCode = dwError;
		bRet = FALSE;
	}

	if (bRet)
	{
		SetPortStatus(TRUE);
	}
	return bRet;
}

void  CSerialPort::GetState(DCB& dcb)
{
	if(GetCommState(m_hPortHandle, &dcb) == 0) //function failed
	{
		throw COMERR_GETSTATE;
	}
}
void  CSerialPort::SetState(DCB& dcb)
{
	if(SetCommState(m_hPortHandle, &dcb) == 0) //function failed
	{
		throw COMERR_SETSTATE;
	}
}

BOOL CSerialPort::Purge()
{
	if(m_hPortHandle != INVALID_HANDLE_VALUE)
	{
		m_EventPurge.SetEvent();		
		m_SectionLock.Lock();
		PurgeComm(m_hPortHandle, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
		m_SectionLock.Unlock();
	}
	return TRUE;
}

BOOL CSerialPort::Read(BYTE* pOutBuf,DWORD dwBufLen,DWORD *pdwRealLen,DWORD* pdwStatus)
{
	OVERLAPPED OverLap;
	DWORD dwNoUse;
	BOOL bRet;

	memset(&OverLap, 0, sizeof(OverLap));

	for(;;)
	{
		m_SectionLock.Lock();	//

		if(GetAvailableDataLen() >= dwBufLen)
		{
			break;
		}
		
		BeginListenCommEvent();

		for(;;)
		{
			try
			{
				m_SectionLock.Unlock();
				break;
			}
			catch(...)
			{
				m_dwLastErrorCode = ERROR_CODE_UNKNOW;
			}
		}

		if(WaiteForAEvent() == FALSE)
		{
			if(pdwRealLen)
			{
				*pdwRealLen = 0;
			}
			return TRUE;
		}
	}
	//!!注,上面的等待理论上是有漏洞的,如果操作系统的串口缓冲区长度不到dwBufferLen,
	//则这个等待将永远不会返回。
	//m_SectionLock.Lock();
	bRet = ReadFile(m_hPortHandle, pOutBuf, dwBufLen, &dwNoUse, &OverLap);

	if(FALSE == bRet)
	{
		//如果发生错误
		if(::GetLastError() != ERROR_IO_PENDING)
		{
			m_SectionLock.Unlock();
			return FALSE;
		}
		else
		{
			//如果读操作正在进行
			if(GetOverlappedResult(m_hPortHandle, &OverLap, &dwNoUse, TRUE) == FALSE)
			{
				m_SectionLock.Unlock();
				return FALSE;
			}
		}
	}

	m_SectionLock.Unlock();


	if(pdwRealLen)
	{
		*pdwRealLen = dwBufLen;
	}
	return TRUE;
}

BOOL CSerialPort::Write(BYTE* pInBuf,DWORD dwBufLen,DWORD* pdwStatus)
{
	OVERLAPPED OverLap;
	DWORD dwWriteLen, dwNoUse;	
	memset(&OverLap, 0, sizeof(OverLap));
	
	m_SectionLock.Lock();
	BOOL bRet = WriteFile(m_hPortHandle, pInBuf, dwBufLen, &dwWriteLen, &OverLap);
	
	if(FALSE == bRet)
	{
		if(::GetLastError() != ERROR_IO_PENDING)
		{
			m_SectionLock.Unlock();
			return FALSE;
		}
		if(GetOverlappedResult(m_hPortHandle, &OverLap, &dwNoUse, TRUE) == FALSE)
		{
			m_SectionLock.Unlock();
			return FALSE;
		}
	}
	m_SectionLock.Unlock();
	return TRUE;
}

BOOL CSerialPort::OpenPort(SerialPortInfo* stPortInfo)
{
	return Init(stPortInfo);
}

BOOL CSerialPort::ClosePort()
{
	if(m_hPortHandle != INVALID_HANDLE_VALUE)
	{
		CloseHandle(m_hPortHandle);
		m_hPortHandle = INVALID_HANDLE_VALUE;
		SetPortStatus(FALSE);
	}
	return TRUE;
}

DWORD CSerialPort::GetAvailableDataLen()
{
	COMSTAT ComState;
	DWORD dwError;
	
	BOOL bRet = ClearCommError(m_hPortHandle, &dwError, &ComState);
	if(FALSE == bRet)
	{
		return DWORD(0);
	}
	
	return ComState.cbInQue;
}

BOOL CSerialPort::BeginListenCommEvent()
{
	DWORD dwEvent;
	OVERLAPPED	OverLap;
	
	memset(&OverLap, 0, sizeof(OverLap));
	OverLap.hEvent = m_EventComPort.m_hObject;
	
	BOOL bRet = WaitCommEvent(m_hPortHandle, &dwEvent, &OverLap);
	if(FALSE == bRet)
	{
		if(::GetLastError() != ERROR_IO_PENDING)
		{
			return FALSE;
		}
	}
	
	return TRUE;
}

BOOL CSerialPort::WaiteForAEvent()
{
	DWORD dwRet;
	
	HANDLE hEvent[] = {HANDLE(m_EventComPort), HANDLE(m_EventPurge)};
	for(;;)
	{
		dwRet = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);
		
		if(dwRet - WAIT_OBJECT_0  == 1)
		{
			return FALSE;
		}
		else if(dwRet - WAIT_OBJECT_0  == 0)
		{
			return TRUE;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值