⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comport.cpp

📁 《AVR单片机GCC程序设计》
💻 CPP
字号:
// ComPort.cpp: implementation of the CComPort class.
//	芯艺 (c) copyright 2004
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ComPort.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CComPort::CComPort()
{
	m_nCurrentCom=0;
	memset(&m_ovRead,0,sizeof(OVERLAPPED));
	memset(&m_ovWrite,0,sizeof(OVERLAPPED));
}

CComPort::~CComPort()
{
	m_strLastError.Empty();
}

BOOL CComPort::Open(int portnum)
{
	//如果要打开的端口号与当前打开的端口相同,返回
	if(m_nCurrentCom==portnum)
		return TRUE;

	Close();//关闭当前端口
	m_strLastError.Empty();

	if(m_ovRead.hEvent)
		ResetEvent(m_ovRead.hEvent);
	else
		m_ovRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

	if(m_ovRead.hEvent==NULL)
		return FALSE;

	if(m_ovWrite.hEvent)
		ResetEvent(m_ovWrite.hEvent);
	else
		m_ovWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
	if(m_ovWrite.hEvent==NULL)
		return FALSE;

	COMMTIMEOUTS TimeOuts;
	DCB dcb;
	CString strCom;
	strCom.Format("COM%d",portnum);

	m_hCom=CreateFile(strCom								//端口符号链接
		,GENERIC_READ|GENERIC_WRITE							//操作属性:读并写
		,0													//不共享
		,NULL												//无安全属性
		,OPEN_EXISTING										//打开现存文件,若不存在则返回失败
		,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED			//重叠操作
		,NULL												//无创建属性
		);

	if(m_hCom==INVALID_HANDLE_VALUE)
		return FALSE;

	SetupComm(m_hCom,1024,1024);//设置输入输出缓冲区

	/*
	在串行接收时相邻两个字节到达时间间隔的超时毫秒数
	在ReadFile函数中第一个字节到达后生效
	0为不使用
	*/
	TimeOuts.ReadIntervalTimeout=MAXWORD;

	/*
	下四个域设置读写的总超时时间	
	总超时时间计算方法:
	ReadTotalTimeoutConstant+(ReadTotalTimeoutMultiplier*读字节数)
	写类似读
	*/
	/*读超时设为0,使ReadFile立即返回*/
	TimeOuts.ReadTotalTimeoutConstant=0;
	TimeOuts.ReadTotalTimeoutMultiplier=0;

	TimeOuts.WriteTotalTimeoutConstant=2000;
	TimeOuts.WriteTotalTimeoutMultiplier=50;

	SetCommTimeouts(m_hCom, &TimeOuts);//设置超时

	if(!GetCommState(m_hCom,&dcb))
	{
		Close();
		return FALSE;
	}
	dcb.fBinary=TRUE;//二进制方式,WINDOWS API只支持此方式
	dcb.BaudRate=9600;
	dcb.ByteSize=8;
	dcb.fParity=FALSE;//校验禁止

	SetCommState(m_hCom,&dcb);

	m_nCurrentCom=portnum;
	return TRUE;
}

void CComPort::Close()
{
	if(m_nCurrentCom)
		CloseHandle(m_hCom);
	m_nCurrentCom=0;
}

//同步写入操作
UINT CComPort::Write(UCHAR *buf, UINT len)
{
	DWORD length=len;
	COMSTAT ComStat;
	DWORD dwErrorFlags;

	ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
	
	if(WriteFile(m_hCom,buf,length,&length,&m_ovWrite)==0)
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			GetOverlappedResult(m_hCom,&m_ovWrite,&length,TRUE);// 等待
		}
		else
			length=0;
	}
	return length;
}

//异步读取操作 反回:0:成功 1:超时 2:I/O错误 [3:用户取消,pEvent[1]设置用户取消事件时可用]
UINT CComPort::Read(UCHAR *buf, UINT len , DWORD timeout)
{
	DWORD WaitResult;
	HANDLE pEvent[2];

	pEvent[0]=m_ovRead.hEvent;

	DWORD length;
	ClearCommError(m_hCom,&length,NULL);
	length=0;
	ResetEvent(m_ovRead.hEvent);

	if(!ReadFile(m_hCom,buf,len,&length,&m_ovRead))
	{
		if(GetLastError()==ERROR_IO_PENDING) //重叠操作返回
		{
			//等待接收数据、取消操作和超时
			WaitResult=WaitForMultipleObjects(1,pEvent,FALSE,timeout);
			if(WaitResult==0)
			{
				GetOverlappedResult(m_hCom, &m_ovRead,&length, FALSE) ; 
				m_strLastError.Empty();
			}
			else if(WaitResult==WAIT_TIMEOUT)//超时
			{
				m_strLastError="\r\n通信超时";
				return 1;
			}
			else if(WaitResult==WAIT_FAILED)
			{
				m_strLastError="\r\n当前端口不可用";
				return 2;
			}

		}
		else//I/O错误
		{
			m_strLastError="\r\n当前端口不可用";
			return 2;
		}
	}
	return 0;
}

void CComPort::GetError(CString &str)
{
	str=m_strLastError;
	m_strLastError.Empty();
}

void CComPort::ClearBuffer()
{
	if(m_nCurrentCom>0)
		PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -