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

📄 yscomm.cpp

📁 VisualC++通信编程工程实例精解 Chapter 2 Example 1 MSCOMM控件编程实例 Example 2 基于Windows API的虚拟终端实现 Example 3
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  dcb.StopBits = ONESTOPBIT;  // one stop bit
  dcb.fAbortOnError=FALSE;

  //dcb.EofChar=1;
	//dcb.fRtsControl=DTR_CONTROL_DISABLE;
  if(m_bSemiduplex)
	dcb.fRtsControl=RTS_CONTROL_TOGGLE;//半双工
  else dcb.fRtsControl=RTS_CONTROL_ENABLE;//用来控制modem

  SetupComm(m_hFileHandle,2048,2048);//setup comm buffer size

  /*  COMMTIMEOUTS  TimeOuts;
	//Setup timeout
	TimeOuts.ReadIntervalTimeout=MAXDWORD; 
	TimeOuts.ReadTotalTimeoutMultiplier=0; 
	TimeOuts.ReadTotalTimeoutConstant=0; 
	TimeOuts.WriteTotalTimeoutMultiplier=100; 
	TimeOuts.WriteTotalTimeoutConstant=1000;
	SetCommTimeouts(m_hFileHandle, &TimeOuts);
*/

  Purge(PURGE_ALL);
  fSuccess = SetCommState(m_hFileHandle, &dcb);


  if (!fSuccess) 
  {
      // Handle the error.
      TRACE(_TEXT("SetCommState failed with error %d.\n"), GetLastError());
      return FALSE;
  }
//  EscapeCommFunction(m_hFileHandle,CLRRTS);//半双工
  return TRUE;
}

/*************************2001.10.31 ycat *********************************************
FUNCTION: BOOL CYsComm::SetEvent(DWORD dwEvent)

PURPOSE: 设置要等待的串口事件

PARAMETERS:
		dwEvent:要等待的事件

		EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\
		EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY 

RETURN VALUE: 
		TRUE表示操做成功,FALSE表示操作失败

COMMENTS: 目前只支持一种状态,说明见下一WaitEvent()
*********************************************************************************/
BOOL CYsComm::SetEvent(DWORD dwEvent)
{
	return SetCommMask(m_hFileHandle,dwEvent);
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::WaitEvent(DWORD* pwdEvent,DWORD dwTimeOut)

PURPOSE: 等待收到某个串口事件

PARAMETERS:
		pwdEvent:所等到的事件
		dwTimeOut:超时设置

RETURN VALUE: 
    -1: 除timeout外其它错误
	 1:等待成功
	-2: 表示timeout

COMMENTS: 
		Note   The Microsoft Win32 SDK Knowledge Base documents 
	a problem with Windows 95 and the EV_RING flag.
	The above code never returns in Windows 95 because
	the EV_RING event is not detected by the system;
	Windows NT properly reports the EV_RING event.
	Please see the Win32 SDK Knowledge Base for more 
	information on this bug.

		There are two interesting side effects of SetCommMask
	and WaitCommEvent. First, if the communications port 
	is open for nonoverlapped operation, WaitCommEvent 
	will be blocked until an event occurs. 

		If another thread calls SetCommMask to set a new event mask,
	that thread will be blocked on the call to SetCommMask. 
	The reason is that the original call to WaitCommEvent 
	in the first thread is still executing. 

		The call to SetCommMask blocks the thread until
	the WaitCommEvent function returns in the first 
	thread. This side effect is universal for ports
	open for nonoverlapped I/O. If a thread is blocked
	on any communications function and another thread
	calls a communications function, the second thread
	is blocked until the communications function returns 
	in the first thread. 

		The second interesting note about
	these functions is their use on a port open for overlapped 
	operation. If SetCommMask sets a new event mask,
	any pending WaitCommEvent will complete successfully,
	and the event mask produced by the operation is NULL.

	如果用重叠IO,则SetCommMask使正在等待的WaitCommEvent马上返回,
	而且返回的事件为NULL

	出错时返回负数,但DWORD为无符号数,会不会出问题?
	目前只支持等待一个事件
**********************************************************************/
int CYsComm::WaitEvent(DWORD* pwdEvent,DWORD dwTimeOut)
{
	  if(m_hFileHandle==NULL) return -1;
	  DWORD nRet;
	  DWORD dwRes;
	  DWORD dwOvRes;
	  int i;
	  
//	  if(!SetCommMask(m_hFileHandle,EV_RXCHAR))
//		  return -1;//清除以前事件
	 // WaitCommEvent(m_hFileHandle,pwdEvent,NULL);

      // Issue a status event check if one hasn't been issued already.
      if (WaitCommEvent(m_hFileHandle,pwdEvent,&m_overlappedEvent))
	  {
            // WaitCommEvent returned immediately.
            // Deal with status event as appropriate.
            DoStateEvent(*pwdEvent); 
			nRet=1;
			goto Exit;
      }

	  i=GetLastError();
	  // error in WaitCommEvent; abort
      if (i!= ERROR_IO_PENDING)
	  {
		  nRet=-1;
		  TRACE(_TEXT("GetlastError %d\n"),i);
		  goto Exit;
	  }
      // Check on overlapped operation.
      // Wait a little while for an event to occur.
      dwRes = WaitForSingleObject(m_overlappedEvent.hEvent, dwTimeOut);
      switch(dwRes)
       {
        // Event occurred.
	       case WAIT_OBJECT_0: 
                if (GetOverlappedResult(m_hFileHandle,&m_overlappedEvent,&dwOvRes,FALSE))
				{
                    // Status event is stored in the event flag
                    // specified in the original WaitCommEvent call.
                    // Deal with the status event as appropriate.
                    DoStateEvent(*pwdEvent);
					nRet=1;
					goto Exit;
				}
				else 
				{
                    // An error occurred in the overlapped operation;
                    // call GetLastError to find out what it was
                    // and abort if it is fatal.
					TRACE(_TEXT("An error occurred in the overlapped operation\nGetLastError is %d\n "),
						GetLastError());
					nRet=-1;
					goto Exit;
				}
                break;
             case WAIT_TIMEOUT:
				nRet=-2;
				goto Exit;
                break;                       
             default:
				nRet=-1;
				goto Exit;
         }
Exit:
	return nRet;
}
/*
对串口事件进行处理,还要修改
返回值无意义
*/
BOOL CYsComm::DoStateEvent(DWORD dwEvtMask)
{
	if(dwEvtMask==NULL) return TRUE;
//dwEvtMask可能会为NULL
		if (dwEvtMask & EV_BREAK) //检测到转入的中止
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_BREAK,m_nPort);
		}
		if (dwEvtMask & EV_CTS) //CTS (清除发送)信号改变状态
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_CTS,m_nPort);
		}
		if (dwEvtMask & EV_DSR) //DSR (数据设置就绪) 信号改变状态
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_DSR,m_nPort);
		}
		if (dwEvtMask & EV_ERR) //发生线路状态错误
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_ERR,m_nPort);
		}
		if (dwEvtMask & EV_RING)//检测到振铃
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RING,m_nPort);
		}
		if (dwEvtMask & EV_RLSD)//RLSD(接收线路信号检测)信号改变状态
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RLSD,m_nPort);
		}
		if (dwEvtMask & EV_RXCHAR)//收到一个字符,并放入输入缓冲区
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RXCHAR,m_nPort);
		}
		if (dwEvtMask & EV_RXFLAG) //收到事件字符(DCB结构的EvtChar成员),并放入输入缓冲区
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RXFLAG,m_nPort);
		}
		if (dwEvtMask & EV_TXEMPTY)//输出缓冲区最后一个字符发送出去
		{
			if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_TXEMPTY,m_nPort);
		}
	return TRUE;
}

//一个例子,供参考
/*************************2001.10.30 ycat *********************************************
FUNCTION: UINT CATModem::ReadCommThread(LPVOID pParam)

PURPOSE: 线程函数,把串口读入缓冲区的字符,写到自己维护的缓冲区中,并判断断线

PARAMETERS:
		pParam:指向CATModem类

RETURN VALUE:

COMMENTS: 断线的处理,也许还要改进
**********************************************************************/


/*************************2001.11.06 ycat *********************************************
FUNCTION: int CYsComm::ReadComm(
						PBYTE pByteRead,
						DWORD dwCount,
						DWORD* dwHaveReaded,
						DWORD nTimeOut)

PURPOSE: 在dwReadTimeOut里读到dwCount个字符,既使超时,
		 在缓冲区里也有在超时之前读出来的数据

PARAMETERS:
		pByteRead:			存放返回数据的字符串缓冲区
		dwCount:			希望要读到的字符个数
		dwHaveReaded:		已经读到的数据
		dwReadTimeOut:		超时的时间

RETURN VALUE:
	   -1: 除-2,-3之外的其它错误
		1:表示写com口成功
		-2:表示超时
		-3: 表示读操作被停止


COMMENTS:
        不能支持多线程

		即使没有读够dwCount个数,缓冲区里的字符仍然有效

		注意和ReadIn()的区别
**********************************************************************/
/*int CYsComm::ReadComm(PBYTE pByteRead,DWORD dwCount,
			DWORD* dwHaveReaded,DWORD nTimeOut)
{
	int nRet;
	DWORD dwTimeAfter;
	DWORD dwTimeUsed;
	DWORD dwTimeBefore;

	for(DWORD i=0;i<dwCount;i++)
	{
		dwTimeBefore=GetTickCount();
		nRet=ReadIn(pByteRead+i,1,nTimeOut);

		if(nRet==-2)//超时
		{
		//	TRACE(_TEXT("ReadComm Timeout %ld \n"),nTimeOut);
			goto Exit;
		}
		else if(nRet!=1) //出错
		{
			TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
			goto Exit;
		}

		dwTimeAfter=GetTickCount();
		dwTimeUsed=dwTimeAfter-dwTimeBefore;

		if(dwTimeUsed>nTimeOut)
		{
			if(i<dwCount)
			{
				nRet=-2;//TimeOut
				goto Exit;
			}
			else 
			{
				nRet=1;
				goto Exit;
			}
		}
		//计算剩下的时间
		nTimeOut-=dwTimeUsed;
	}
	nRet=1;
Exit:
	*dwHaveReaded=i;
	return nRet;
}
*/
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::ReadComm(PBYTE buffer,
			DWORD dwRead,
			LPDWORD pdwReaded,
			DWORD dwStartTimeOut,
			DWORD dwInterTimeOut)

PURPOSE: 读从dwStartTimeOut时间开始,以dwInterTimeOut为时间间隔,
		的字符


PARAMETERS:
			buffer:			缓冲区
			dwRead:			希望读到的长度
			pdwReaded:		实际读到的长度
			dwStartTimeOut:	最大的开始读数等待时间
			dwInterTimeOut:	读每个字符之间的等待时间

RETURN VALUE:
	   -1: 除-2,-3之外的其它错误
		1:表示写com口成功
		-2:表示超时
		-3: 表示读操作被停止

COMMENTS:
		有两种超时可能

		即使超时,缓冲区里的字符串仍然有效
	
		读出缓冲区里的数据,时间处理有问题? 有待测试
	希望读到的长度读到时,是否正常? 有待测试
**********************************************************************/
int CYsComm::ReadComm(PBYTE pByteRead,
			DWORD dwCount,
			LPDWORD dwHaveReaded,
			DWORD dwStartTimeOut,
			DWORD dwInterTimeOut)
{
	int nRet;
	DWORD dwTimeAfter;
	DWORD dwTimeUsed;
	DWORD dwTimeBefore;
	DWORD i=0;

	nRet=ReadIn(pByteRead+i,1,dwStartTimeOut);
	if(nRet!=1)
	{
		TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
		goto Exit;
	}

	for(i=1;i<dwCount;i++)
	{
		dwTimeBefore=GetTickCount();
		nRet=ReadIn(pByteRead+i,1,dwInterTimeOut);
		if(nRet!=1)
		{
			TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
			goto Exit;
		}
		dwTimeAfter=GetTickCount();
		dwTimeUsed=dwTimeAfter-dwTimeBefore;

		if(dwTimeUsed>dwInterTimeOut)
		{
			if(i<dwCount)
			{
				nRet=-2;//TimeOut
				goto Exit;
			}
			else 
			{
				nRet=1;
				goto Exit;
			}
		}
		//计算剩下的时间
		dwInterTimeOut-=dwTimeUsed;
	}
	nRet=1;
Exit:
	*dwHaveReaded=i;
	return nRet;
}
BOOL CYsComm::StopRead()
{
	return PulseEvent(m_hStopReadEvent);
}
BOOL CYsComm::StopWrite()
{
	return PulseEvent(m_hStopWriteEvent);
}

int CYsComm::ReadComm(PBYTE lpszInputBuffer,DWORD dwCountoByte,
			DWORD* dwHaveReaded,DWORD dwReadTimeOut)
{
	if ( m_hFileHandle == NULL)
	{
		TRACE(_TEXT("m_hFileHandle error.\n"));
		return -1;
	}
	int nRet;
    DWORD dwLastError;
    DWORD dwHandleSignaled;
    HANDLE HandlesToWaitFor[2];
	int iWait=2;
   // HandlesToWaitFor[0] = g_hCloseEvent;//为了支持多线程
	//OVERLAPPED o={0};
	//o.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
	
    HandlesToWaitFor[0] = m_overlappedRead.hEvent;
	HandlesToWaitFor[1] = m_hStopReadEvent;


	if (ReadFile((HANDLE)m_hFileHandle, 
		(LPVOID)lpszInputBuffer,
		(DWORD)dwCountoByte,
		(LPDWORD)dwHaveReaded,
		(LPOVERLAPPED)&m_overlappedRead))
	{  // This would only happen if there was data waiting to be read.
		
	//	TRACE(_TEXT("there waw data waiting to be read.\n");
		nRet=1;
		goto Exit;
	}
	// ReadFile failed.  Expected because of overlapped I/O.
	dwLastError = GetLastError();
	
	// Its possible for this error to occur if the 
	// service provider has closed the port.  Time to end.
	if (GetLastError()!= ERROR_IO_PENDING)
	{
		TRACE(_TEXT("Error to reading to CommFile %x\n"),dwLastError);
		nRet=-1;
		goto Exit;
	}
	
	// This is the expected ERROR_IO_PENDING case.
	
	// Wait for either overlapped I/O completion,
	// or for the CloseEvent to get signaled.
	dwHandleSignaled = 
		WaitForMultipleObjects(iWait,HandlesToWaitFor, 
		FALSE,dwReadTimeOut);
	switch(dwHandleSignaled)
	{
	case WAIT_OBJECT_0 : // Wait finished.
		{
			// Time to get the results of the WriteFile
			break;
		}
	case WAIT_OBJECT_0+1 : // Wait finished.
		{
			TRACE(_TEXT("stop read event set\n"));
			nRet=-3;
			goto Exit;
		}		
	case WAIT_TIMEOUT :
		{
//			TRACE(_TEXT("read time out\n"));
			nRet=-2;
			goto Exit;
		}
		
	case WAIT_FAILED: // Wait failed.  Shouldn't happen.
		{
			TRACE(_TEXT("read WAIT_FAILED: \n "));

			nRet=-1;
			goto Exit;
		}
		
	default: // This case should never occur.
		{
			TRACE(_TEXT("Unexpected Wait return value '%x'"),dwHandleSignaled);
			nRet=-1;
			goto Exit;			
		}
	}
	
	if (GetOverlappedResult(m_hFileHandle,
		&m_overlappedRead,dwHaveReaded, FALSE))
    {
		nRet=1;
		goto Exit;
	}
	else
	{
		//cause by Purge(PURGE_RXABORT)
		TRACE(_TEXT("read operation error \n "));
		nRet=-1;
	}
Exit:
/*	if(nRet==1)
	{
		for(UINT i=0;i<*dwHaveReaded;i++)
		TRACE("@@@ %x  %c @@@\n",lpszInputBuffer[i],lpszInputBuffer[i]);
	}//test*/
	if(nRet!=1) Purge(PURGE_RXABORT);//取消读操作
	return nRet;
}


⌨️ 快捷键说明

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