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

📄 serialport.cpp

📁 一部容易理解的书
💻 CPP
字号:
// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SerialPort.h"
#include "process.h"
#include <assert.h>
/***********global variable**********/
UINT WINAPI  CommThread(void* lpParameter);
HANDLE g_hReadSignal;
HANDLE g_hWriteSignal;
UCHAR RXBuffer;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerialPort::CSerialPort()
{
	m_ov.hEvent = NULL;
	m_ov.Offset = 0;
	m_ov.Internal = 0;
	m_hWriteEvent = NULL;
	m_szWriteBuffer = NULL;
	m_hShutdownEvent = NULL;
	m_nSendDataLen = 0;
}

CSerialPort::~CSerialPort()
{
	SetEvent(m_hShutdownEvent);
	delete [] m_szWriteBuffer;
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
void ReceiveChar(CSerialPort *port)
{
	BOOL bRead = TRUE;
	BOOL bResult = TRUE;
	DWORD dwError = 0;
	DWORD BytesRead = 0;
	COMSTAT comstat;


	while (1)
	{
		bResult = ClearCommError(port->m_hCom,&dwError,&comstat);
		if (comstat.cbInQue == 0)
		{
			break;
		}

		if (bRead)
		{
			bResult = ReadFile(port->m_hCom,
							   &RXBuffer,
							   1,
							   &BytesRead,
							   &port->m_ov);
			if (!bResult)
			{
				switch(dwError = GetLastError())
				{
					case ERROR_IO_PENDING:
						{
							bRead = FALSE;
							break;
						}
					default:
						{
							port->ProcessErrorMessage("ReadFile()");
							break;
						}
						
				}
			}
			else
			{
				bRead = TRUE;
			}
		}
		if (!bRead)
		{
			bRead = TRUE;
			bResult = GetOverlappedResult(port->m_hCom,
										  &port->m_ov,
										  &BytesRead,
										  TRUE);
			if (!bResult)
			{
				port->ProcessErrorMessage("GetOverlappedResult() in ReadFile()");
			}			
		}
			SetEvent(g_hReadSignal);
			ResetEvent(port->m_ov.hEvent);
	}
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
void WriteChar(CSerialPort *port)
{
	BOOL bWrite = TRUE;
	BOOL bResult = TRUE;
	DWORD BytesSent = 0;

	OutputDebugString("write function  is running");
	ResetEvent(port->m_hWriteEvent);
	if (bWrite)
	{
		port->m_ov.Offset = 0;
		port->m_ov.Internal = 0;
		port->m_ov.OffsetHigh = 0;
        
		/* clear buffer */
		PurgeComm(port->m_hCom,PURGE_RXCLEAR | PURGE_TXCLEAR |PURGE_RXABORT | PURGE_TXABORT);

		bResult = WriteFile(port->m_hCom,
							port->m_szWriteBuffer,
							port->m_nSendDataLen,
							&BytesSent,
							&port->m_ov);
		/* deal with any error codes */
		if (!bResult)
		{
			DWORD dwError = GetLastError();
			switch(dwError)
			{
				case ERROR_IO_PENDING:
					{
						BytesSent = 0;
						bWrite = FALSE;
						break;
					}
				default:
					{
						port->ProcessErrorMessage("WriteFile()");
					}
			}
		}
	}
	if (!bWrite)
	{
		bWrite = TRUE;
		bResult = GetOverlappedResult(port->m_hCom,
										  &port->m_ov,
										  &BytesSent,
										  TRUE);
		if (!bResult)
		{
			port->ProcessErrorMessage("GetoverlappedResults() in WriteFile()");
		}
	}
	
	if (BytesSent != port->m_nSendDataLen)
	{
		OutputDebugString("WARNING:writeFile() error..BytesSent;Message Length\n");
		ResetEvent(port->m_ov.hEvent);
	}	
	FlushFileBuffers(port->m_hCom);
	SetEvent(g_hWriteSignal);
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/ 
UINT WINAPI  CommThread(void* lpParameter)
{
	CSerialPort *port = (CSerialPort*)lpParameter;
	BOOL bResult = TRUE;
	DWORD CommEvent = 0;
	DWORD dwError = 0;
	COMSTAT commStat;
	DWORD receiveEvent = 0;
	if (port->m_hCom)
	{
		PurgeComm(port->m_hCom,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
	}
	OutputDebugString("thread1  is running");
	while (1)
	{
		bResult = WaitCommEvent(port->m_hCom,&CommEvent,&port->m_ov);
		if (!bResult)
		{
			switch(dwError = GetLastError())
			{
				case ERROR_IO_PENDING:
				{
					break;
				}
				case 87:
				{
					break;		
				}
				default:
				{
					port->ProcessErrorMessage("WaitCommEvent()");
				}
			}
			ClearCommError(port->m_hCom,&dwError,&commStat);
		} //end of if(!bResult)
		
		CommEvent = WaitForMultipleObjects(3,port->m_hEventArray,FALSE,INFINITE);
		switch(CommEvent)
		{
			case 0:  //shutdown event
				{
					_endthreadex(0);
					CloseHandle(port->m_hCom);
					break;
				}
			case 1:  //read event
				{
					ResetEvent(port->m_ov.hEvent);
					if (GetCommMask(port->m_hCom,&receiveEvent))
					{
						if (receiveEvent & EV_RXCHAR)
						{
							ReceiveChar(port);		
						}
					}
					break;
				}
			case 2: //write event
				{
					ResetEvent(port->m_hWriteEvent);
					WriteChar(port);
					break;
				}
		}
	}
	return 0;
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
BOOL CSerialPort::InitPort(UINT portNum, UINT baud, char parity, UINT dataBits, UINT stopsBits, DWORD dwCommEvents, UINT nBufferSize)
{
	DWORD dwError;
	BOOL bResult = FALSE;
	char *szPort = new char[50];
	char *szBaud = new char[50];

	// prepare port strings
	sprintf(szPort, "COM%d", portNum);
	sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, dataBits, stopsBits);

	if (m_szWriteBuffer != NULL)
		delete [] m_szWriteBuffer;
	m_szWriteBuffer = new char[nBufferSize];
	
	m_nPortNr	= portNum;
	m_nBaud		= baud;
	m_nParity	= parity;
	m_nDatabits	= dataBits;
	m_nStopbits	= stopsBits;
	
	m_nWriteBufferSize = nBufferSize;
	m_dwCommEvents = dwCommEvents;
	
	if (m_ov.hEvent != NULL)
	{
		ResetEvent(m_ov.hEvent);
	}
	else
	{	
		m_ov.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	}
	if (m_hWriteEvent != NULL)
	{
		ResetEvent(m_hWriteEvent);
	}
	else
	{
		m_hWriteEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	}
	if (m_hShutdownEvent != NULL)
	{
		ResetEvent(m_hShutdownEvent);
	}
	else
	{
		m_hShutdownEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	}
	SetThreadPriority(m_hShutdownEvent,THREAD_PRIORITY_HIGHEST);
	/* this event is used for work thread to notify main thread read operation is complete*/
	g_hReadSignal = CreateEvent(NULL,TRUE,FALSE,NULL);
	g_hWriteSignal = CreateEvent(NULL,TRUE,FALSE,NULL);

	m_hEventArray[0] = m_hShutdownEvent;
	m_hEventArray[1] = m_ov.hEvent;
	m_hEventArray[2] = m_hWriteEvent;

	// get a handle to the port
	m_hCom = CreateFile(szPort,			// communication port string (COMX)
		GENERIC_READ | GENERIC_WRITE,	// read/write types
		0,								// comm devices must be opened with exclusive access
		NULL,							// no security attributes
		OPEN_EXISTING,					// comm devices must use OPEN_EXISTING
		FILE_FLAG_OVERLAPPED,			// Async I/O
		0);							    // template must be 0 for comm devices
	
	if (m_hCom == INVALID_HANDLE_VALUE)
	{
		// port not found
		dwError=GetLastError();
		switch(dwError)
		{
			case 0:
			break;
			default:
			break;
		}
		delete [] szPort;
		delete [] szBaud;
		
		return FALSE;
	}

	/* set the timeout values,the base unit is ms */
	m_Timeouts.ReadIntervalTimeout = 1000;
	m_Timeouts.ReadTotalTimeoutMultiplier = 1000;
	m_Timeouts.ReadTotalTimeoutConstant = 1000;
	m_Timeouts.WriteTotalTimeoutMultiplier = 1000;
	m_Timeouts.WriteTotalTimeoutConstant = 1000;
	/* set the timeout values,if success return nonzero */
	if (SetCommTimeouts(m_hCom,&m_Timeouts))
	{	
		/* set event mask to monitor given port event */
		if (SetCommMask(m_hCom,m_dwCommEvents))
		{
			/* get the current DCB structure */
			if(GetCommState(m_hCom,&m_dcb))
			{	
				/* change DCB settings */
				if (BuildCommDCB(szBaud,&m_dcb))
				{
					/* set the current DCB structure */
					if (SetCommState(m_hCom,&m_dcb))
					{
						/* there is no error ,continue execute */
					}
					else
					{
						ProcessErrorMessage("SetCommState()");
					}
				}
				else
				{
					ProcessErrorMessage("BuildCommDCB()");
				}
			}
			else
			{
				ProcessErrorMessage("GetCommState()");
			}
		}
		else
		{
			ProcessErrorMessage("SetCommMask()");
		}
	}
	else
	{
		ProcessErrorMessage("SetCommTimeouts()");
	}
	 
	return TRUE;
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
void CSerialPort::ProcessErrorMessage(char *ErrorText)
{
	char *Temp = new char[200];
	LPVOID lpMsgBuf;
	
	FormatMessage( 
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		GetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL 
		);
	
	sprintf(Temp, "WARNING:  %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr); 
	MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
	
	LocalFree(lpMsgBuf);
	delete[] Temp;
}

/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
BOOL CSerialPort::StartMonitoring()
{
	if (!(m_handle = (HANDLE)_beginthreadex(NULL,0,CommThread,this,0,NULL)))
	{	
		return FALSE;
	}
	ResumeThread(m_handle);
	OutputDebugString("thread  is running");
	return TRUE;
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
void CSerialPort::WriteData(char *string,UINT length)
{
	assert(m_hCom);

	memset(m_szWriteBuffer,0,m_nWriteBufferSize);
	memcpy(m_szWriteBuffer,string,length);
	m_nSendDataLen = length;
	SetEvent(m_hWriteEvent);
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
BOOL CSerialPort::StopMonitoring()
{
	OutputDebugString("Thread suspended\n");
	SuspendThread(m_hCom);
	return TRUE;
}
/*/*******************************************************************
--Function name: 
--Function Description:  
--Function involved:  
--Global variable  :  
--Input :
--Output:
--Designer: song      Time : 08.3.17
--Modifier:           Time :
--Version: v0.1
--*******************************************************************/
BOOL CSerialPort::RestartMonitoring()
{
	OutputDebugString("Thread resumed\n");
	ResumeThread(m_hCom);
	return TRUE;
}

⌨️ 快捷键说明

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