📄 comport.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 + -