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

📄 gpsdlg.cpp

📁 GPS数据接收及分析测试程序,由魏先生完成,本人收集整理,绝对可用.
💻 CPP
字号:
// GPSDlg.cpp : implementation file
//

#include "stdafx.h"
#include "GPS.h"
#include "GPSDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGPSDlg dialog

CGPSDlg::CGPSDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGPSDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGPSDlg)
	m_strCourse = _T("");
	m_strDate = _T("");
	m_strLatitude = _T("");
	m_strLongitude = _T("");
	m_strSpeed = _T("");
	m_strTime = _T("");
	m_strStatus = _T("");
	m_nCommIndex = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGPSDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGPSDlg)
	DDX_Control(pDX, IDC_COMBO_COMM, m_Comm);
	DDX_Text(pDX, IDC_EDIT_COURSE, m_strCourse);
	DDX_Text(pDX, IDC_EDIT_DATE, m_strDate);
	DDX_Text(pDX, IDC_EDIT_LATITUDE, m_strLatitude);
	DDX_Text(pDX, IDC_EDIT_LONGITUDE, m_strLongitude);
	DDX_Text(pDX, IDC_EDIT_SPEED, m_strSpeed);
	DDX_Text(pDX, IDC_EDIT_TIME, m_strTime);
	DDX_Text(pDX, IDC_EDIT_STATUS, m_strStatus);
	DDX_CBIndex(pDX, IDC_COMBO_COMM, m_nCommIndex);
	if(!pDX->m_bSaveAndValidate)
		{
		CString strComm;
		for(int i=1;i<64;i++)
			{
			strComm.Format("COM%d",i);
			m_Comm.AddString(strComm);
			}
		}
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGPSDlg, CDialog)
	//{{AFX_MSG_MAP(CGPSDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDSTART, OnStart)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDSTOP, OnStop)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// 对话框消息处理函数
/////////////////////////////////////////////////////////////////////////////

//对话框初始化
BOOL CGPSDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	GetDlgItem(IDSTART)->EnableWindow(TRUE);					//"开始"按钮使能
	GetDlgItem(IDSTOP)->EnableWindow(FALSE);					//"停止"按钮禁止
	GetDlgItem(IDCANCEL)->EnableWindow(TRUE);					//"退出"按钮使能


	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CGPSDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CGPSDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CGPSDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//"开始"按钮响应函数
void CGPSDlg::OnStart() 
{
	// TODO: Add your control notification handler code here
	CString strComm;											//串口名

	UpdateData(TRUE);
	m_Comm.GetLBText(m_nCommIndex, strComm);					//得到选择的串口名称
	strComm=_T("\\\\.\\")+strComm;
	ClearEdit();
	if (InitComm(strComm))
	{
		m_strRecv.Empty();										//清空接收到的字符串
		SetTimer(1, 250, NULL);									//启动定时器(250毫秒)
		GetDlgItem(IDSTART)->EnableWindow(FALSE);				//"开始"按钮禁止
		GetDlgItem(IDSTOP)->EnableWindow(TRUE);					//"停止"按钮使能
		GetDlgItem(IDCANCEL)->EnableWindow(FALSE);				//"退出"按钮禁止
	}
	else
		AfxMessageBox("串口初始化错误!");
}

//"停止"按钮响应函数
void CGPSDlg::OnStop() 
{
	// TODO: Add your control notification handler code here
	
	//禁止发送接收并且清空发送接收缓冲区
	PurgeComm(m_hComm, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);	
	CloseHandle(m_hComm);										//关闭串口
	KillTimer(1);												//关闭定时器
	//按钮状态变更
	GetDlgItem(IDSTART)->EnableWindow(TRUE);
	GetDlgItem(IDSTOP)->EnableWindow(FALSE);
	GetDlgItem(IDCANCEL)->EnableWindow(TRUE);	
}

//定时器响应函数(周期250毫秒)
void CGPSDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if (nIDEvent == 1)
	{
		ClearRecvBuf();											//接收缓冲区清0
		ClearCommError(m_hComm, &m_dwError, &m_CommStat);		//清除通信错误
		//读取接收缓冲区中的数据
		ReadFile(m_hComm, m_RecvBuf, m_CommStat.cbInQue, &m_dwRwByte, NULL);
		m_strRecv += m_RecvBuf;									//在未处理完的字符串后面添加上新接收到的数据	
		//获取GPS的定位参数
		if (GetGPSParam())
			UpdateData(FALSE);									//更新GPS参数的显示
	}
}

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

//接收缓冲区清0
void CGPSDlg::ClearRecvBuf()
{
	memset(m_RecvBuf, 0, MAXLENGTH);
}

//清除编辑框显示
void CGPSDlg::ClearEdit()
{
	m_strCourse = _T("");
	m_strDate = _T("");
	m_strLatitude = _T("");
	m_strLongitude = _T("");
	m_strSpeed = _T("");
	m_strTime = _T("");
	m_strStatus = _T("");
	
	UpdateData(FALSE);
}

//初始化串口
//入口:strComm(串口名)
//返回:TRUE(成功);FALSE(失败)
BOOL CGPSDlg::InitComm(CString strComm)
{
	int i;
	DCB dcb;
	COMMTIMEOUTS TimeOuts;

	for (i=0; i<3; i++)											//串口最多初始化3次
	{
		m_hComm = CreateFile(strComm, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (m_hComm != INVALID_HANDLE_VALUE)
			break;
	}
	if (i == 3)													//串口初始化失败
	{
		AfxMessageBox("串口初始化失败...");
		return FALSE;
	}
	
	SetupComm(m_hComm, MAXLENGTH, MAXLENGTH);					//设置发送接收缓冲区大小
	
	TimeOuts.ReadIntervalTimeout = 0;							//设定5个超时参数
	TimeOuts.ReadTotalTimeoutMultiplier = 0;
	TimeOuts.ReadTotalTimeoutConstant = 500;
	TimeOuts.WriteTotalTimeoutMultiplier = 0;
	TimeOuts.WriteTotalTimeoutConstant = 500;
	SetCommTimeouts(m_hComm, &TimeOuts);						//设置超时参数
	
	GetCommState(m_hComm, &dcb);								//获得通信状态
	dcb.fAbortOnError = FALSE;									//有错误不停止
	dcb.BaudRate = CBR_4800;									//波特率4800
	dcb.ByteSize = 8;											//8位
	dcb.Parity = NOPARITY;										//奇校验
	dcb.StopBits = ONESTOPBIT;									//1位停止位
	SetCommState(m_hComm, &dcb);								//设置通信状态
	PurgeComm(m_hComm, PURGE_TXCLEAR|PURGE_RXCLEAR);			//清空发送和接收缓冲区	
	
	return TRUE;
}

//获得GPS参数
//注意:从GPS接收到的字符串已经在m_strRecv中,由于是定时接收,所以在这个字符串的头和尾都可能存在
//     不完整的NMEA输出字符串,在处理时要特别注意
//返回:TRUE(格式正确);FALSE(格式错误)
BOOL CGPSDlg::GetGPSParam()
{
	int i,j;
	CString str,strNEMA;
		
	//先判断是否接收到数据
	if (m_strRecv.IsEmpty())
		return FALSE;

	//若字符串不是以'$'开头的,必须删掉这部分不完整的
	if (m_strRecv[0] != '$')
	{
		i = m_strRecv.Find('\n', 0);
		if (i == -1)
			return FALSE;										//尾部未接收完整,必须等接收完后才能删除
		m_strRecv.Delete(0, i+1);								//尾部已接收完整(尾部为\r\n结束),删除不完整的部分
	}
	
	//截取完整的NMEA-0183输出语句(m_strRecv中可能有多条语句,每条间以\r\n分隔)
	for (;;)
	{
		i = m_strRecv.Find('\n', 0);
		if (i == -1)
			break;												//所有的完整输出语句都已经处理完毕,退出循环
		
		//截取完整的NMEA-0183输出语句
		strNEMA = m_strRecv.Left(i+1);							
		m_strRecv.Delete(0, i+1);
		//下面对各种输出语句进行分别处理
		if (strNEMA.Find("$GPRMC",0) == 0)
		{
			//该输出语句中的各项以','分隔
			for (i=j=0; strNEMA[i]!='\r'; i++)					//j为逗号的计数器
			{
				if (strNEMA[i] == ',')
				{
					j++;
					str = "";
					for (i++; strNEMA[i]!=','&&strNEMA[i]!='\r'; i++)
						str += strNEMA[i];						//str为某项的值
					i--;
					
					//对各项数据分别处理
					switch (j)
					{
					case 1:										//时间(UTC)					
						m_strTime = str.Left(6);
						m_strTime.Insert(2, ':');
						m_strTime.Insert(5, ':');
						break;
					case 2:										//状态(A-数据有效;V-数据无效,还未定位)
						if (str == "A")
							m_strStatus = "有效数据";
						else if(str == "V")
							m_strStatus = "正在定位...";
						else
							m_strStatus = "非法数据格式";
						break;
					case 3:										//纬度(ddmm.mmmm)
						str.Insert(2, "度");
						str += "分";
						m_strLatitude = str;
						break;
					case 4:										//纬度指示(N-北纬;S-南纬)
						if (str == "N")
							m_strLatitude.Insert(0, "北纬");
						else
							m_strLatitude.Insert(0, "南纬");
						break;
					case 5:										//经度(dddmm.mmmm)
						str.Insert(3, "度");
						str += "分";
						m_strLongitude = str;
						break;
					case 6:										//经度指示(E-东经;W-西经)
						if (str == "E")
							m_strLongitude.Insert(0, "东经");
						else
							m_strLongitude.Insert(0, "西经");
						break;
					case 7:										//速度(单位:节)
						m_strSpeed = str;
						break;
					case 8:										//航向(单位:度)
						m_strCourse = str;
						break;
					case 9:										//日期(UTC)
						m_strDate = "";
						m_strDate += "20";
						m_strDate += str[4];
						m_strDate += str[5];
						m_strDate += "-";
						m_strDate += str[2];
						m_strDate += str[3];
						m_strDate += "-";
						m_strDate += str[0];
						m_strDate += str[1];
						break;
					default:
						break;
					}
				}
			}
		}
		else if (strNEMA.Find("$GPGGA",0) == 0)
		{
		
		}
		else if (strNEMA.Find("$GPGSA",0) == 0)
		{
		
		}
		else if (strNEMA.Find("$GPGSV",0) == 0)
		{
		
		}
		else if (strNEMA.Find("$GPGLL",0) == 0)
		{
		
		}
		else if (strNEMA.Find("$GPVTG",0) == 0)
		{
		
		}
		else
			return FALSE;										//格式错误
	}
	return TRUE;
}

⌨️ 快捷键说明

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