📄 commport.cpp
字号:
case 56000:
eBaudrates=EBaud56000;
break;
case 57600:
eBaudrates=EBaud57600;
break;
case 115200:
eBaudrates=EBaud115200;
break;
default:
eBaudrates=EBaud9600;
return FALSE;
}
nTimePerByte=10000/eBaud;
nTimePerByte+=1;
return TRUE;
}
//------------------------------------------------------------------
// 串口打开函数
//函数功能:
// 1、打开串口
// 2、调用读写缓冲区设置函数
// 3、调用串口串口忏悔设置函数
// 4、调用超时设置函数
//入口参数: 无
//返回值:成功后,返回值为0。否则返回失败码
//-----------------------------------------------------------------------------
int CCommPort::OpenPort (int nDataBit,int nStopBit,int nParity)
{
if (hComm)
return 102; //操作串口时,串口已打开
hComm = ::CreateFile(lpszPort,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE){
hComm = 0;
return 101; //不能打开串口
}
m_hevtOverlapped = ::CreateEvent(0,true,false,0);
if (m_hevtOverlapped == 0){
::CloseHandle(hComm);
hComm = 0;
return 200;
}
if (!::SetupComm(hComm,1024*64,1024*64)){
ClosePort();
return 205; //不能设置收发缓冲区
}
if(nDataBit<5||nDataBit>8)
nDataBit=8;
Setup(eBaudrates ,
EDataBits(nDataBit),
EParity(nParity),
EStopBits(nStopBit)
);
SetupReadTimeouts(0);
return 0;
}
//-----------------------------------------------------------------------------
//关闭串口函数
//----------------------------------------------------------------------------
//bR: 是否清DTR、RTS
void CCommPort::ClosePort (BOOL bR)
{
if (hComm == 0)
return ;
if(bR){
ClrDTR();
ClrRTS();
}
::CloseHandle(m_hevtOverlapped);
m_hevtOverlapped = 0;
::CloseHandle(hComm);
hComm = 0;
}
//-----------------------------------------------------------------------------
// 发送命令函数
//函数功能:发送PC机命令至单片机中,并读取单片机发回的响应信号。
//入口参数: pOrderBuff - 命令缓冲区指针
// pAckBuff - 响应缓冲区指针
// dwTimeOuts - 等待回应信息时的超时时间
//返回值:成功后,返回值为0; 失败后,返回相应错误码
//-----------------------------------------------------------------------------
int CCommPort::SendOrder(BYTE* pOrderBuff,BYTE* pAckBuff,int nTimeOuts)
{
int nWaitTime=nTimePerByte; //设置读串口超时系数
int nAndBgn=nFrameHead & 0xC0;
int nLen;
COMSTAT ComStat;
DWORD dwErrorFlags;
SetupReadTimeouts(20);
//判断此帧长度
switch(nAndBgn){
case 0x0: //当命令码长度为1、参数长度为1时
nLen=3+pOrderBuff[2];
break;
case 0x40: //当命令码长度为1、参数长度为2时
nLen=4+pOrderBuff[2]*256+pOrderBuff[3];
break;
case 0x80: //当命令码长度为2、参数长度为1时
nLen=4+pOrderBuff[3];
break;
case 0xC0: //当命令码长度为2、参数长度为2时
nLen=5+pOrderBuff[3]*256+pOrderBuff[4];
break;
}
if (!hComm)
return 102; //操作串口时,串口未打开
int CommEro=0;
Flush();
//发送命令
CommEro=Write (pOrderBuff,nLen,0,0,nWaitTime*nLen);
if(CommEro)
return CommEro;
//等回应
ClearCommError(hComm,&dwErrorFlags,&ComStat);
if(ComStat.cbInQue == 0){
CommEro=WaitEvent(pAckBuff,nTimeOuts);
}else{
int nThreshold=0;
int CommEro=0;
BYTE StartBuff=0x0;
while(StartBuff!=nFrameHead && nThreshold<3){
CommEro=Read(&StartBuff,1,0,0,300);
nThreshold++;
if(CommEro)
return 1;
}
pAckBuff [0]=StartBuff;
BYTE OrdAndLenBuff[4]={0x0};
int nAndBgn=nFrameHead & 0xC0;
int nAlreadyRead=0;
int nFrameLen=0;
//判断接收长度
switch(nAndBgn){
case 0x0: //当命令码长度为1、参数长度为1时
CommEro=Read(OrdAndLenBuff,2,0,0,nTimeOuts);
if(CommEro)
return CommEro;
pAckBuff[1]=OrdAndLenBuff[0];
pAckBuff[2]=OrdAndLenBuff[1];
nFrameLen=OrdAndLenBuff[1];
nAlreadyRead=3;
break;
case 0x40: //当命令码长度为1、参数长度为2时
CommEro=Read(OrdAndLenBuff,3,0,0,nTimeOuts);
if(CommEro)
return CommEro;
pAckBuff[1]=OrdAndLenBuff[0];
pAckBuff[2]=OrdAndLenBuff[1];
pAckBuff[3]=OrdAndLenBuff[2];
nFrameLen=OrdAndLenBuff[1]*256+OrdAndLenBuff[2];
nAlreadyRead=4;
break;
case 0x80: //当命令码长度为2、参数长度为1时
CommEro=Read(OrdAndLenBuff,3,0,0,nTimeOuts);
if(CommEro)
return CommEro;
pAckBuff[1]=OrdAndLenBuff[0];
pAckBuff[2]=OrdAndLenBuff[1];
pAckBuff[3]=OrdAndLenBuff[2];
nFrameLen=OrdAndLenBuff[1];
nAlreadyRead=4;
break;
case 0xC0: //当命令码长度为2、参数长度为2时
CommEro=Read(OrdAndLenBuff,4,0,0,nTimeOuts);
if(CommEro)
return CommEro;
pAckBuff[1]=OrdAndLenBuff[0];
pAckBuff[2]=OrdAndLenBuff[1];
pAckBuff[3]=OrdAndLenBuff[2];
pAckBuff[4]=OrdAndLenBuff[3];
nFrameLen=OrdAndLenBuff[2]*256+OrdAndLenBuff[3];
nAlreadyRead=5;
break;
}
BYTE *LeaveBuff;
LeaveBuff=new BYTE[nFrameLen];
CommEro=Read(LeaveBuff,nFrameLen,0,0,nTimeOuts);
if(CommEro)
return CommEro;
for(int i=0;i<nFrameLen;i++)
pAckBuff[i+nAlreadyRead]=LeaveBuff[i];
}
return CommEro;
}
//---------------------------------------------------------------------------
int CCommPort::SendData(BYTE* pOrderBuff,BYTE* pAckBuff,int nSendLen,int nTimeOuts,
int nRcv,BYTE cEnd,BOOL bIfRcv)
{
int nWaitTime=nTimePerByte; //设置读串口超时系数
if (!hComm)
return 102; //操作串口时,串口未打开
int CommEro=0;
Flush();
SetupReadTimeouts(nTimeOuts/nRcv+1);
//发送命令
CommEro=Write(pOrderBuff,nSendLen,0,0,nWaitTime*nSendLen);
if(CommEro)
return CommEro;
if(!bIfRcv)
return 0;
if(nTimeOuts<=0)
return 333; //用户设置参数出错
if(nRcv>0)
CommEro=Wait_Cnt(pAckBuff,nTimeOuts,nRcv);
else
CommEro=Wait_Byte(pAckBuff,nTimeOuts,cEnd);
return CommEro;
}
//---------------------------------------------------------------------------
int CCommPort::Wait_Cnt(BYTE* Buff,int nTimeOuts,int nRcvCnt)
{
int CommEro;
/*
BYTE byRcv;
for(int i=0;i<nRcvCnt;i++){
CommEro=Read(&byRcv,1,0,0,nTimeOuts/nRcvCnt+1);
if(!CommEro)
Buff[i]=byRcv;
else
break;
}
*/
CommEro=Read(Buff,nRcvCnt,0,0,nTimeOuts);
if(CommEro)
return CommEro;
return 0;
}
//----------------------------------------------------------------------------
int CCommPort::Wait_Byte(BYTE* Buff,int nTimeOuts,BYTE cEndByte)
{
DWORD dwEvtMask,dwTrans ;
OVERLAPPED os ;
memset( &os, 0, sizeof( OVERLAPPED ) ) ;
os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (os.hEvent == NULL)
return 1;
SetMask();
dwEvtMask=0;
if(!WaitCommEvent(hComm, &dwEvtMask, &os)){ // 重叠操作
if(GetLastError()==ERROR_IO_PENDING){
// 无限等待重叠操作结果
// GetOverlappedResult(hComm, &os, &dwTrans, true);
switch (::WaitForSingleObject(os.hEvent,nTimeOuts)){
case WAIT_OBJECT_0:
if (!::GetOverlappedResult(hComm,&os, &dwTrans, TRUE))
return 209; //监视串口出错
break;
case WAIT_TIMEOUT:
::CancelIo(hComm);
return 209; //监视串口出错
default:
return 209; //监视串口出错
}
}else
return 209; //监视串口出错
}
CloseHandle(os.hEvent);
//清空掩码
SetCommMask(hComm,0);
int CommEro=0;
BYTE EndBuff=0x0;
int nCurrentCnt=0;
int nCurrentWaitTime=nTimeOuts;
while(EndBuff!=cEndByte){
CommEro=Read(&EndBuff,1,0,0,nCurrentWaitTime);
Buff[nCurrentCnt]=EndBuff;
nCurrentCnt++;
nCurrentWaitTime=nCurrentWaitTime/nCurrentCnt+100;
if(CommEro)
return CommEro;
}
return 0;
}
//----------------------------------------------------------------------------
//在缓冲区中读取一数据
int CCommPort::ReadBlock(BYTE* pBuff,int nLen,int nTimeOuts)
{
SetupReadTimeouts(0);
COMSTAT ComStat;
DWORD dwErrorFlags;
ClearCommError(hComm,&dwErrorFlags,&ComStat);
if(ComStat.cbInQue)
return(Read(pBuff,nLen,0,0,nTimeOuts));
DWORD dwEvtMask,dwTrans ;
OVERLAPPED os ;
memset( &os, 0, sizeof( OVERLAPPED ) ) ;
os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (os.hEvent == NULL)
return 1;
SetMask();
dwEvtMask=0;
if(!WaitCommEvent(hComm, &dwEvtMask, &os)){ // 重叠操作
if(GetLastError()==ERROR_IO_PENDING){
// 无限等待重叠操作结果
// GetOverlappedResult(hComm, &os, &dwTrans, true);
switch (::WaitForSingleObject(os.hEvent,nTimeOuts)){
case WAIT_OBJECT_0:
if (!::GetOverlappedResult(hComm,&os, &dwTrans, TRUE))
return 209; //监视串口出错
break;
case WAIT_TIMEOUT:
::CancelIo(hComm);
return 209; //监视串口出错
default:
return 209; //监视串口出错
}
}else
return 209; //监视串口出错
}
CloseHandle(os.hEvent);
//清空掩码
SetCommMask(hComm,0);
return(Read(pBuff,nLen,0,0,nTimeOuts));
}
//----------------------------------------------------------------------------
HANDLE CCommPort::GetCommHandle()
{
return hComm;
}
//----------------------------------------------------------------------------
BOOL CCommPort::SetDTR()
{
if (hComm == 0)
return FALSE; //操作串口时,串口没打开
return(EscapeCommFunction(hComm,SETDTR));
}
//----------------------------------------------------------------------------
BOOL CCommPort::ClrDTR()
{
if (hComm == 0)
return FALSE; //操作串口时,串口没打开
return(EscapeCommFunction(hComm,CLRDTR));
}
//----------------------------------------------------------------------------
BOOL CCommPort::SetRTS()
{
if (hComm == 0)
return FALSE; //操作串口时,串口没打开
return(EscapeCommFunction(hComm,SETRTS));
}
//----------------------------------------------------------------------------
BOOL CCommPort::ClrRTS()
{
if (hComm == 0)
return FALSE; //操作串口时,串口没打开
return(EscapeCommFunction(hComm,CLRRTS));
}
//----------------------------------------------------------------------------
int CCommPort::CommWatch(int &nLen,BYTE* pBuff)
{
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError(hComm,&dwErrorFlags,&ComStat);
nLen=ComStat.cbInQue;
if(nLen>0)
return(Read(pBuff,nLen,0,0,10*nLen));
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -