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

📄 sensor.cpp

📁 GPS的串口读取数据过程,并且进行了坐标转换,转化为通用的坐标系
💻 CPP
字号:
//THIS FILE SHOULD BE EXCLUDED FROM BUILD
//#include "StdAfx.h"
//#include "Sensor.h"

template <class T>
Sensor<T>::Sensor(void)
{
	m_hComm = NULL;

	m_nPortNr = -1;
	m_dwCommEvents = 0;

	m_ov.Offset = 0;
	m_ov.OffsetHigh = 0;
	m_ov.hEvent = NULL;

	m_hThread = NULL;
	m_bThreadAlive = false;
	m_hShutdownEvent = NULL;
	m_hInitDoneEvent = NULL;

	m_nInFrequency = -1;
	m_nOutFrequency = -1;
	
	m_nDataBufferSize = -1;
	m_vDataBuffer.clear();
}

template <class T>
Sensor<T>::~Sensor(void)
{
	ClosePort();
}

template <class T>
void Sensor<T>::InitSensor(int infrequency, int outfrequency, int buffersize)
{
	assert(infrequency > 0);
	assert(outfrequency > 0);
	assert(buffersize > 0);

	m_nInFrequency = infrequency;
	m_nOutFrequency = outfrequency;

	m_nDataBufferSize = buffersize;
}

template <class T>
void Sensor<T>::ProcessErrorMessage(const string& msg)
{
	TCHAR *Temp = new TCHAR[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 
		);

	wsprintf(Temp, _T("WARNING:  %s Failed with the following error: \n%s\nPort: %d\n"), msg.c_str(), lpMsgBuf, m_nPortNr); 
	MessageBox(NULL, Temp, _T("Application Error"), MB_ICONSTOP);

	LocalFree(lpMsgBuf);
	delete[] Temp;
	exit(EXIT_FAILURE);
}

template <class T>
void Sensor<T>::Lock(void)
{
	EnterCriticalSection(&m_csCommunicationSync);
}

template <class T>
void Sensor<T>::Unlock(void)
{
	LeaveCriticalSection(&m_csCommunicationSync);
}

template <class T>
BOOL Sensor<T>::OpenPort(UINT  portnr,				// portnumber (1..4)
					  UINT  baud,			// baudrate
					  char  parity,		// parity 
					  UINT  databits,		// databits 
					  UINT  stopbits,		// stopbits 
					  DWORD dwCommEvents)	// EV_RXCHAR, EV_CTS etc
{
	assert(portnr > 0 && portnr < 5);

	BOOL bResult = FALSE;

	// prepare port strings
	m_nPortNr = portnr;
	m_dwCommEvents = dwCommEvents;

	char *szPort = new char[50];
	char *szBaud = new char[50];
	sprintf(szPort, "COM%d", m_nPortNr);
	sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);

	// create events
	m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	// initialize the event objects
	m_hEventArray[0] = m_hShutdownEvent;	// highest priority
	m_hEventArray[1] = m_ov.hEvent;

	// initialize critical section
	InitializeCriticalSection(&m_csCommunicationSync);

	// get a handle to the port
	m_hComm = 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_hComm == INVALID_HANDLE_VALUE)
	{
		// port not found
		delete [] szPort;
		delete [] szBaud;

		m_hComm = NULL;

		ProcessErrorMessage("CreateFile()");

		return FALSE;
	}

	//YOU MAY CHANGE THIS STRUCT
	// set the timeout values
	m_CommTimeouts.ReadIntervalTimeout = 1000;
	m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
	m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
	m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
	m_CommTimeouts.WriteTotalTimeoutConstant = 1000;

	// configure
	if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
	{						   
		if (SetCommMask(m_hComm, dwCommEvents))
		{
			if (GetCommState(m_hComm, &m_dcb))
			{
				m_dcb.fRtsControl = RTS_CONTROL_ENABLE;		// set RTS bit high!
				if (BuildCommDCB(szBaud, &m_dcb))
				{
					if (SetCommState(m_hComm, &m_dcb)); // normal operation... continue
					else
						ProcessErrorMessage("SetCommState()");
				}
				else
					ProcessErrorMessage("BuildCommDCB()");
			}
			else
				ProcessErrorMessage("GetCommState()");
		}
		else
			ProcessErrorMessage("SetCommMask()");
	}
	else
		ProcessErrorMessage("SetCommTimeouts()");

	delete [] szPort;
	delete [] szBaud;

	output::writeln("try to start thread...");

	////clear the data buffer before thread starts to avoid race condition
	m_vDataBuffer.clear();
	m_vDataBuffer.resize(m_nDataBufferSize);

	int threadid = 0;
	m_hInitDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_hThread = (HANDLE)_beginthreadex(NULL,
		0,
		(PBEGINTHREADEX_THREADFUNC) Sensor<T>::CommThread,
		(LPVOID)this,
		0,
		(PBEGINTHREADEX_THREADID) &threadid );

	if (m_hThread == 0)
	{
		CloseHandle(m_hInitDoneEvent);
		m_hInitDoneEvent = NULL;
		return FALSE;
	}

	WaitForSingleObject(m_hInitDoneEvent, INFINITE);

	return TRUE;
}

template <class T>
void Sensor<T>::ClosePort(void)
{
	if (m_bThreadAlive)
	{
		output::writeln("try to stop thread...");
		do
		{
			SetEvent(m_hShutdownEvent);
		}
		while (m_bThreadAlive);
	}

	if (m_hThread != NULL)
	{
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}

	// if the port is still opened: close it 
	if (m_hComm != NULL)
	{
		CloseHandle(m_hComm);
		m_hComm = NULL;
	}
	// Close Handles  
	if(m_hShutdownEvent != NULL)
	{
		CloseHandle(m_hShutdownEvent);
		m_hShutdownEvent = NULL;
	}

	if (m_ov.hEvent!=NULL)
	{
		CloseHandle(m_ov.hEvent);
		m_ov.hEvent = NULL;
	}

	if (m_hInitDoneEvent != NULL)
	{
		CloseHandle(m_hInitDoneEvent);
		m_hInitDoneEvent = NULL;
	}

	DeleteCriticalSection(&m_csCommunicationSync);

	//clear data buffer
	m_vDataBuffer.clear();

	output::writeln("port closed.\n");
}

template <class T>
UINT Sensor<T>::CommThread(LPVOID pParam)
{
	Sensor *port = (Sensor*)pParam;
	assert(port->m_hComm != NULL);

	DWORD BytesTransfered = 0; 
	DWORD Event = 0;
	DWORD CommEvent = 0;
	DWORD dwError = 0;
	COMSTAT comstat = {0};
	BOOL  bResult = TRUE;

	// Clear comm buffers at startup
	if (port->m_hComm)		// check if the port is opened
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

	port->m_bThreadAlive = TRUE;
	output::writeln("thread starts.\n");
	SetEvent(port->m_hInitDoneEvent);

	// begin forever loop.  This loop will run as long as the thread is alive.
	for (;;) 
	{
		bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);

		if (!bResult)  
		{
			switch (dwError = GetLastError()) 
			{ 
			case ERROR_IO_PENDING: 	
				{ 
					// This is a normal return value if there are no bytes
					// to read at the port.
					// Do nothing and continue
					break;
				}
			case 87:
				{
					// Under Windows NT, this value is returned for some reason.
					// I have not investigated why, but it is also a valid reply
					// Also do nothing and continue.
					break;
				}
			default:
				{
					// All other error codes indicate a serious error has
					// occured.  Process this error.
					port->ProcessErrorMessage("WaitCommEvent()");
					break;
				}
			}
		}
		else
		{
			bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

			if (comstat.cbInQue == 0)
				continue;
		}	// end if bResult

		// Main wait function.  This function will normally block the thread
		// until one of nine events occur that require action.
		Event = WaitForMultipleObjects(2, port->m_hEventArray, FALSE, INFINITE);

		switch (Event)
		{
		case 0:
			{
				// Shutdown event.  This is event zero so it will be
				// the higest priority and be serviced first.

				port->Lock();
				port->m_bThreadAlive = FALSE;
				port->Unlock();

				output::writeln("thread ends.\n");

				_endthreadex(0);
				break;
			}
		case 1:	// read event
			{
				GetCommMask(port->m_hComm, &CommEvent);

				if (CommEvent & EV_RXCHAR)
					// Receive character event from port.
					ReceiveChar(port, comstat);

				break;
			}
		} // end switch

	} // close forever loop

	return 0;
}

template <class T>
void Sensor<T>::ReceiveChar(Sensor* port, COMSTAT comstat)
{
	BOOL  bRead = TRUE; 
	BOOL  bResult = TRUE;
	DWORD dwError = 0;
	DWORD BytesRead = 0;
	char RXBuff;

	for (;;) 
	{
		//port->Lock();
		bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
		//port->Unlock();

		if (comstat.cbInQue == 0)
		{
			// break out when all bytes have been read
			break;
		}

		//port->lock();

		if (bRead)
		{
			bResult = ReadFile(port->m_hComm,		// Handle to COMM port 
				&RXBuff,				// RX Buffer Pointer
				1,					// Read one byte
				&BytesRead,			// Stores number of bytes read
				&port->m_ov);		// pointer to the m_ov structure
			// deal with the error code 
			if (!bResult)  
			{ 
				switch (dwError = GetLastError()) 
				{ 
				case ERROR_IO_PENDING: 	
					{ 
						// asynchronous i/o is still in progress 
						// Proceed on to GetOverlappedResults();
						bRead = FALSE;
						break;
					}
				default:
					{
						// Another error has occured.  Process this error.
						port->ProcessErrorMessage("ReadFile()");
						break;
					} 
				}
			}
			else
			{
				// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
				bRead = TRUE;
			}
		}  // close if (bRead)

		if (!bRead)
		{
			bRead = TRUE;
			bResult = GetOverlappedResult(port->m_hComm,	// Handle to COMM port 
				&port->m_ov,		// Overlapped structure
				&BytesRead,		// Stores number of bytes read
				TRUE); 			// Wait flag

			// deal with the error code 
			if (!bResult)  
			{
				port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
			}	
		}  // close if (!bRead)

		//port->Unlock();

		port->OnReceiveChar(RXBuff);

	} // end forever loop

}

template <class T>
bool Sensor<T>::GetCurrentData(T& data)
{
	assert(m_bThreadAlive && m_hComm != NULL);
	Lock();
	bool res = m_vDataBuffer.empty() ? false : true;
	if (res)
	{
		data = m_vDataBuffer[0];
	}
	Unlock();
	return res;
}

template <class T>
void Sensor<T>::UpdateDataBuffer(const T& data)
{
	Lock();
	assert(m_vDataBuffer.size() == m_nDataBufferSize);
	m_vDataBuffer[1] = m_vDataBuffer[0];
	m_vDataBuffer[0] = data;
	Unlock();
}

⌨️ 快捷键说明

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