gpsviewerdlg.cpp

来自「GPS信号强度」· C++ 代码 · 共 342 行

CPP
342
字号
/* GPSViewerDlg.cpp
 * ----------------
 * This file is the heart of the GPSViewer Application and demonstrates how to
 * use the Centrality GPS NMEA interface located on COM7.  Careful study of this
 * code will allow the user to understand the methods needed to fully utilize
 * the COM7 GPS port.  This code is intended to be used as a fully functional
 * sample for complete integration with the Centrality GPS platform and this 
 * purpose only.  Debug statements have been commented out but left embedded in
 * the code for development purposes.
 *
 * Here are the key steps that you should take note of as you walk through
 * this code:
 *
 * 1. Using Createfile to open the COM7 port
 * 2. Setting up the COM7 port
 * 3. Creating a thread to wait on COM7 and read its contents
 * 4. Parsing NMEA commands that come out of the COM7 port
 * 5. Safely closing the port
 *
 * Author: Howard Shen, Centrality Communications MTS
 * Date: 8/29/03
*/

#include "stdafx.h"
#include "GPSViewer.h"
#include "GPSViewerDlg.h"
#include "GPSExport.h"
#include "windows.h"
#include "math.h"
#include "stdlib.h"

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

/* Global Defines */
/* -------------- */
#define g_UpdateInterval 1000  // This is the update interval for the screen (in milliseconds)


/* Global variables */
/* ---------------- */
CString time, lat, latdir, lon, londir, numused, alt;
UINT g_allinit;
char buff[1000];		// Read buffer
UINT m_nTimer;			// Timer for refreshing the screen
HANDLE comm_hand;		// Global handle to the COM7 port
HANDLE nmeathread_hand; // Global handle to the NMEA reading thread


/* Function Prototypes */
/* ------------------- */
DWORD WINAPI ReadNMEAThread(LPVOID lpParameter);
// This is the function which contorls the NMEA reading thread


/* START of Microsoft Machine Generated Message Handler Code - DO NOT MODIFY */
/////////////////////////////////////////////////////////////////////////////
// CGPSViewerDlg dialog

CGPSViewerDlg::CGPSViewerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGPSViewerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGPSViewerDlg)
	m_staticlong = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGPSViewerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGPSViewerDlg)
	DDX_Text(pDX, IDC_STATIC_LONG, m_staticlong);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGPSViewerDlg, CDialog)
	//{{AFX_MSG_MAP(CGPSViewerDlg)
	ON_WM_CANCELMODE()
	ON_WM_TIMER()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// End of Microsoft machine generated code


/* Function: OnInitDialog()
 * ------------------------
 * This fucntion gets called at startup and initalizes the whole program.
 * Initializing the COM port takes place here.  Key steps (1), (2) ,and (3)
 * take place in this function.
 */
BOOL CGPSViewerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	DCB commDCB;
	COMMTIMEOUTS timeouts;
	DWORD dwError;
	ULONG bytesWritten;

	// 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
	
	CenterWindow(GetDesktopWindow());	// center to the hpc screen

	// Key Step #1 - Using CreateFile to open COM7
	// -------------------------------------------
	comm_hand = CreateFile(L"COM7:", GENERIC_READ | GENERIC_WRITE, 0, NULL,
								OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
	if(comm_hand == NULL)
	{
		MessageBox (TEXT("Unable to open COM7."), TEXT("Error"), MB_OK);
		dwError = GetLastError ();
		DEBUGMSG(1, (L"Opening COM7 failed: %d!\r\n", (int)GetLastError()));
		return TRUE;
	}

	commDCB.DCBlength = sizeof (DCB);     

	// Key Step #2 - Setting the COM7 port settings
	// --------------------------------------------
	// Get the default port setting information.
	if(!GetCommState (comm_hand, &commDCB))
	{
		CloseHandle(comm_hand);
		DEBUGMSG(1, (L"Failed in getting COM7 DCB settings: %d!\r\n", (int)GetLastError()));
		return FALSE;
	}

	commDCB.DCBlength = sizeof(DCB); 
	commDCB.BaudRate = 38400;             // Current baud
	commDCB.ByteSize = 8;                 // Number of bits/bytes, 4-8
	commDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space 
	commDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2
  
	// Setting COM7 to Centrality speicifcations
	if (!SetCommState(comm_hand, &commDCB))
	{
		CloseHandle(comm_hand);
		MessageBox (TEXT("Unable to configure COM7 DCB settings"), TEXT("Error"), MB_OK);
		DEBUGMSG(1, (L"Error in trying to set COM7 DCB settings: %d!\r\n", (int)GetLastError()));
		dwError = GetLastError ();
		return FALSE;
	}
 
	// Get the default timeout settings for port
	if(!GetCommTimeouts(comm_hand, &timeouts))
	{
		CloseHandle(comm_hand);
		DEBUGMSG(1, (L"Failed in getting COM7 timeout settings: %d!\r\n", (int)GetLastError()));
		return FALSE;
	}
	DEBUGMSG(1, (L"DCB set successfully.\r\n"));

	// Change the timeouts structure settings to Centrality settings
	timeouts.ReadIntervalTimeout = 0;  
	timeouts.ReadTotalTimeoutMultiplier = 0;  
	timeouts.ReadTotalTimeoutConstant = 0;    

	// Set the time-out parameters for all read and write operations on the port. 
	if (!SetCommTimeouts(comm_hand, &timeouts))
	{
		CloseHandle(comm_hand);
		MessageBox (TEXT("Unable to configure COM7 timeout settings"), TEXT("Error"), MB_OK);
		DEBUGMSG(1, (L"Error in trying to set COM7 timeout settings: %d!\r\n", (int)GetLastError()));
		dwError = GetLastError ();
		return FALSE;
	}
	DEBUGMSG(1, (L"Comm timeouts set successfully.\r\n"));

	// Key Step #3 - Creating a thread to wait on COM7 and read its contents
	// ----------------------------------------------------------------------
	// * See definition of ReadNMEAThread() for details on thread operations
	nmeathread_hand = CreateThread(NULL, 0, ReadNMEAThread, NULL, 0, NULL);
	if(!nmeathread_hand)
	{
		DEBUGMSG(1, (L"Could not create NMEA read thread.\r\n"));
		return 0;
	}
	m_nTimer = SetTimer(1, g_UpdateInterval, 0);
	g_allinit = 1;

	// Writing something to the COM7 port to start GPS processing (Added March 2004)
	// -----------------------------------------------------------------------------
	if(!WriteFile(comm_hand, (L"StartGPS!\r\n"), 20, &bytesWritten, NULL))
	{
		DEBUGMSG(1, (L"Could not write message to COM7 to start GPS.\r\n"));
	}
	DEBUGMSG(1, (L"GPS started! Bytes written: %d.\r\n", bytesWritten));
	
	return TRUE;
}


/* Function: OnCancelMode()
 * ------------------------
 * This fucntion gets called to deinitialize the GPSViewer.  Notice that you  
 * should wait for the NMEA reading thread to exit cleanly before continuing.
 * Key step (5) is covered by this function.
 */
void CGPSViewerDlg::OnCancelMode() 
{
	CDialog::OnCancelMode();
	
	if(g_allinit == 1) {
		DEBUGMSG(1, (L"Cancel application.  Shutting down.\r\n"));	

		SetCommMask(comm_hand, 0);

		// Wait for NMEA reading thread to cleanly exit (max 5 sec)
		WaitForSingleObject(nmeathread_hand, 5000);

		KillTimer(m_nTimer);

		// This call officially closes the COM7 and shuts down GPS.
		CloseHandle(comm_hand);

		g_allinit = 0;
	} else {
		DEBUGMSG(1, (L"Trying to cancel, but nothing was started.  Exiting.\r\n"));
	}
}


/* Function: OnNotify()
 * ------------------------
 * This fucntion is not vital to the opertaions of GPS but needs to exist
 * for Microsoft EVC programs.  There is no need to modify/study this function.
 */
BOOL CGPSViewerDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CDialog::OnNotify(wParam, lParam, pResult);
}


/* Function: OnNotify()
 * --------------------
 * This fucntion's only purpose is to force the application to redraw the
 * output at the interval specified by g_UpdateInterval.  It's not that 
 * important.
 */
void CGPSViewerDlg::OnTimer(UINT nIDEvent) 
{
	//MessageBeep(0xFFFFFFFF);  // Beep
	DEBUGMSG(1, (L"Timer Signled."));
	Invalidate();
	UpdateWindow();
	CDialog::OnTimer(nIDEvent);
}


/* Function: ReadNMEAThread()
 * --------------------------
 * This is the function responsible for reading the GPS NMEA port (COM7) 
 * and parsing the output - key step (4).  Basically, this function sets
 * up to read the COM port whenever an event is passed down by the GPS 
 * NMEA driver.  This event is the simple EV_RXCHAR.  You must first set up
 * the function to wait on this even (4a) and then read from the port when
 * the event is signified (4b).  After reading information out of the port,
 * you must then parse it to extract the needed location/satellite 
 * information (4c).  You will notice that all the information needed
 * by GPSViewer is contained in the $GPGGA NMEA message.  You are obviously
 * free to do use whatever information you need that is supported by the 
 * NMEA standard.  If you need other mesages to be supported by Centrality
 * Communications, please contact your local representative.
 */
DWORD WINAPI ReadNMEAThread(LPVOID lpParameter)
{
	int start, endline, onestart, oneend, length, linelen, degdig;
	ULONG bytesRead;
	DWORD EventMask = EV_RXCHAR;

	// Setting the CommMask to listen for this event (4a)
	SetCommMask(comm_hand, EV_RXCHAR);
	
	// Wait on the event
	while(WaitCommEvent(comm_hand, &EventMask, NULL))
	{
		// Clear the buffer before you start reading
		memset(buff, 0, 1000);

		// Read from COM7 (4b)
		while(ReadFile(comm_hand, buff, 1000, &bytesRead, NULL))
		{
			if(bytesRead == 0)
				break;

			CString dacstr(buff);
			DEBUGMSG(1, (L"bytesRead = %d", bytesRead));
			DEBUGMSG(1, (L"CString = %s", dacstr));

			start = 0;
			endline = 0;

			// Parse/Process the output (4c)
			while(1)
			{
				start = dacstr.Find(L"$G", start);
				if(start < 0)
					break;
				endline = dacstr.Find(L"\r\n", start);
				if(endline < 0)
					break;

				linelen = endline - start;
				//DEBUGMSG(1, (L"start = %d endline = %d length = %d", start, endline, linelen));	

				// Extract one line
				CString oneline;
				oneline = dacstr.Mid(start, linelen);
				DEBUGMSG(1, (L"Oneline = %s", oneline));

				// Process one line
				onestart = 0;
				oneend = 0;
				if(oneline.Left(6) == L"$GPGGA")
				{
					onestart += oneline.Find(L",", onestart);
					oneend = oneline.Find(L",", onestart+1);
					length = oneend - onestart - 1;
					time = oneline.Mid(onestart + 1, length);
					time = time.Left(2) + L":" + time.Mid(2,2) + L":" + time.Right(5);
					//DEBUGMSG(1, (L"onestart = %d oneend = %d length = %d", onestart, oneend, length));

					onestart = oneend+1;
					oneend = oneline.Find(L",", onestart+1);
					length = oneend - onestart;
					lat = oneline.Mid(onestart, length);
					degdig = lat.GetLength() - 2;
					lat = lat.Left(2) + L"

⌨️ 快捷键说明

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