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

📄 serial.cpp

📁 VC类,标准串口类,无消息类型,用于工业控制中
💻 CPP
字号:
// Serial.cpp

#include "stdafx.h"
#include "serial.h"
#include "time.h"
#include "stdio.h"

CSerial::CSerial()
{

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

}

CSerial::~CSerial()
{

	Close();

}

BOOL CSerial::Open( int nPort, int nBaud )
{

	if( m_bOpened ) return( TRUE );

	char szPort[15];
	char szComParams[50];
	DCB dcb;

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

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

	wsprintf( szComParams, "COM%d:%d,n,8,1", nPort, nBaud );

	m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

	dcb.DCBlength = sizeof( DCB );
	GetCommState( m_hIDComDev, &dcb );

	dcb.BaudRate = nBaud;
	dcb.fParity = FALSE;
	dcb.fOutxCtsFlow = FALSE;
	dcb.fOutxDsrFlow = FALSE;
	dcb.fDtrControl = DTR_CONTROL_ENABLE;
	dcb.fDsrSensitivity = FALSE;
	dcb.fTXContinueOnXoff = FALSE;
	dcb.fOutX = FALSE;
	dcb.fInX = FALSE;
	dcb.fErrorChar = FALSE;
	dcb.fNull = FALSE;
	dcb.fRtsControl = RTS_CONTROL_ENABLE;
	dcb.fAbortOnError = FALSE;
	dcb.XonLim = 512;
	dcb.XoffLim = 1024;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	

	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 );
		}
	DWORD dwMask;
	if(GetCommMask(m_hIDComDev,&dwMask))
	{
		dwMask =dwMask | EV_RXCHAR ;
		if(!SetCommMask(m_hIDComDev,dwMask))
			return FALSE;
	}
	m_bOpened = TRUE;

	return( TRUE );

}

BOOL CSerial::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;

	return( TRUE );

}

BOOL CSerial::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 CSerial::WriteCommStr(const char* buf,int len )
{
	BOOL bWriteStat;
	DWORD dwBytesWritten;

	bWriteStat = WriteFile( m_hIDComDev, buf, len, &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;
		}
	}
	else
		return FALSE;
	return( TRUE );

}
int CSerial::SendData(const char *buffer, int size,int opt )
{

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


	DWORD dwBytesWritten = 0;
	int i;
	PurgeComm(m_hIDComDev,PURGE_TXCLEAR | PURGE_RXCLEAR);
	DWORD dwError;
	COMSTAT cs;
	ClearCommError(m_hIDComDev,&dwError,&cs);
	if(opt==0)
	{
		for( i=0; i<size; i++ ){
			WriteCommByte( buffer[i] );
			dwBytesWritten++;
			}
	}
	else
	{
		if(WriteCommStr(buffer,size))
			dwBytesWritten=size;
		else
			dwBytesWritten=0;

	}
	return( (int) dwBytesWritten );

}

int CSerial::ReadDataWaiting( void )
{

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

	DWORD dwErrorFlags;
	COMSTAT ComStat;

	ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

	return( (int) ComStat.cbInQue );

}

int CSerial::ReadData( void *buffer, int limit )
{

	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( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

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

	return( (int) dwBytesRead );

}

int CSerial::ReadEvent(char* buffer,int limit)
{
	DWORD nBytesRead,dwError;
	COMSTAT cs;	
	short rc=0;
	ClearCommError(m_hIDComDev,&dwError,&cs);
	if( !cs.cbInQue ) return( 0 );
	nBytesRead = (DWORD) cs.cbInQue;
	if( limit > (int) nBytesRead ) nBytesRead = (DWORD) limit;
	if(ReadFile(m_hIDComDev,buffer,nBytesRead ,&nBytesRead,&m_OverlappedRead))
		rc=(short)nBytesRead;
	else
		rc=0;
	return rc;
}

/*
int CSerial::ReadEvent(char* buffer,int limit)
{
	DWORD nBytesRead,dwEvent,dwError;
	COMSTAT cs;
	DWORD idx;
	short rc=0;
//	while(m_bReading){
	if(!WaitCommEvent(m_hIDComDev,&dwEvent,&m_OverlappedRead)){

		if(GetLastError()==ERROR_IO_PENDING)
		{
			
			idx=WaitForSingleObject(m_OverlappedRead.hEvent,3000);
			if(idx==WAIT_OBJECT_0)
			{
				//ResetEvent(m_OverlappedRead.hEvent);
				ClearCommError(m_hIDComDev,&dwError,&cs);
				if( !cs.cbInQue ) return( 0 );
				nBytesRead = (DWORD) cs.cbInQue;
				if( limit > (int) nBytesRead ) nBytesRead = (DWORD) limit;
				if((dwEvent & EV_RXCHAR) && cs.cbInQue ){
					if(ReadFile(m_hIDComDev,buffer,nBytesRead ,&nBytesRead,&m_OverlappedRead))
					{
						rc=(short)nBytesRead;
					}
					else
					{
						if( GetLastError() == ERROR_IO_PENDING ){
							WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
							rc= (short)nBytesRead ;
						}
						else
							rc=0;
					}
				}
			}
			else 
				rc=0;
		}
		else
			rc=0;
	}
	return rc;
}
*/

int CSerial::GetModemstatus()
{
	COMSTAT cs;
	int rc;
	DWORD ModemStatus=0,dwstatus;
	ClearCommError(m_hIDComDev,&dwstatus,&cs);
	if(GetCommModemStatus(m_hIDComDev,&ModemStatus))
	{
		if(!(ModemStatus & MS_RLSD_ON))
			rc=0;
		else
			rc=1;
	}
	else
		rc=-1;
	return rc;
}

short CSerial::InitialModem(int opt)
{
	ReadTillFound("ATZ\r",4,"OK",3);
	{
		switch(opt)
		{
		case 0:			//起呼拨号modem;
			ReadTillFound("ATE1V1Q0S0=0S7=40&C1&W\r",23,"OK",3);
			break;
		case 1:			//反向拨号MODEM;
			ReadTillFound("ATE1V1Q0S0=1&C1&W\r",18,"OK",3);
			break;
		case 2:
			break;
		}
	}
	return 0;
}
short CSerial::ReadTillFound(const char* cmd,int len,const char* endstr,int s)
{
	char retv[50];
	int retlen=0;
	short rc=-1;
	PurgeComm(m_hIDComDev,PURGE_TXCLEAR | PURGE_RXCLEAR);
	SendData(cmd,len,0);
	//int start=0,end=0;
	time_t end,start=time(0);
	while(1)
	{
		//end++;
		end=time(0);
		retlen=ReadData(retv,1);
		if(retlen>0)
		{
			if(strstr(retv,endstr)!=NULL)
			{
				rc=0;break;
			}
			else if(strstr(retv,"NO CARRIER")!=NULL)
			{
				HangupModem();
				m_bConnected=FALSE;
				break;
				//continue;
			}
			else if(strstr(retv,"BUSY")!=NULL)
			{
				HangupModem();
				m_bConnected=FALSE;
				break;
			}
		}
		else if(end-start>s)
		{
			rc=1;			//timeout;
			break;
		}
		end=time(0);
		Sleep(100);
	}
	return rc;
}

void CSerial::HangupModem()
{
	Sleep(1000);
	SendData("+++",3,0);
	Sleep(2000);
	SendData("ath0\r",5,0);
	Sleep(1000);
	
}
short CSerial::ModifyBaud(int port, int nbaud)
{
	DCB dcb;
	char msg[50];
	if(m_hIDComDev==NULL) 
	{
		m_bOpened=FALSE;
		return -1;
	}
	GetCommState(m_hIDComDev,&dcb);
	wsprintf(msg,"COM%d:%d,n,8,1",port,nbaud);
	if(BuildCommDCB(msg,&dcb))
	{
		if(SetCommState(m_hIDComDev,&dcb))
			return 0;
	}
	else
		return -1;
	return -1;
}

short CSerial::ReadModem(char *buffer, int limit)
{
	DWORD dwEvent; //,dwError;
//	COMSTAT cs;
//	DWORD idx;
	short rc=0;
	while(1)
	{
		if(WaitCommEvent(m_hIDComDev,&dwEvent,&m_OverlappedRead)){
			if(dwEvent & EV_RLSD)
			{
				rc=0;break;
			}
			else
				rc=1;
		}

/*
		ClearCommError(m_hIDComDev,&dwError,&cs);
		if( !cs.cbInQue ) return( 0 );
		nBytesRead = (DWORD) cs.cbInQue;
		if( limit > (int) nBytesRead ) nBytesRead = (DWORD) limit;
		if((dwEvent & EV_RXCHAR) && cs.cbInQue ){
			if(ReadFile(m_hIDComDev,buffer,nBytesRead ,&nBytesRead,&m_OverlappedRead))
				{
					rc=(short)nBytesRead;
				}
				else
				{
					if( GetLastError() == ERROR_IO_PENDING ){
						WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
						rc= (short)nBytesRead ;
					}
					else
					rc=0;
				}
			}
*/	}
	return rc;
}
BOOL CSerial::IsConnected()
{
	unsigned long st;
	GetCommModemStatus(m_hIDComDev, &st);
	if (!(st&MS_RLSD_ON))
		m_bConnected = FALSE;
	else
		m_bConnected=TRUE;
	return m_bConnected;

}/*
int CSerial::Connect(char* phone,LPCTSTR answer)
{
	int rc=-1,waitcnt=0;
	DWORD dwError;
	COMSTAT cs;	char msg[50];
	if(m_bConnected)
		HangupModem();
	//DWORD dwstatus;
	time_t end ,start;
//	GetCommModemStatus(m_hIDComDev,&dwstatus);
	sprintf(msg,"atdt%s\r\x00",phone);
	int len=strlen(msg);
	PurgeComm(m_hIDComDev,PURGE_TXCLEAR | PURGE_RXCLEAR);
//	ClearCommError(m_hIDComDev,&dwError,&cs);
	SendData((const char*)msg,len,0);
	start=time(0);
	DWORD dwEvent;

	waitcnt=0;
	while(1)
	{
		end=time(0);
		WaitCommEvent(m_hIDComDev,&dwEvent,&m_OverlappedRead);
		if(dwEvent & EV_RLSD)
		{
			m_bConnected=true;
			
			rc=0;
			break;
		}
		else if(end-start>=40)
		{
			m_bConnected=false;
			rc=1;
			break;
		}
		else
		{
			char c[50];
			if(ReadData(c,ReadDataWaiting())>0)
			{
				if(strstr(c,"BUSY")!=NULL)
				{
					rc=-1;
					break;
				}
				else if(strstr(c,"CARRIER")!=NULL)
				{
					rc=-1;break;
				}
				else if(strstr(c,"CONNECT")!=NULL)
				{
					rc=0; break;
				}
			}
		}
		Sleep(100);
		PurgeComm(m_hIDComDev,PURGE_RXCLEAR);
	}
	PurgeComm(m_hIDComDev,PURGE_RXCLEAR);
//	ResetEvent(m_OverlappedRead.hEvent);
	return rc;
}*/

int CSerial::Connect(char* phone,LPTSTR answer)
{
	int rc=4;
	char msg[50];
	
	if(m_bConnected)
		HangupModem();
	//DWORD dwstatus;
	time_t end ,start;
//	GetCommModemStatus(m_hIDComDev,&dwstatus);
	sprintf(msg,"atdt%s\r\x00",phone);
	int len=strlen(msg);
	PurgeComm(m_hIDComDev,PURGE_TXCLEAR | PURGE_RXCLEAR);
	SendData((const char*)msg,len,0);
	start=time(0);
	while(1)
	{
		end=time(0);
		if(IsConnected())
		{
			rc=0;
			break;
		}
		else if(end-start>=40)
		{
			rc=1;
//			SendData("ath0\r",5,1);
			break;
		}
		else if(end-start>=20)
		{
			char *c=(char*)answer;
			short rc=ReadEvent(c,1);
			rc=-1;
			if(rc>len)
				break;
		}
		Sleep(1000);
//		PurgeComm(m_hIDComDev,PURGE_RXCLEAR);
	}
	PurgeComm(m_hIDComDev,PURGE_RXCLEAR);
	return rc;
}

int CSerial::SendCmd(const char* cmd,int len)
{
	PurgeComm(m_hIDComDev,PURGE_RXCLEAR);

	if(SendData(cmd, len,1)==len)
		return 0;
	else
		return -1;
}

void CSerial::RTSControl(BOOL State)
{
  if(State)
	  EscapeCommFunction(m_hIDComDev,SETRTS);
  else
	  EscapeCommFunction(m_hIDComDev,CLRRTS);
}

⌨️ 快捷键说明

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