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

📄 gps_receiverdlg.cpp

📁 本程序是针对特定GPS接收机--JAVAD公司的legacy的一个应用
💻 CPP
字号:
// GPS_receiverDlg.cpp : implementation file
//

#include "stdafx.h"
#include "GPS_receiver.h"
#include "GPS_receiverDlg.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()

/////////////////////////////////////////////////////////////////////////////
inline CString NMEA::ToString()
{
	CString c;
	//时间(时:分:秒),经度(度d分m秒s),纬度(度d分m秒s),高度
	c.Format("%02d:%02d:%02.2f\t%02dd%02dm%02.5fs\t%02dd%02dm%02.5fs\t\t%.4f\n",
		time.h, time.m, time.s, lon.h, lon.m, lon.s, lat.h, lat.m, lat.s, hei);
	return c;
}

inline CString JPS::ToString()
{
	CString c;
	//时间(时:分:秒),X坐标,Y坐标,Z坐标
	c.Format("%02d:%02d:%02.2f\t%7.4f\t%7.4f\t%7.4f\n",
		time.h, time.m, time.s, x, y, z);
	return c;
}

// CGPS_receiverDlg dialog
CGPS_receiverDlg::CGPS_receiverDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGPS_receiverDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGPS_receiverDlg)
	m_RX = _T("");
	m_format = -1;
	m_timespan = _T("");
	m_filesize = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGPS_receiverDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGPS_receiverDlg)
	DDX_Control(pDX, IDC_STOP, m_stop);
	DDX_Control(pDX, IDC_START, m_start);
	DDX_Control(pDX, IDC_MSCOMM, m_com);
	DDX_Text(pDX, IDC_RX, m_RX);
	DDX_Radio(pDX, IDC_NMEA, m_format);
	DDX_Text(pDX, IDC_TIMESPAN, m_timespan);
	DDX_Text(pDX, IDC_FILESIZE, m_filesize);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGPS_receiverDlg, CDialog)
	//{{AFX_MSG_MAP(CGPS_receiverDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_START, OnStart)
	ON_BN_CLICKED(IDC_STOP, OnStop)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGPS_receiverDlg message handlers

BOOL CGPS_receiverDlg::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
	m_sync = FALSE;
	m_filesize = 0;
	m_timespan = "00:00";
	//默认使用NMEA/GGA格式
	m_format = 1;
	UpdateData(FALSE);
	//隐藏"Stop"按钮,显示"Start"按钮
	m_start.ShowWindow(SW_SHOW);
	m_stop.ShowWindow(SW_HIDE);
	//串口初始化
	m_com.SetCommPort(1);
	m_com.SetInputMode(1);//binary mode
	m_com.SetInBufferSize(4096);
	m_com.SetOutBufferSize(64);
	m_com.SetHandshaking(0);//0:none, 2:RTS/CTS(Request To Send/Clear To Send)
	m_com.SetSettings("115200,n,8,1");
	if(!m_com.GetPortOpen())
		m_com.SetPortOpen(TRUE);
	m_com.SetOutput(COleVariant("dm,/dev/ser/a\n"));//使接收机停止输出
	m_com.SetRThreshold(1);
	m_com.SetInputLen(0);
	m_com.GetInput();//清空接收区
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CGPS_receiverDlg::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 CGPS_receiverDlg::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 CGPS_receiverDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

BEGIN_EVENTSINK_MAP(CGPS_receiverDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CGPS_receiverDlg)
	ON_EVENT(CGPS_receiverDlg, IDC_MSCOMM, 1 /* OnComm */, OnCom, VTS_NONE)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CGPS_receiverDlg::OnCom() 
{
	// TODO: Add your control notification handler code here
	if(m_com.GetCommEvent() == 2) {
		COleSafeArray sa;
		sa.Attach(m_com.GetInput());
		long len = (long)sa.GetOneDimSize();
		m_filesize += len;
		m_stopTime = CTime::GetCurrentTime() - m_startTime;
		m_timespan = m_stopTime.Format("%M:%S");
		char c;
		m_RX = "";
		for (long i = 0; i < len; i++) {
			sa.GetElement(&i, &c);
			m_RX += c;
		}
		UpdateData(FALSE);
		m_inFile.Write(m_RX, len);
		switch (m_format) {
			case 0://collect NMEA GGA message
				CollectNMEA();		break;
			case 1://collect JPS {RT,PO} message
				CollectJPS();		break;
		}
	}
}

void CGPS_receiverDlg::OnStart()
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);//update m_format
	m_filesize = 0;//reset log info
	m_timespan = "00:00";
	UpdateData(FALSE);
	switch (m_format) {
		case 0://NMEA/GGA
			m_com.GetInput();//清空接收缓冲区
			m_com.SetRThreshold(84);
			m_com.SetInputLen(84);//一条GGA语句约为84字节
			m_com.SetOutput(COleVariant("em,/dev/ser/a,nmea/GGA:0.1\n"));
			break;
		case 1://JPS/{RT,PO}
			m_com.GetInput();//清空接收缓冲区
			m_com.SetRThreshold(47);//一条RT + 一条PO语句 = 47字节
			m_com.SetInputLen(47);
			m_com.SetOutput(COleVariant("em,/dev/ser/a,jps/{RT,PO}:0.1\n"));
			break;
	}
	m_startTime = CTime::GetCurrentTime();
	m_start.ShowWindow(SW_HIDE);
	m_stop.ShowWindow(SW_SHOW);
	//将串口读入的数据存储至.in文件,将处理过的数据存储至.out文件
	CString c;
	switch (m_format) {
		case 0:	c = "E:\\gps\\tool\\data\\NMEA";	break;
		case 1:	c = "E:\\gps\\tool\\data\\JPS";		break;
	}
	CTime t = CTime::GetCurrentTime();
	c += t.Format("%m%d_%H%M.in");
	m_inFile.Open((LPCTSTR)c, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
	c.Replace(".in", ".out");
	m_outFile.Open((LPCTSTR)c, CFile::modeCreate | CFile::modeWrite);
}

void CGPS_receiverDlg::OnStop()
{
	// TODO: Add your control notification handler code here
	m_com.SetOutput(COleVariant("dm,/dev/ser/a\n"));
	m_start.ShowWindow(SW_SHOW);
	m_stop.ShowWindow(SW_HIDE);
	m_inFile.Close();
	m_outFile.Close();
}


inline void CGPS_receiverDlg::CollectNMEA()
{
	if ((m_RX.Left(7) == "$GPGGA,") && (m_RX.Find('M') != -1) && (m_RX.Right(2) == "\xd\xa")) {
		ParseNMEA();
		m_outFile.WriteString(m_NMEA.ToString());
	} else if (m_sync == FALSE) {
		m_sync = TRUE;//进入同步调整状态
		m_com.SetInputLen(200);//包含至少2帧数据,以计算帧长;
		m_com.SetRThreshold(200);
	} else {
		int tmp = m_RX.Find("$GPGGA,");
		tmp = m_RX.Find("\n", tmp) - tmp + 1;
		m_com.SetOutput(COleVariant("dm,/dev/ser/a\n"));//暂停输出
		for (int i = 0; i < 10000; i++);//等待片刻,使GPS接收机响应“暂停输出”的指令
		m_com.SetInputLen(0);				
		m_com.GetInput();//清空缓冲区
		m_com.SetInputLen(tmp);//重新调整帧长
		m_com.SetRThreshold(tmp);
		m_sync = FALSE;//结束同步调整状态
		m_com.SetOutput(COleVariant("em,/dev/ser/a,nmea/GGA:0.1\n"));//重新开始输出
	}
}

inline void CGPS_receiverDlg::CollectJPS()
{
	if ((m_RX.Left(5) == "~~005") && (m_RX.Mid(11, 5) == "PO01E") && (m_RX.Right(1) == 10)) {
		ParseJPS();
		m_outFile.WriteString(m_JPS.ToString());
	} else if (m_sync == FALSE) {
		m_sync = TRUE;//进入同步调整状态
		m_com.SetInputLen(100);//包含至少2帧数据,以计算帧长
		m_com.SetRThreshold(100);
	} else {
		int tmp = m_RX.Find(10, '\xa') - m_RX.Find("~~005");//查找一帧“RT”信息后的第一个‘0a'结束符
		m_com.SetOutput(COleVariant("dm,/dev/ser/a\n"));//暂停输出
		for (int i = 0; i < 10000; i++);//等待片刻,使GPS接收机响应“暂停输出”的指令
		m_com.SetInputLen(0);
		m_com.GetInput();//清空缓冲区
		m_com.SetInputLen(tmp);
		m_com.SetRThreshold(tmp);
		m_sync = FALSE;//结束同步调整状态
		m_com.SetOutput(COleVariant("em,/dev/ser/a,jps/{RT,PO}:0.1\n"));//重新开始输出
	}
}
inline void CGPS_receiverDlg::ParseNMEA()
{
	int index = 0;
	//时间
	index = m_RX.Find(',', index);
	m_NMEA.time.h = atoi((LPCTSTR)m_RX.Mid(index + 1, 2));
	m_NMEA.time.m = atoi((LPCTSTR)m_RX.Mid(index + 3, 2));
	m_NMEA.time.s = (float)atof((LPCTSTR)m_RX.Mid(index + 5, 5));
	//纬度
	index = m_RX.Find(',', index+1);
	m_NMEA.lat.h = atoi((LPCTSTR)m_RX.Mid(index + 1, 2));
	m_NMEA.lat.m = atoi((LPCTSTR)m_RX.Mid(index + 3, 2));
	m_NMEA.lat.s = 60 * (float)atof((LPCTSTR)m_RX.Mid(index + 5, 8));
	//经度
	for (int i = 0; i < 2; i++) 
		index = m_RX.Find(',', index+1);
	m_NMEA.lon.h = atoi((LPCTSTR)m_RX.Mid(index + 1, 3));
	m_NMEA.lon.m = atoi((LPCTSTR)m_RX.Mid(index + 4, 2));
	m_NMEA.lon.s = 60 * (float)atof((LPCTSTR)m_RX.Mid(index + 6, 8));
	//高度与高程误差
	for (int j = 0; j < 5; j++) 
		index = m_RX.Find(',', index+1);
	m_NMEA.hei = atof((LPCTSTR)m_RX.Mid(index + 1, 7));
	for (int k = 0; k < 2; k++)
		index = m_RX.Find(',', index+1);
	m_NMEA.hei += atof((LPCTSTR)m_RX.Mid(index + 1, 7));
}
inline void CGPS_receiverDlg::ParseJPS()
{
	//处理“RT”
	UINT ui = (*(UINT*)(LPCTSTR)m_RX.Mid(5, 4));
	m_JPS.time.h = ui / 3600000;
	m_JPS.time.m = (ui % 3600000) / 60000;
	m_JPS.time.s = (float)((ui % 60000) / 1000.0);
	//处理“PO”
	m_JPS.x = *(double*)(LPCTSTR)m_RX.Mid(16, 8);
	m_JPS.y = *(double*)(LPCTSTR)m_RX.Mid(24, 8);
	m_JPS.z = *(double*)(LPCTSTR)m_RX.Mid(32, 8);
}

⌨️ 快捷键说明

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