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

📄 commport.cpp

📁 ISP1160 for uCOS-II,使用于lpc2200系列芯片
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// CommPort.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "CommPort.h"

//----------------------------------------------------------------
//类构造函数
 CCommPort::CCommPort()
{
  hComm          = 0;
  m_eEvent         = EEventNone;
  m_hevtOverlapped = 0;
  lpszPort="COM1";		//初始化串口
  eBaudrates=EBaud9600;		//初始化波特率
  nFrameHead=0x12;
  nTimePerByte=1;
}
//---------------------------------------------------------------
//类析构函数
 CCommPort::~CCommPort ()
{
  Flush();

  if (hComm)
	ClosePort();
}
//---------------------------------------------------------------------------
//      串口属性设置函数
//入口参数:波特率、数据位、校验位、停止位
//函数功能:
//        一、设置波特率
//        二、设置数据位
//        三、设置较验位
//        四、设置停止位
//返回值:调用成功返回值为0;失败返回失败码
//--------------------------------------------------------------------------
int  CCommPort::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits)
{
	if (hComm ==0)
		return 102;	//操作串口时,串口未打开

	ZeroMemory(&m_dcb, sizeof (DCB));
	m_dcb.DCBlength	= sizeof (DCB);
	m_dcb.BaudRate = DWORD(eBaudrate);
	m_dcb.ByteSize = BYTE(eDataBits);
	m_dcb.Parity   = BYTE(eParity);
	m_dcb.StopBits = BYTE(eStopBits);
	m_dcb.fParity  = (eParity != EParNone);

	m_dcb.fBinary = 1;
	m_dcb.fDtrControl = 0;
	m_dcb.fRtsControl = 0;
	m_dcb.XonLim = 2048;
	m_dcb.XoffLim = 512;

	m_dcb.XonChar = 17;
	m_dcb.XoffChar = 19;

	if (!::SetCommState(hComm,&m_dcb))	//不能设置DCB结构
		return 202;
	return 0;
}
//-----------------------------------------------------------
//      超时设置函数
//入口参数:超时种类
//函数功能:
//        超时设置
//-----------------------------------------------------------
int  CCommPort::SetupReadTimeouts (int nBlockRead)
{
  if (hComm == 0)
        return 102;
  COMMTIMEOUTS cto;
  if (!::GetCommTimeouts(hComm,&cto))
        return 203;	//不能获得超时结构

  //设置超时结构
  if(!nBlockRead){
          cto.ReadIntervalTimeout = 0;
          cto.ReadTotalTimeoutConstant = 0;
          cto.ReadTotalTimeoutMultiplier =0;
  }else{
          cto.ReadIntervalTimeout = 0;
          cto.ReadTotalTimeoutConstant = 0;
          cto.ReadTotalTimeoutMultiplier =nBlockRead;
  }

  if (!::SetCommTimeouts(hComm,&cto))
        return 204;	//不能设置超时结构
  return 0;
}


//-----------------------------------------------------------------------------
//      写串口函数
//入口参数:所写数据缓冲区地址、所写数据长度、
//-----------------------------------------------------------------------------
int  CCommPort::Write ( BYTE* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
  DWORD dwWritten;
  if (pdwWritten == 0)
  	pdwWritten = &dwWritten;
  *pdwWritten = 0;

  if (hComm == 0)
	return 102;	//操作串口时,串口未打开

  OVERLAPPED ovInternal;
  if (lpOverlapped == 0){
	memset(&ovInternal,0,sizeof(ovInternal));
	ovInternal.hEvent = m_hevtOverlapped;
	lpOverlapped = &ovInternal;
  }

  if (!::WriteFile(hComm,pData,iLen,pdwWritten,lpOverlapped)){

	long lLastError = ::GetLastError();
	if (lLastError != ERROR_IO_PENDING)
			return 104;	//写串口出错

 	if (lpOverlapped == &ovInternal){
		switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)){

			case WAIT_OBJECT_0:
				if (!::GetOverlappedResult(hComm,lpOverlapped,pdwWritten,FALSE))
					return 104;	//写串口出错
				break;
			case WAIT_TIMEOUT:
				::CancelIo(hComm);
				return 104;	//读串口出错
			default:
				return 104;	//读串口出错
                }
        }
  }

  return 0;
}

//---------------------------------------------------------------------
//      读串口函数
//入口参数:所读数据存放地址、所读数据长度
//----------------------------------------------------------------------
int  CCommPort::Read (BYTE* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
  DWORD dwRead;
  if (pdwRead == 0)
	pdwRead = &dwRead;
  *pdwRead = 0;

  if (hComm == 0)
        return 102;	//操作串口时,串口已打开

  OVERLAPPED ovInternal;
  if (lpOverlapped == 0){
  	memset(&ovInternal,0,sizeof(ovInternal));
        ovInternal.hEvent = m_hevtOverlapped;
	lpOverlapped = &ovInternal;
  }

  if(!ReadFile(hComm,pData,iLen,pdwRead,lpOverlapped)){
  	long lLastError = ::GetLastError();
  	if (lLastError != ERROR_IO_PENDING)
		return 1031;	//读串口失败

  	if (lpOverlapped == &ovInternal){
		switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)){

			case WAIT_OBJECT_0:
                                {
				if (!::GetOverlappedResult(hComm,lpOverlapped,pdwRead,TRUE))
					return 1032;	//读串口失败
                                }
				break;

			case WAIT_TIMEOUT:
				::CancelIo(hComm);
				return 1033;	//读串口失败

			default:
				return 1034;	//读串口失败
                }
        }
  }

  return 0;
}

//-------------------------------------------------------------------------------
//      设置通信事件掩码
//函数功能:设置通信事件的掩码
//入口参数:    dwMask — 所要设置的事件掩码
//返回值:成功时,返回值为0;失败后,返回失败码
//-----------------------------------------------------------------------------
int  CCommPort::SetMask (DWORD dwMask)
{
  if (hComm == 0)
        return 102;	//操作串口时,串口没打开
  if (!::SetCommMask(hComm,EEventRecv))
        return 208;	//不能设置事件掩码
  return 0;
}
//-----------------------------------------------------------------------------

//      清除缓冲区函数
//函数功能:清除当前缓冲区所有已接收的数据或欲发送的数据
//入口参数:    无
//返回值:成功时,返回值为0;失败后,返回失败码
//-----------------------------------------------------------------------------
int  CCommPort::Flush()
{
  if (hComm == 0)
        return 102;	//操作串口时,串口没打开
  if (!::PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_TXABORT|PURGE_RXABORT))
        return 207;	//清除缓冲区出错
  return 0;
}

//-------------------------------------------------------------------------------
int   CCommPort::WaitEvent (BYTE* pAckBuff,int nTimeOuts)
{
  COMSTAT     ComStat;
  DWORD       dwErrorFlags;

  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:
                                ClearCommError(hComm,&dwErrorFlags,&ComStat);
                                if(ComStat.cbInQue == 0){
                                        ::CancelIo(hComm);
                                        return 209;	//监视串口出错
                                }
			default:
				return 209;	//监视串口出错
		}
	}else
	   	return 209;	//监视串口出错
  }//else
   	//return 0;

   CloseHandle(os.hEvent);

  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];


  //清空掩码
  SetCommMask(hComm,0);
  return 0;
}
//-------------------------------------------------------------------------------
//      设置帧头函数
//函数功能:设置通信时,命令/响应帧的帧头
//入口参数:    nHead — 帧头参数,值为0-255之间
//                    当   0<=nHead<0x40 时,    帧参数长度用1个字节表示,命令字符用1个字节表示
//                    当   0x40<=nHead<0x80 时, 帧参数长度用2个字节表示,命令字符用1个字节表示
//                    当   0x80<=nHead<0xC0 时, 帧参数长度用1个字节表示,命令字符用2个字节表示
//                    当   0xC0<=nHead<=0xFF 时,帧参数长度用1个字节表示,命令字符用1个字节表示
//返回值:设置成功后,返回值为TRUE; 否则返回值为FALSE
//-----------------------------------------------------------------------------

BOOL   CCommPort::SetFrameHead(int nHead)
{
 if(nHead>256||nHead<0)
        return FALSE;
 nFrameHead=nHead;
 return TRUE;
}

//-----------------------------------------------------------------------------

//	设置串口号函数
//函数功能:选择所要打开的串口号
//入口参数:    ePort — 串口号,1-4各代表COM1-COM4,其它值无意义.
//返回值:成功后,返回值为TRUE, 否则为 FALSE
//-----------------------------------------------------------------------------
BOOL  CCommPort::SetCommPort(int ePort)
{
  switch(ePort){
        case 1:
                lpszPort="COM1";
                break;
        case 2:
                lpszPort="COM2";
                break;
        case 3:
                lpszPort="COM3";
                break;
        case 4:
                lpszPort="COM4";
                break;
        case 5:
                lpszPort="COM5";
                break;
        case 6:
                lpszPort="COM6";
                break;
        default:
                lpszPort="COM1";
                return FALSE;
  }
  return TRUE;
}
//-----------------------------------------------------------------------------
//	设置通信波特率函数
//函数功能:设置通信过程中所使用的波特率
//入口参数:    eBaud — 波特率值,如9600代表9600bit/s
//返回值:成功后,返回值为TRUE, 否则为 FALSE
//-----------------------------------------------------------------------------

BOOL CCommPort::SetCommBaud(int eBaud)
{
  switch(eBaud){
        case 110:
                eBaudrates=EBaud110;
                break;
        case 300:
                eBaudrates=EBaud300;
                break;
        case 600:
                eBaudrates=EBaud600;
                break;
        case 1200:
                eBaudrates=EBaud1200;
                break;
        case 2400:
                eBaudrates=EBaud2400;
                break;
        case 4800:
                eBaudrates=EBaud4800;
                break;
        case 9600:
                eBaudrates=EBaud9600;
                break;
        case 14400:
                eBaudrates=EBaud14400;
                break;
        case 19200:
                eBaudrates=EBaud19200;
                break;
        case 38400:
                eBaudrates=EBaud38400;
                break;

⌨️ 快捷键说明

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