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

📄 gps.cpp

📁 gps数据采集代码。 vc++6.0编写
💻 CPP
字号:
#include "stdafx.h"
#include "GPSManager.h"
#include "GPS.h"
#include "MainFrm.h"
#include "GPSManagerDoc.h"
#include "GPSManagerView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

  #if   defined(UNICODE)   ||   defined   (_UNICODE)   
  #define   WinMain   wWinMain   
  #endif
/*************************************************************************
 *
 * 函数名称:
 *   GPSDataProc()
 *
 * 参数:
 *   LPVOID lpVoid		- 参数指针
 *
 * 返回值:
 *	 UINT				- 线程返回代码
 *
 * 说明:
 *	 本函数为线程处理函数,所完成的功能为异步数据接收
 *
 ************************************************************************/

UINT GPSDataProc(LPVOID lpVoid)
{
	CGPS* pGPS = (CGPS*)lpVoid;
	if (pGPS == NULL)
		return 1003;
	
	// 参数复位
	pGPS->ParamReset();

	// GPS数据处理
	pGPS->DoDataProc();

	return 1004;
}

/////////////////////////////////////////////////////////////////////////////
// CGPS		

CGPS::CGPS()
{
	m_pView = NULL;
	m_hCom = INVALID_HANDLE_VALUE;
	m_hExitListenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	ParamReset();
}

CGPS::~CGPS()
{
	m_hCom = INVALID_HANDLE_VALUE;
	m_pReadThread = NULL;
	CloseHandle(m_hExitListenEvent);
}


BEGIN_MESSAGE_MAP(CGPS, CWnd)
	//{{AFX_MSG_MAP(CGPS)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CGPS message handlers


/*************************************************************************
 *
 * 函数名称:
 *   DoReadProc()
 *
 * 参数:
 *   无
 *
 * 返回值:
 *	 无 
 *
 * 说明:
 *	 对端口进行异步读取
 *
 ************************************************************************/

void CGPS::DoDataProc()
{
	// 中间变量
	DWORD dwErrorMask;
	DWORD dwEvtMask = 0;

	// 清空缓冲区
	memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));

	// 串口状态结构对象
	COMSTAT comstat;		

	// 异步结构对象	
	OVERLAPPED ov, ovEvent;
	ov.Internal = 0;
	ov.InternalHigh = 0;
	ov.Offset = 0;
	ov.OffsetHigh = 0;
	ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	ovEvent.Internal = 0;
	ovEvent.InternalHigh = 0;
	ovEvent.Offset = 0;
	ovEvent.OffsetHigh = 0;
	ovEvent.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	// 设置事件驱动的类型
	if (!SetCommMask(m_hCom, EV_RXCHAR | EV_TXEMPTY))
		return; 

	while (true) 
	{
		// 等待接收事件
		if (WaitCommEvent(m_hCom, &dwEvtMask, &ovEvent) == FALSE)
		{
		    if (GetLastError() == ERROR_IO_PENDING)
		       WaitForSingleObject(ovEvent.hEvent, INFINITE);
		}

		// 终止侦听线程
		if (m_bExitListen == TRUE)
		{
			// 线程退出事件置位
			SetEvent(m_hExitListenEvent);
			return;
		}

		// 数据到达事件发生后进行接收处理
		if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
		{
			do
			{
				// 确定接收缓冲中处于等待的字节数
				ClearCommError(m_hCom, &dwErrorMask, &comstat);
				if (comstat.cbInQue == 0)
					break;

				// 异步读取数据到帧缓冲
				if (!ReadFile(m_hCom, m_cFrameBuf + m_dwPoint, comstat.cbInQue, &m_dwActRead, &ov))
				{
					if (GetLastError() == ERROR_IO_PENDING)
					{
						// 检测数据是否接收完毕
						//while (!GetOverlappedResult(m_hCom, &ov, &m_dwActRead, FALSE))
						while(!WaitForSingleObject(ov.hEvent,INFINITE))
						{
							// 数据尚未接收完毕
							if (GetLastError() == ERROR_IO_INCOMPLETE)
								continue;
						}
							
						// 接收数据处理
						RecvDataProc();

						// 手动复位
						ResetEvent(ov.hEvent);
					}
				}
				else
				{
					// 接收数据处理
					RecvDataProc();

					// 手动复位
					ResetEvent(ov.hEvent);
				}
			} while (comstat.cbInQue > 0);
		} 
	} 
}


/*************************************************************************
 *
 * 函数名称:
 *   OpenPort()
 *
 * 参数:
 *	 CString sPort		- 串口号("COM1","COM2","COM3","COM4")
 *	 DWORD dwBaud		- 波特率
 *
 * 返回值:
 *	 BOOL				- 打开成功与否
 *
 * 说明:
 *	 异步打开指定串口
 *
 ************************************************************************/

BOOL CGPS::OpenPort(CString sPort, DWORD dwBaud)
{
	// 打开串口
	m_hCom = CreateFile(sPort,
					GENERIC_READ | GENERIC_WRITE,
					0,                    
					NULL,                 
					OPEN_EXISTING,
					FILE_FLAG_OVERLAPPED,
					NULL); 
	if (m_hCom == INVALID_HANDLE_VALUE)
		return FALSE;

 	// 得到当前串口配置
	DCB dcb;
   	dcb.DCBlength = sizeof(dcb);
	GetCommState(m_hCom, &dcb);

	// 基本配置
	dcb.BaudRate = dwBaud;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;

	// 不使用DSR--DTR流控方式
	dcb.fOutxDsrFlow = FALSE;
	dcb.fDtrControl = DTR_CONTROL_DISABLE;

	dcb.fNull = FALSE;
	dcb.fAbortOnError = FALSE;
	dcb.fTXContinueOnXoff = FALSE;

	// 二进制传输
	dcb.fBinary = TRUE;

	// 配置串口设置
	SetCommState(m_hCom, &dcb);

	// 超时设置
	COMMTIMEOUTS  CommTimeOuts;
	CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 2 * 9600 / dcb.BaudRate;
	CommTimeOuts.WriteTotalTimeoutConstant = 25;
	SetCommTimeouts(m_hCom, &CommTimeOuts);

	// 设置缓冲区大小
	SetupComm(m_hCom, 8192, 8192);

	// 开启数据接收线程
	m_bExitListen = FALSE;
	m_pReadThread = AfxBeginThread(GPSDataProc, this, THREAD_PRIORITY_TIME_CRITICAL);

	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   ClosePort()
 *
 * 参数:
 *   无
 *
 * 返回值:
 *	 BOOL			- 端口成功关闭与否
 *
 * 说明:
 *	 结束正在进行的数据收发任务后关闭端口
 *
 ************************************************************************/

BOOL CGPS::ClosePort()
{
	// 关闭端口释放资源
	if (m_hCom != INVALID_HANDLE_VALUE)	
	{
		// 关闭侦听线程
		m_bExitListen = TRUE;
		TerminateRecv();

		// 终止端口操作,清空缓冲区
		PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
		CloseHandle(m_hCom);
 
		// 端口复位
		m_hCom = INVALID_HANDLE_VALUE;
	}

	return TRUE;
}


/*************************************************************************
 *
 * 函数名称:
 *   RecvDataProc()
 *
 * 参数:
 *   无
 *
 * 返回值:
 *	 无
 *
 * 说明:
 *   对接收数据的处理过程
 *
 ************************************************************************/

void CGPS::RecvDataProc()
{
	// 当前缓冲区末尾     
	m_dwPoint += m_dwActRead;
	if (m_dwActRead == 0 || m_dwActRead + m_dwPoint < 30)
		return;

	if (m_bInfoStart == FALSE)
	{
		// 寻找GPS帧头
		CString sData  = (CString)m_cFrameBuf;
		int nHead = sData.Find(_T("$GPRMC"), 0);
		if ( nHead >= 0)
		{
			// 清除信息前的垃圾数据
			for (DWORD i = nHead; i < m_dwPoint; i++)
				m_cFrameBuf[i - nHead] = m_cFrameBuf[i];
			m_dwPoint -= nHead;
			m_dwActRead = 0;
			m_cFrameBuf[m_dwPoint] = 0;

			// 标记为找到帧头
			m_bInfoStart = TRUE;

			// LF个数清零
			m_nLFNum = 0;
		}
		else
		{
			// 清除缓冲区全部垃圾数据
			m_dwPoint = 0;
			m_dwActRead = 0;
			memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
		}
	}

	if (m_bInfoStart == TRUE)
	{
		// 寻找GPS帧头
		CString sData  = CString(m_cFrameBuf);
		int nEnd = sData.Find('\n', 0);
		if (nEnd >= 0)
		{
			m_nLFNum++;
			m_cFrameBuf[nEnd] = '\r';
			if (m_nLFNum == 2)
			{
				// LF个数清零
				m_nLFNum = 0;

				// 清除信息后的垃圾数据
				memset(m_cFrameBuf + nEnd, 0, m_dwPoint - nEnd);
				
				m_dwPoint = nEnd;
				m_dwActRead = 0;
				m_cFrameBuf[m_dwPoint] = 0;

				// GPS帧数据分析 
				AnalysisGPSFrame();

				// 准备接收下一帧GPS数据 
				m_bInfoStart = FALSE;

				// 变量复位
				m_dwPoint = 0;
				m_dwActRead = 0;
				memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
			}
		}
	}

	// 清理接收缓冲区 
	PurgeComm(m_hCom, PURGE_RXCLEAR);
}


/*************************************************************************
 *
 * 函数名称:
 *   AnalysisGPSFrame()
 *
 * 参数:
 *   无
 *
 * 返回值:
 *	 无 
 *
 * 说明:
 *   对接收到的GPS帧数据进行解帧处理
 *
 ************************************************************************/

void CGPS::AnalysisGPSFrame()
{
	int nSectionID = 0;
	char Temp[15];
	memset(Temp, 0, sizeof(Temp));
	int nIndex = 0;
	CString sTemp = _T("");
	BOOL bGetValue = false;

	for (DWORD i = 0; i < m_dwPoint; i++)
	{
		Temp[nIndex] = m_cFrameBuf[i];
		if (m_cFrameBuf[i] == ',')
		{
			nSectionID++;
			Temp[nIndex] = 0;
			bGetValue = true;
		}
		nIndex++;

		if (bGetValue == TRUE)
		{
			bGetValue = false;
			nIndex = 0;
			switch(nSectionID)
			{
			case 2:		// 时间
				sTemp.Format(_T("%c%c"), Temp[0], Temp[1]);
				m_lHour = _wtoi(sTemp);
				sTemp.Format(_T("%c%c"), Temp[2], Temp[3]);
				m_lMinute = _wtoi(sTemp);
				sTemp.Format(_T("%c%c"), Temp[4], Temp[5]);
				m_lSecond = _wtoi(sTemp);
				break;
			case 4:		// 纬度
				sTemp.Format(_T("%c%c"), Temp[0], Temp[1]);
				m_dLat = _wtoi(sTemp);
				sTemp.Format(_T("%c%c%c%c%c%c"), Temp[2], Temp[3], Temp[4], Temp[5], Temp[6], Temp[7]);
				m_dLat = m_dLat + wcstod(sTemp,NULL) / 60.0f;
				break;
			case 6:		// 经度
				sTemp = CString(Temp);
				sTemp.Format(_T("%c%c%c"), Temp[0], Temp[1], Temp[2]);
				m_dLon = _wtoi(sTemp);
				sTemp.Format(_T("%c%c%c%c%c%c"), Temp[3], Temp[4], Temp[5], Temp[6], Temp[7], Temp[8]);
				m_dLon = m_dLon + wcstod(sTemp,NULL) / 60.0f;
				break;
			case 8:		// 速度
				m_dVelo = atof(Temp);
				break;
			case 9:		// 方位角
				m_dDirection = atof(Temp);
				break;
			case 10:	// 日期
				sTemp.Format(_T("%c%c"), Temp[0], Temp[1]);
				m_lDay = _wtoi(sTemp);
				sTemp.Format(_T("%c%c"), Temp[2], Temp[3]);
				m_lMonth = _wtoi(sTemp);
				sTemp.Format(_T("%c%c"), Temp[4], Temp[5]);
				m_lYear = 2000 + _wtoi(sTemp);
				break;
			case 21:	// 高度
				m_dAlt = atof(Temp);
				break;
			}
		}
	}

	// 修正时区
	m_lHour += 8;
	if (m_lHour >= 24)
	{
		m_lHour -= 24;
		m_lDay ++;

		// 2月闰年处理
		if (m_lMonth == 2)
		{
			if (m_lYear % 4 == 0)
			{
				if (m_lDay > 29)
				{
					m_lDay = 1;
					m_lMonth = 3;
				}
			}
			else
			{
				if (m_lDay > 28)
				{
					m_lDay = 1;
					m_lMonth = 3;
				}
			}
		}
			
		// 大月处理
		if (m_lMonth == 1 || m_lMonth == 3 || m_lMonth == 5 || m_lMonth == 7 || m_lMonth == 8 || m_lMonth == 10 || m_lMonth == 12)
		{
			if (m_lDay > 31)
			{
				m_lDay = 1;
				m_lMonth++;
				if (m_lMonth > 12)
				{
					m_lMonth = 1;
					m_lYear++;
				}
			}
		}
		
		// 小月处理
		if (m_lMonth == 4 || m_lMonth == 6 || m_lMonth == 9 || m_lMonth == 11)
		{
			if (m_lDay > 30)
			{
				m_lDay = 1;
				m_lMonth++;
				if (m_lMonth > 12)
				{
					m_lMonth = 1;
					m_lYear++;
				}
			}
		}
	}

	// 向显示视图发送消息通知其显示数据
	if (m_pView != NULL) 
		m_pView->PostMessage(WM_SHOWGPSDATA, 0, 0);
}


/*************************************************************************
 *
 * 函数名称:
 *   TerminateRecv()
 *
 * 参数:
 *	 无
 *
 * 返回值:
 *	 无
 *
 * 说明:
 *	 强行终止侦听线程
 *
 ************************************************************************/

void CGPS::TerminateRecv()
{
	// 降低线程优先级到普通
	if (m_pReadThread != NULL)
		SetThreadPriority(m_pReadThread->m_hThread, THREAD_PRIORITY_NORMAL);

	// 强行终止侦听线程
	if (m_pReadThread != NULL)
	{
		TerminateThread(m_pReadThread->m_hThread, 0);
		m_pReadThread = NULL;
	}
}

void CGPS::ParamReset()
{
	m_pReadThread = NULL;
	m_bInfoStart = FALSE;
	m_dwPoint = 0;
	m_dwActRead = 0;
	memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
	m_bExitListen = FALSE;
	m_nLFNum = 0;

	m_lYear = 0;
	m_lMonth = 0;
	m_lDay = 0;
	m_lHour = 0;
	m_lMinute = 0;
	m_lSecond = 0;
	m_dLon = 0;
	m_dLat = 0;
	m_dAlt = 0;
	m_dVelo = 0;
	m_dDirection = 0;
}

⌨️ 快捷键说明

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