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

📄 sensor.cpp

📁 这是一个罗盘的串口数据读取过程,并且在此之前加入了标定过程
💻 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;
	mode = 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_hWriteEvent = NULL;

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

template <class T>
Sensor<T>::~Sensor(void)
{
	//ClosePort();
	delete [] m_szWriteBuffer;
}

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
                      UINT  writebuffersize)

{
					  	
	assert(portnr > 0 && portnr < 5);

	// if the thread is alive: Kill
	if (m_bThreadAlive)
	{
		do
		{
			SetEvent(m_hShutdownEvent);
		} while (m_bThreadAlive);
		printf("Thread ended\n");
	}

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


	

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

	// initialize critical section
	InitializeCriticalSection(&m_csCommunicationSync);

	// now it critical!
	EnterCriticalSection(&m_csCommunicationSync);


	if (m_szWriteBuffer != NULL)
		delete [] m_szWriteBuffer;
	m_szWriteBuffer = new char[writebuffersize];

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

	
	BOOL bResult = FALSE;
	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);


	// if the port is already opened: close it
	if (m_hComm != NULL)
	{
		CloseHandle(m_hComm);
		m_hComm = NULL;
	}	

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

	// flush the port
	PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

	// release critical section
	LeaveCriticalSection(&m_csCommunicationSync);

	printf("\nInitialisation for communicationport  COM%d  completed.\n\n", portnr);

	return TRUE;
}

template <class T>
BOOL Sensor<T>::StartThread()
{
	//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\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(3, 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;
			}
		case 2: // write event
			{
				// Write  character enent from port
				WriteChar(port);
				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();
          if(port->mode == 1)
			  port->OnReceiveCh(RXBuff);
		  else if(port->mode == 0)
			  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();
}

//
// Write a character.
//
template <class T>
void Sensor<T>::WriteChar(Sensor* port)
{
	BOOL bWrite = TRUE;
	BOOL bResult = TRUE;

	DWORD BytesSent = 0;

	ResetEvent(port->m_hWriteEvent);

	// Gain ownership of the critical section
	EnterCriticalSection(&port->m_csCommunicationSync);

	if (bWrite)
	{
		// Initailize variables
		port->m_ov.Offset = 0;
		port->m_ov.OffsetHigh = 0;

		// Clear buffer
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

		bResult = WriteFile(port->m_hComm,							// Handle to COMM Port
							port->m_szWriteBuffer,					// Pointer to message buffer in calling finction
							strlen((char*)port->m_szWriteBuffer),	// Length of message to send
							&BytesSent,								// Where to store the number of bytes sent
							&port->m_ov);							// Overlapped structure

		// deal with any error codes
		if (!bResult)  
		{
			DWORD dwError = GetLastError();
			switch (dwError)
			{
				case ERROR_IO_PENDING:
					{
						// continue to GetOverlappedResults()
						BytesSent = 0;
						bWrite = FALSE;
						break;
					}
				default:
					{
						// all other error codes
						port->ProcessErrorMessage("WriteFile()");
					}
			}
		} 
		else
		{
			LeaveCriticalSection(&port->m_csCommunicationSync);
		}
	} // end if(bWrite)

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

		LeaveCriticalSection(&port->m_csCommunicationSync);

		// deal with the error code 
		if (!bResult)  
		{
			port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
		}	
	} // end if (!bWrite)

	// Verify that the data size send equals what we tried to send
	if (BytesSent != strlen((char*)port->m_szWriteBuffer))
	{
		printf("WARNING: WriteFile() error.. Bytes Sent:  %s  ,%d; Message Length: %d\n",(char*)port->m_szWriteBuffer, BytesSent, strlen((char*)port->m_szWriteBuffer));
	}
}

//
// Write a string to the port
//
template <class T>
void Sensor<T>::WriteToPort(char* string)
{		
	assert(m_hComm != 0);

	memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
	strcpy(m_szWriteBuffer, string);

	// set event for write
	SetEvent(m_hWriteEvent);
}



⌨️ 快捷键说明

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