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

📄 rs232.cpp

📁 简单的 RS232 串口通信测试程序,可以做到资料的传送与接收
💻 CPP
字号:
#include "stdafx.h"
#include "RS232.h"

C_RS232 ::
	C_RS232(BYTE* DeviceCount, char* Namen, COMM_SIGNAL OnSignal, COMM_ERROR OnError)
{
	//unter Win NT w鋜en theoretisch 255 Com-Ports m鰃lich
	//testen welche existieren und/oder noch frei sind

	char* Testname		= new char[MAX_PATH];
	memset(&m_Handles.name[0],0x00,MAX_PATH);
	memset(&m_dcb,0x00,sizeof(DCB));
	
	*DeviceCount		= 0;
	m_Signal			= OnSignal;
	m_CommError			= OnError;
	m_Handles.hHandle	= 0;
	m_SignalEvents		= 0;
	m_ThreadEvent		= 0;
	m_Timeout			= 0;
	m_Read				= 0;
	m_Write				= 0;
	m_EventThread		= 0;
	m_FlowControl		= 0;
	
	for (int i = 1; i < 256; i++)
	{
		memset(&Testname[0],0x00,MAX_PATH);
		sprintf(&Testname[0],"Com%d",i);
		m_Handles.hHandle = CreateHandle(Testname, true, 0);
		if (Enabled(m_Handles.hHandle))
		{
			strcat(Namen,"[");
			strcat(Namen,Testname);
			strcat(Namen,"];");
			DestroyHandle(&m_Handles.hHandle);
			*DeviceCount += 1;
		};
	};
	sprintf(Namen,"%s (%d freie Schnittstellen)",Namen,*DeviceCount);
	delete Testname;
}

C_RS232 ::
	~C_RS232()
{
	if (Enabled(m_Handles.hHandle))
		DestroyHandle(&m_Handles.hHandle);
}

void C_RS232 ::
	ReturnLastErrorMsg(unsigned long Code, char* Msg)
{
	char sMsg[MAX_PATH];
	memset(&sMsg[0],0x00,MAX_PATH);
	memset(&Msg[0],0x00,MAX_PATH);
	if (!FormatMessage(	FORMAT_MESSAGE_FROM_SYSTEM,
					    NULL,
                        Code,
                        LANG_NEUTRAL, // Default language
                        sMsg,
                        MAX_PATH-1,
                        NULL
                      ))
		strcpy(Msg,"FormatMessage failed.");
	else
		strncpy(Msg,sMsg,strlen(sMsg)-2);
}
/***************************************************************************************************/
//Dataconrol-Block
/***************************************************************************************************/
DCB	C_RS232 ::
	GetDataControlBlock(HANDLE hHandle)
{
	if (Enabled(hHandle))
	{
		memset(&m_dcb,OFF,sizeof(m_dcb));
		GetCommState(hHandle, &m_dcb);
	};
	return m_dcb;
}

BOOL C_RS232 ::
	UpdateDataControlBlock(HANDLE hHandle, BYTE Baud, BYTE Size, BYTE StpBits, BYTE Parity)
{
	if (Enabled(hHandle))
	{
		GetCommState(hHandle, &m_dcb);
		m_dcb.BaudRate	= (1 << Baud)*300;
		m_dcb.ByteSize	= Size+4;
		m_dcb.StopBits	= StpBits;
		m_dcb.Parity	= Parity;
		
		m_dcb.DCBlength	= sizeof(m_dcb);
		switch(m_FlowControl)
		{
		case NONE:	m_dcb.fBinary	= ON; //Clear all flags
			break;
		case CTS:	
			{
				m_dcb.fOutxCtsFlow	= ON;
				m_dcb.fRtsControl	= ON;
				break;
			};
		case DTR:	
			{
				m_dcb.fOutxDsrFlow	= ON;
				m_dcb.fDtrControl	= ON;
				break;
			};
		case SWR:	
			{
				m_dcb.fOutX			= ON;
				m_dcb.fInX			= ON;
				break;
			};
		default: m_dcb.fBinary		= ON;
		};
		if (!SetCommState(hHandle, &m_dcb))
		{
			if (Assigned(m_CommError))
				m_CommError(hHandle,GetLastError(),DCBERRORSTRING);
			return FALSE;
		}
		else 
			return TRUE;
	};
	m_CommError(hHandle,GetLastError(),INVALIDHANDLESTRING);
	return FALSE;
}

/***************************************************************************************************/		
//Ereignisse anzeigen (J/N)
/***************************************************************************************************/
DWORD WINAPI OnComEvent(LPVOID pParam)
{
	DWORD			WaitableEvents = EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;
	COMMTIMEOUTS	lpCommTimeouts;
	OVERLAPPED		Overlapped		= {0};
	BOOL			IsSignaled		= FALSE;
	C_RS232*		seriell			= (C_RS232*)pParam;
	memset(&lpCommTimeouts,seriell->m_Timeout,sizeof(COMMTIMEOUTS));
	
	//alle hineinmaskieren und default timeout verwenden
	if	((!SetCommMask(seriell->m_Handles.hHandle, WaitableEvents))
	||	(!SetCommTimeouts(seriell->m_Handles.hHandle,&lpCommTimeouts)))
		goto ShowFailure;
	
	memset(&Overlapped, OFF, sizeof(Overlapped));
	seriell->m_ThreadEvent	= CreateEvent(NULL,FALSE,FALSE,NULL);
	Overlapped.hEvent		= seriell->m_ThreadEvent;
		
	while (seriell->m_SignalEvents)
	{
		IsSignaled			= WaitCommEvent(seriell->m_Handles.hHandle, &WaitableEvents, &Overlapped);
		
		if (ERROR_IO_PENDING == GetLastError())
			IsSignaled = (WAIT_TIMEOUT != WaitForSingleObject(seriell->m_ThreadEvent,seriell->m_Timeout));
		
		if (IsSignaled)
			seriell->DoOnSignal(WaitableEvents);
		else
		{
			if (NULL != seriell->m_CommError)
				seriell->m_CommError(seriell->m_Handles.hHandle,ERROR_COUNTER_TIMEOUT,THREADTIMEOUT);
			WaitableEvents = EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;
			SetCommMask(seriell->m_Handles.hHandle, WaitableEvents);
			ResetEvent(seriell->m_ThreadEvent);
		};
	};
ShowFailure:;
	SetCommMask(seriell->m_Handles.hHandle, 0);
	PurgeComm(seriell->m_Handles.hHandle, PURGEALL);
	CloseHandle(seriell->m_ThreadEvent);
	seriell->m_ThreadEvent = 0;
	if (NULL != seriell->m_CommError)
		seriell->m_CommError(seriell->m_Handles.hHandle,GetLastError(),THREADDONE);
	return 0;
}

/***************************************************************************************************/
//Create..Destroy Handle
/***************************************************************************************************/	
HANDLE C_RS232 ::
	CreateHandle(char* Name, BOOL testmode, DWORD Timeout)
{
	m_Timeout = Timeout;
	if ((Enabled(m_Handles.hHandle))
		&&(!testmode))
	{
		if (Assigned(m_CommError))
			m_CommError(m_Handles.hHandle,0,ALREADYOPENEDSTRING);
		return m_Handles.hHandle;
	};
	if (0 == strlen(Name))
	{
		if (Assigned(m_CommError))
			m_CommError(m_Handles.hHandle,0,INVALIDNAME);
		return m_Handles.hHandle;
	};
	
	strcpy(m_Handles.name,Name);
	m_Handles.hHandle = CreateFile(	m_Handles.name,
									GENERIC_READ|GENERIC_WRITE,
									0, 
									NULL,
									OPEN_EXISTING, 
									FILE_FLAG_OVERLAPPED, 
									0);

	if ((	(!Enabled(m_Handles.hHandle))
		||	(GetFileType(m_Handles.hHandle) != FILE_TYPE_CHAR))
		&&	(!testmode))
	{
		DestroyHandle(&m_Handles.hHandle);
		if (Assigned(m_CommError))
			m_CommError(m_Handles.hHandle,GetLastError(),OPENERRORSTRING);
		return m_Handles.hHandle;
	};

	DWORD Dummy;
	m_SignalEvents = (	(Enabled(m_Handles.hHandle)) 
					&&	(Assigned(m_Signal))
					&&	(!testmode));
	if (m_SignalEvents)
		m_EventThread = CreateThread(NULL,0,OnComEvent,this,THREAD_PRIORITY_NORMAL,&Dummy);
	return m_Handles.hHandle;

}

BOOL C_RS232 ::
	DestroyHandle(HANDLE* hHandle)
{
	BOOL ret = true;
	if(	(Enabled(m_EventThread))
	  &&(*hHandle == m_Handles.hHandle))
		{
			m_SignalEvents = 0;
			ret = TerminateOnSignal();
			Sleep(10);
		};
	CloseHandle(*hHandle);
	*hHandle = INVALID_HANDLE_VALUE;
	return ret;	
}

void C_RS232 ::
	DoOnSignal(DWORD hEvent)
{
	
	COMSTAT	ComStat;
	DWORD	Errors;
	BOOL	hasEvent = FALSE;
	
	ClearCommError(m_Handles.hHandle, &Errors, &ComStat);
	//Behandeln des Ereignisses
	if (hEvent&EV_BREAK)
		{/*NOP*/ hasEvent = TRUE;};
	if (hEvent&EV_CTS)
		{/*NOP*/ hasEvent = TRUE;};
	if (hEvent&EV_DSR)
		{/*NOP*/ hasEvent = TRUE;};
	if (hEvent&EV_RING)
		{/*NOP*/ hasEvent = TRUE;};
	if (hEvent&EV_RLSD)
		{/*NOP*/ hasEvent = TRUE;};
	if (hEvent&EV_TXEMPTY)
		{/*NOP*/ hasEvent = TRUE;};
    if (hEvent&EV_RXCHAR)
		{/*NOP*/ hasEvent = (0 < ComStat.cbInQue);};
	if (hEvent&EV_RXFLAG)
		{/*NOP*/ hasEvent = (0 < ComStat.cbInQue);};
	if (Assigned(m_Signal)&&(hasEvent))
		m_Signal(m_Handles.hHandle,Errors,ComStat.cbInQue,hEvent);
}

BOOL C_RS232 ::
	TerminateOnSignal()
{
	BYTE Dummy = 0;
	if(Enabled(m_EventThread))
	{
		SetEvent(m_ThreadEvent);
		DWORD ExitCode	= STILL_ACTIVE;
		while (STILL_ACTIVE == ExitCode)
		{
			TerminateThread(m_EventThread,0);
			GetExitCodeThread(m_EventThread,&ExitCode);
			if ((Dummy++) >= 0xfe) break;
		};
		CloseHandle(m_EventThread);
		m_EventThread = 0;
	};
	return (Dummy < 0xfe);
}
	
BOOL C_RS232 ::
	DisableOnSignal()
{
	BYTE Dummy = 0;
	if(Enabled(m_EventThread))
	{
		m_SignalEvents = false;
		SetEvent(m_ThreadEvent);
		while (!(0 >= SuspendThread(m_EventThread)))
		{/* NOP */ if ((Dummy++) >= 0xfe) break;};
	};
	return (Dummy < 0xfe);
}
	
BOOL C_RS232 ::
	EnableOnSignal()
{
	DWORD Dummy = 0;
	if(Enabled(m_EventThread))
	{
		m_SignalEvents = true;
		while (!(0 >= ResumeThread(m_EventThread)))
		{/* NOP */ if ((Dummy++) >= 0xfe) break;};
	}
	else
	{
		m_EventThread = CreateThread(NULL,0,OnComEvent,this,THREAD_PRIORITY_NORMAL,&Dummy);
		return (Enabled(m_EventThread));
	};
	return (Dummy < 0xfe);
}
/***************************************************************************************************/
//I/O-Buffer bearbeiten
/***************************************************************************************************/
BOOL C_RS232 ::
	Purge(BYTE Kind, HANDLE hHandle)
{
	if (Enabled(hHandle))
	{
		switch(Kind)
		{
		case INBUF:		PurgeComm(hHandle, PURGEREAD);
			break;
		case OUTBUF:	PurgeComm(hHandle, PURGEWRITE);
			break;
		case ALL:		PurgeComm(hHandle, PURGEALL);
			break;
		default:
			{
				if (Assigned(m_CommError))
				{
					char Msg[MAX_PATH] = {0};
					strcpy(Msg,INVALIDCHOISE);
					sprintf(Msg,"%s [valids are %d; %d; %d]",INVALIDCHOISE,INBUF,OUTBUF,ALL);
					m_CommError(m_Handles.hHandle,0,Msg);
					return false;
				};
			};
		};
		return true;
	};
	return false;
}
/***************************************************************************************************/
int	C_RS232 ::
	GetInOutQueCount(BYTE Que, HANDLE hHandle)
{
	if (Enabled(hHandle))
	{
		COMSTAT	ComStat;
		DWORD	Errors;
		if (!ClearCommError(hHandle, &Errors, &ComStat))
		{
			if (Assigned(m_CommError))
				m_CommError(m_Handles.hHandle,GetLastError(),FUNCTIONFAILED);
			return -1;
		}
		
		switch(Que)
		{
		case INBUF:		return ComStat.cbInQue;
			break;
		case OUTBUF:	return ComStat.cbOutQue;
			break;
		default:
			{
				if (Assigned(m_CommError))
				{
					char Msg[MAX_PATH] = {0};
					strcpy(Msg,INVALIDCHOISE);
					sprintf(Msg,"%s [valids are %d; %d]",INVALIDCHOISE,INBUF,OUTBUF);
					m_CommError(m_Handles.hHandle,0,Msg);
					return -1;
				};
			};
		};
	};
	return -1;
}
	
DWORD C_RS232 ::
	GetModemState(HANDLE hHandle)
{
	DWORD	Flag	= 0;
	DWORD	State	= 0x10;
	if (Enabled(hHandle))
	{
		if (GetCommModemStatus(hHandle, &Flag))
		{
			if (Assigned(m_CommError))
			{
				for (BYTE i = 0; i < 4; i++)
				{
					char Msg[MAX_PATH];
					if (Flag&State)
					{
						sprintf(Msg,"%s",tagCSTATESTR[i]);
						m_CommError(m_Handles.hHandle,0,Msg);
					};
					State *= 2;
				};
			};
		};
			
		COMSTAT stat;
		DWORD	Errors;
		if ((ClearCommError(hHandle, &Errors, &stat))&&(Assigned(m_CommError)))
		{
			if(stat.fCtsHold)
				m_CommError(m_Handles.hHandle,0,"Tx waiting for CTS signal ");
	
			if(stat.fDsrHold)
				m_CommError(m_Handles.hHandle,0,"Tx waiting for DSR signal ");
	
			if(stat.fRlsdHold)
				m_CommError(m_Handles.hHandle,0,"Tx waiting for RLSD signal ");
			
			if(stat.fXoffHold)
				m_CommError(m_Handles.hHandle,0,"Tx waiting, XOFF char received ");
	
			if(stat.fXoffSent)
				m_CommError(m_Handles.hHandle,0,"Tx waiting, XOFF char sent ");
		};
		return Flag;
	};
	return false;
}
	
BOOL WaitFor(EVENT event, DWORD TimeOut)
{
	switch(WaitForSingleObject(event,TimeOut))
	{
	case WAIT_ABANDONED:	return false;	// The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled. 
		break;
	case WAIT_OBJECT_0:		return true;	// The state of the specified object is signaled. 
		break;
	case WAIT_TIMEOUT:		return false;	// The time-out interval elapsed, and the object's state is nonsignaled. 
	default :return false;
	};
}

BOOL C_RS232 ::
	ComWrite(void* Buffer, DWORD BufferSize)
{
	OVERLAPPED Overlapped;
    DWORD BytesWritten;

	if (!Enabled(m_Write))
		m_Write = CreateEvent(NULL,FALSE,FALSE,NULL);
	
	memset(&Overlapped, OFF, sizeof(Overlapped));
	Overlapped.hEvent = m_Write;
	
	if (!WriteFile(	m_Handles.hHandle, 
					Buffer, 
					BufferSize, 
					&BytesWritten,
					&Overlapped))
	{
		switch(GetLastError())
		{
		case ERROR_IO_PENDING:
			{
				GetOverlappedResult(m_Handles.hHandle, 
									&Overlapped, 
									&BytesWritten, 
									!(WaitFor(Overlapped.hEvent,m_Timeout))
									);
				break;
			};
		default: return (BufferSize == BytesWritten);
		};
	}
	else
	{
		GetOverlappedResult(	m_Handles.hHandle, 
								&Overlapped, 
								&BytesWritten, 
								!(WaitFor(Overlapped.hEvent,m_Timeout))
									);
				
	};
	return (BufferSize == BytesWritten);
}
	
DWORD C_RS232 ::
	ComRead(void* Buffer, DWORD* BufferSize)
{
	OVERLAPPED Overlapped;
    DWORD BytesRead;

	if (!Enabled(m_Read))
		m_Read = CreateEvent(NULL,FALSE,FALSE,NULL);
	
	memset(&Overlapped, OFF, sizeof(Overlapped));
	Overlapped.hEvent = m_Read;
	
	if (!ReadFile(	m_Handles.hHandle, 
					Buffer, 
					*BufferSize, 
					&BytesRead,
					&Overlapped))
	{
		switch(GetLastError())
		{
		case ERROR_IO_PENDING:
			{
				GetOverlappedResult(m_Handles.hHandle, 
									&Overlapped, 
									&BytesRead, 
									!(WaitFor(Overlapped.hEvent,m_Timeout))
									);
				return (BytesRead);
			};
		default: return (BytesRead);
		};
	}
	else
	{
		GetOverlappedResult(	m_Handles.hHandle, 
								&Overlapped, 
								&BytesRead, 
								!(WaitFor(Overlapped.hEvent,m_Timeout))
									);
				
	};
	return (BytesRead);
}

BOOL C_RS232 ::
	Assigned(void* Pointer)
{
	return (NULL != Pointer);
}

BOOL C_RS232 ::
	Enabled(HANDLE hHandle)
{
	return ((0!=hHandle)&&(INVALID_HANDLE_VALUE!=hHandle));
};

⌨️ 快捷键说明

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