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

📄 portobj.cpp

📁 button of Xp style,provide some infterface of the button control!
💻 CPP
字号:
// PortObj.cpp: implementation of the CPortObj class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PortObj.h"

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

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


CPortObj::CPortObj()
{

	memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
 	memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
	m_hIDComDev = NULL;
	m_bOpened = FALSE;

	m_nErrCode = ERROR_SUCCESS;

}

CPortObj::~CPortObj()
{
	Close();
}


//取最后错误信息
void CPortObj::GetLastErrInfo( int& nErrCode,					
							   LPSTR *lpszErrInfo, 
							   int nSize)
{
	int nLen = 0;
	nLen = CString((char *)m_lpMsgBuf).GetLength();
	nLen = min(nLen, nSize);
	memcpy( lpszErrInfo,m_lpMsgBuf, nLen);
	nErrCode = m_nErrCode;
}

//取最后一次错误,并翻译
void CPortObj::GetAndFormatLastErr()							
{
	LocalFree( m_lpMsgBuf );
	m_nErrCode = GetLastError();
	FormatMessage( 
		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		FORMAT_MESSAGE_FROM_SYSTEM | 
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		m_nErrCode,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &m_lpMsgBuf,
		0,
		NULL 
		);
//	MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
}


BOOL CPortObj::Open( int nPort, 
					 int nBaud,
					 int nParity,
					 int nByteSize, 
					 int nStopBits )
{	
	char szPort[15];
	DCB dcb;
	COMMTIMEOUTS CommTimeOuts;

	wsprintf( szPort, "\\\\.\\COM%d", nPort );

	m_hIDComDev = CreateFile( szPort, 
		GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
		NULL );

	if( m_hIDComDev == NULL ) return FALSE ;

	memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
 	memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
	m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	

	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 5000;
	SetCommTimeouts( m_hIDComDev, &CommTimeOuts );

	memset( &dcb, 0, sizeof( DCB ) );
	dcb.DCBlength = sizeof( DCB );
	GetCommState( m_hIDComDev, &dcb );
	dcb.BaudRate = nBaud;
	dcb.ByteSize = nByteSize;
	dcb.Parity = nParity;
	dcb.StopBits = nStopBits;	//1个停止位
	dcb.fBinary = TRUE ;
	dcb.fParity = TRUE ;

	dcb.fDtrControl=DTR_CONTROL_DISABLE;
	dcb.fRtsControl=RTS_CONTROL_DISABLE;

    dcb. fOutxCtsFlow=FALSE;      // CTS output flow control 
    dcb. fOutxDsrFlow=FALSE;      // DSR output flow control 
    dcb. fDsrSensitivity=FALSE;   // DSR sensitivity 
    dcb. fTXContinueOnXoff=FALSE; // XOFF continues Tx 
    dcb. fOutX=FALSE;            // XON/XOFF out flow control 
    dcb. fInX=FALSE;             // XON/XOFF in flow control 
    dcb. fErrorChar=FALSE;       // enable error replacement 
    dcb. fNull=FALSE;            // enable null stripping 
    dcb. fAbortOnError=FALSE;     // abort reads/writes on error

	unsigned char ucSet;
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );

	if( !SetCommState( m_hIDComDev, &dcb ) ||
		!SetupComm( m_hIDComDev, 10000, 10000 ) ||
		m_OverlappedRead.hEvent == NULL ||
		m_OverlappedWrite.hEvent == NULL )
	{
		DWORD dwError = GetLastError();
		if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
		if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
		CloseHandle( m_hIDComDev );

		return( FALSE );
	}

	m_bOpened = TRUE;

	return( m_bOpened );
}


BOOL CPortObj::Close( void )
{

	if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );

	if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
	if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );

	CloseHandle( m_hIDComDev );

	m_bOpened = FALSE;
	m_hIDComDev = NULL;

//	MessageBox(NULL,"关闭","1",0);

	return( TRUE );

}

BOOL CPortObj::WriteCommByte( unsigned char ucByte )
{
	BOOL bWriteStat;
	DWORD dwBytesWritten;

	bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );

	if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) )
	{
		if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) 
		{
			dwBytesWritten = 0;
		}
		else
		{
			GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
			m_OverlappedWrite.Offset += dwBytesWritten;
		}
	}

	return( TRUE );

}

BOOL CPortObj::ChangeParity( int nParity )							//改变奇偶校验
{
	DCB dcb;
	GetCommState( m_hIDComDev, &dcb );
	if ( dcb.Parity != nParity )
	{
		dcb.Parity = nParity;
		if( !SetCommState( m_hIDComDev, &dcb ) ) 
			return FALSE;
	}
	return TRUE;
}


int CPortObj::SendData( const char *pDataBuf, int nSendLen )
{

	if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

	DWORD dwBytesWritten = 0;

	int i;
	for( i=0; i<nSendLen; i++ )
	{
		WriteCommByte( pDataBuf[i] );
		dwBytesWritten++;
	}

	return( (int) dwBytesWritten );

}

int CPortObj::GetPortBufDataLen( int *pnParityErrCode )
{
	if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
	
	DWORD dwErrorFlags;
	COMSTAT ComStat;
	
	ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
	
	if( pnParityErrCode != NULL ) *pnParityErrCode = dwErrorFlags;

	return (int) ComStat.cbInQue;
}

int CPortObj::ReadData( void *pDataBuf, int nBufSize )
{

	if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

	BOOL bReadStatus;
	DWORD dwBytesRead, dwErrorFlags;
	COMSTAT ComStat;

	ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
	if( !ComStat.cbInQue ) return( 0 );

	dwBytesRead = (DWORD) ComStat.cbInQue;
	if( nBufSize < (int) dwBytesRead ) dwBytesRead = (DWORD) nBufSize;

	bReadStatus = ReadFile( m_hIDComDev, pDataBuf, dwBytesRead, &dwBytesRead, &m_OverlappedRead );

	if( !bReadStatus )
	{
		if( GetLastError() == ERROR_IO_PENDING )
		{
			WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
			return( (int) dwBytesRead );
		}

		return( 0 );
	}

	return( (int) dwBytesRead );

}


///////////////////////////////////////////////////////////////////////////
CFFPortObj::CFFPortObj()
{
	CPortObj::CPortObj();

	m_nPort = 0;
	m_nBaud = 0;
	m_nParity = 0;
	m_nByteSize = 0;
	m_nStopBits = 0;
	
	m_bSharePort = FALSE;									//端口共享标志,如果允许共享,则多次打开时,进行引用计数
	m_bDataFrameAddr = FALSE;								//数据帧带有地址
	m_nAddrByteLen = 1;										//地址的长度
	
	m_nPortUserTotal = 0;									//端口引用计数

	m_nRxDataLen = 0;										//接收缓冲区字节长度
	m_nRxBufSize = 5000;									//接收缓冲区大小
//	char *m_pRxBuf = new char[5000];						//接收缓冲区指针
//	memset( m_pRxBuf, 0 ,5000 );
}

CFFPortObj::~CFFPortObj()
{
	Close();
	CPortObj::~CPortObj();
//	delete[] m_pRxBuf;
}

BOOL CFFPortObj::Open( int nPort, 
					  int nBaud,
					  int nParity,
					  int nByteSize, 
					  int nStopBits)				//打开端口
{
	if( IsOpened() )
	{
		if( m_bSharePort ) 
		{
			if( m_nPort != nPort 
				|| m_nBaud != nBaud
				|| m_nParity != nParity
				|| m_nByteSize != nByteSize
				|| m_nStopBits != nStopBits
				) 
				return FALSE;

			m_nPortUserTotal++;		//允许共享端口
			return TRUE;
		}
	}
	m_nPort = nPort;
	m_nBaud = nBaud;
	m_nParity = nParity;
	m_nByteSize = nByteSize;
	m_nStopBits = nStopBits;

	//计算字节间隔
	CalByteIntervalByBaud();

	return CPortObj::Open( nPort, nBaud, nParity, nByteSize, nStopBits );
}

void CFFPortObj::CalByteIntervalByBaud()
{
	float fFrameLen = 1.0f + m_nByteSize;
	switch( m_nStopBits )
	{
	case ONESTOPBIT:		// 1 stop bit 
		fFrameLen += 1.0f;
		break;
	case ONE5STOPBITS:		//1.5 stop bits 
		fFrameLen += 1.5f;
		break;
	case TWOSTOPBITS:		//2 stop bits
		fFrameLen += 2.0f;
		break;
	default:
		fFrameLen += 1.0f;
		break;
	}

	if( m_nParity != NOPARITY )
	{
		fFrameLen += 1.0f;
	}

	m_nByteInterval = (int)(BYTE_INTERVAL_CONST + (fFrameLen * 1000.0/m_nBaud));
}

void CFFPortObj::SetByteInterval( int nTime )
{
	m_nByteInterval = nTime;
	if( m_nByteInterval < BYTE_INTERVAL_CONST ) 
		m_nByteInterval = BYTE_INTERVAL_CONST;
}

BOOL CFFPortObj::Close()									//关闭端口
{
	if( !IsOpened() )
	{
		m_nPortUserTotal = 0;
		return TRUE;
	}

	if( !m_bSharePort ) return CPortObj::Close();

	//允许共享端口时,处理引用计数
	m_nPortUserTotal--; 
//	char TotalNumInfo[10];
//	sprintf(TotalNumInfo,"%d",m_nPortUserTotal);
//	MessageBox(NULL,TotalNumInfo,"1",0);
	if( m_nPortUserTotal <= 0 )	return CPortObj::Close();

	return TRUE;
}

int CFFPortObj::ReadData( void *pDataBuf, int nBufSize )		//读接收缓冲区数据
{

	//取串口缓冲区已经接收数据大小
	int nPortDataLen = GetPortBufDataLen();	
	char *pReadBufTemp = new char[nPortDataLen];

	//取串口缓冲区已经接收数据
	nPortDataLen = CPortObj::ReadData( pReadBufTemp,nPortDataLen );

	//将串口缓冲区数据放到自己的缓冲区
	int nByteRead = nPortDataLen;
	if( m_nRxDataLen + nPortDataLen >= m_nRxBufSize-1 )
	{
		nByteRead = m_nRxBufSize - m_nRxDataLen;
	}
	memcpy( &m_pRxBuf[m_nRxDataLen],pReadBufTemp, nByteRead);
	m_nRxDataLen += nByteRead;

	//将数据放到调用者的缓冲区
	nByteRead = m_nRxDataLen;
	if( nBufSize < m_nRxDataLen) nByteRead = nBufSize;
	memcpy( pDataBuf,m_pRxBuf, nByteRead);	
	
	delete pReadBufTemp;
	
	return nByteRead;
}

//发送数据
int CFFPortObj::SendData( const char *pDataBuf, int nSendLen )		
{
	return CPortObj::SendData( pDataBuf, nSendLen );
}

//改变奇偶校验
BOOL CFFPortObj::ChangeParity( int nParity )						
{
	return CPortObj::ChangeParity( nParity );
}

//取串口缓冲区字节长度
int CFFPortObj::GetPortBufDataLen( int *pnParityErrCode )		
{
	return CPortObj::GetPortBufDataLen( pnParityErrCode );
}

//取最后错误信息
void CFFPortObj::GetLastErrInfo( int& nErrCode,					
								LPSTR *lpszErrInfo, 
								int nSize)							

{
	CPortObj::GetLastErrInfo( nErrCode, lpszErrInfo, nSize );
}

//清除接收缓冲区
void CFFPortObj::ClearRxBuf()
{
	
	//取串口缓冲区已经接收数据大小
	int nPortDataLen = GetPortBufDataLen();	
	char *pReadBufTemp = new char[nPortDataLen];
	//清除串口缓冲区数据
	CPortObj::ReadData( pReadBufTemp,nPortDataLen );
	delete pReadBufTemp;

//	memset( m_pRxBuf, 0, m_nRxBufSize );
	m_nRxDataLen = 0;
	
	return;
}

//取接收缓冲区数据长度		
int CFFPortObj::GetRxBufDataLen()
{
	return( GetPortBufDataLen() + m_nRxDataLen );
}

void CFFPortObj::SetRxBufSize( int nSize )
{
//	delete m_pRxBuf;
	m_nRxDataLen = 0;										//接收缓冲区字节长度
	m_nRxBufSize = nSize;									//接收缓冲区大小
//	char *m_pRxBuf = new char[nSize];						//接收缓冲区指针
	memset( m_pRxBuf, 0 ,nSize );
	return;
}

BOOL CFFPortObj::SetShareMode( BOOL bSharePort )
{
	m_bSharePort=bSharePort;
	if( bSharePort )	//设置为共享
	{
		if( IsOpened() && m_nPortUserTotal <=0 )
		{
			m_nPortUserTotal++;
		}
	}	
	else	//设置为非共享
	{
		if( IsOpened() && m_nPortUserTotal>1 ) //如果已经打开了多个实例
		{
			return FALSE;
		}
	}

	return TRUE;
}


BOOL CFFPortObj::SendAndWaitReply(const char *pWriteBuf,	//发送缓冲区
								  int nWriteLen,			//发送长度
							      char *pReadBuf,			//接收缓冲区
							      int nReadBufSize,			//接收缓冲区大小
							      int& nReturnDataLen,		//接收到的返回数据长度
							      int nMaxWaitFirstByteTime)//最大等待时间
{
	int nAlreadyReceiveLen;
	BOOL bSuccess = FALSE;
	FASM_CLOCK ClkFirstByte;
	FASM_CLOCK ClkByteInterval;
	
	///////////////////////////////////////////////////////////////////////////////////
	//清除接收缓冲区
	ClearRxBuf();

	///////////////////////////////////////////////////////////////////////////////////
	//发送数据
	if( m_bDataFrameAddr)//数据帧带有地址
	{
		//发送地址帧
		ChangeParity( MARKPARITY ); //奇偶校验位为1
		if( !SendData( pWriteBuf,m_nAddrByteLen) ) return FALSE;
		
		Sleep(2);
		
		//发送数据帧
		ChangeParity( SPACEPARITY ); //奇偶校验位为0

		int iByteLen = nWriteLen - m_nAddrByteLen;
		if ( iByteLen > 0 )
		{
			if( !SendData( &pWriteBuf[m_nAddrByteLen], iByteLen) ) return FALSE;
		}
	}
	else
	{
		//发送数据
		if( !SendData( pWriteBuf,nWriteLen) ) return FALSE;
	}

	///////////////////////////////////////////////////////////////////////////////////
	//准备接收数据
	nAlreadyReceiveLen = 0;
	ClkFirstByte.Start();
	MSG Msg;
	while( TRUE )
	{
		//如果在指定时间内没有收到第一个字节,则返回FALSE
		if( ClkFirstByte.IsTimePass(nMaxWaitFirstByteTime) )
			return FALSE;
		::Sleep(10);
		//检索消息
		if(::PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE )	)
		{
			::TranslateMessage( &Msg );
			::DispatchMessage( &Msg );
		}
		
		nAlreadyReceiveLen = GetRxBufDataLen();
		if( nAlreadyReceiveLen>0 ) 
			break;
	}

	///////////////////////////////////////////////////////////////////////////////////
	//等待发送结束
	int nRxDataLenTemp = 0;
	BOOL bReceiveStop = FALSE;
	while( !bReceiveStop )
	{
		ClkByteInterval.Start();
		//等待下一个字节
		while(TRUE) 
		{
			//查询串口接收缓冲区内字节数
			nRxDataLenTemp = GetRxBufDataLen();
			if( nAlreadyReceiveLen < nRxDataLenTemp ) //在允许两个字节的时间间隔内收到了新的字符
			{
				nAlreadyReceiveLen = nRxDataLenTemp;
				break;
			}

			//判断是否已经接收结束,如果在允许两个字节的时间间隔内没有收到了新的字符,则认为结束了
			if( ClkByteInterval.IsTimePass(m_nByteInterval) ) 
			{
				bReceiveStop = TRUE;
				break;
			}
			::Sleep(1);
			//检索消息
			if(::PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE )	)
			{
				::TranslateMessage( &Msg );
				::DispatchMessage( &Msg );
			}
		}
	}
	
	///////////////////////////////////////////////////////////////////////////////////
	//将接收到的字节放到调用者制定的缓冲区
	nAlreadyReceiveLen = GetRxBufDataLen();
	nReturnDataLen = ReadData(pReadBuf, nReadBufSize);
		
	return TRUE;
}

⌨️ 快捷键说明

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