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

📄 wgps.cpp

📁 自己做的基于PPC2003的GPS信号接收程序
💻 CPP
字号:
/*++ 
  Copyright (c) Wangsoft Corporation. All rights reserved.
  
  File: wgps.cpp
  
  Abstract:
  
  Contents:
	GPS related functions

--*/

#include "stdafx.h"
#include "wgps.h"
//#include <aygshell.h>
//#include <sipapi.h>

// Global Variables:
HANDLE g_hGPSPort = INVALID_HANDLE_VALUE;

HANDLE g_hGPSNewLocationData;
HANDLE g_hGPSDeviceStateChange;

GPS_POSITION g_gps_position;
GPS_DEVICE g_gps_device;

// Forward declarations of functions included in this code module:
DWORD WINAPI GPSReadThreadFunc(LPVOID lpParam);
void ParseRMC(LPTSTR szSentence);
LPTSTR GetNextToken(LPTSTR lpSentence, LPTSTR lpToken);

//
//  FUNCTION: GPSOpenDevice()
//
//  PURPOSE: Creates a connection to the GPS Intermediate Driver.
//
//  COMMENTS: 
//
//  Parameters:
//    hNewLocationData 
//      Handle to a Windows CE event created using CreateEvent, or NULL. 
//      The GPS Intermediate Driver signals the passed event whenever it has new GPS location information. 
//    hDeviceStateChange 
//      Handle to a Windows CE event created using CreateEvent, or NULL. 
//      The GPS Intermediate Driver signals the passed event whenever the state of the device changes. 
//    szDeviceName 
//      Reserved. Must be NULL. 
//    dwFlags 
//      Reserved. Must be 0. 
//
//  Return Values:
//    If successful, returns a handle to the GPS Intermediate Driver. 
//    If unsuccessful, returns NULL. 
//
HANDLE GPSOpenDevice(HANDLE hNewLocationData, HANDLE hDeviceStateChange, const WCHAR *szDeviceName, DWORD dwFlags)
{
	DWORD dwError;
	COMMTIMEOUTS ct;
	DCB dcb;

	if(NULL != hNewLocationData)
	{
		g_hGPSNewLocationData = hNewLocationData;
	}
	if(NULL != hDeviceStateChange)
	{
		g_hGPSDeviceStateChange = hDeviceStateChange;
	}

	g_hGPSPort = CreateFile (szDeviceName,
							GENERIC_READ | GENERIC_WRITE,
							0,			// COM port cannot be shared
							NULL,		// Always NULL for Windows CE
							OPEN_EXISTING,
							0,          // Non-overlapped operation only
							NULL);      // Always NULL for Windows CE
	if(INVALID_HANDLE_VALUE == g_hGPSPort)
	{
		dwError = GetLastError();
		return NULL;
	}

	// Set the timeouts to specify the behavior of reads and writes.
	GetCommTimeouts(g_hGPSPort, &ct);

	ct.ReadIntervalTimeout = MAXDWORD;
	ct.ReadTotalTimeoutMultiplier = 0;
	ct.ReadTotalTimeoutConstant = 0;
	ct.WriteTotalTimeoutMultiplier = 10;
	ct.WriteTotalTimeoutConstant = 1000;
	if(FALSE == SetCommTimeouts(g_hGPSPort, &ct))
	{
		GPSCloseDevice(g_hGPSPort);  // Close comm port
		dwError = GetLastError();
		return NULL;
	}

	// Get the current communications parameters, and configure baud rate
	dcb.DCBlength = sizeof(DCB);
	GetCommState(g_hGPSPort, &dcb);

	dcb.BaudRate = CBR_4800; // Set baud rate to 4,800
	dcb.fOutxCtsFlow = FALSE;
	dcb.fRtsControl = RTS_CONTROL_DISABLE;
	dcb.fDtrControl = DTR_CONTROL_DISABLE;
	dcb.fOutxDsrFlow = FALSE;
	dcb.fOutX = TRUE; // XON/XOFF control
	dcb.fInX = TRUE;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	if(FALSE == SetCommState(g_hGPSPort, &dcb))
	{
		GPSCloseDevice(g_hGPSPort); // Close comm port
		dwError = GetLastError();
		return NULL;
	}

	// Now need to create the thread that will be reading the comms port
	HANDLE hGPSReadThread = CreateThread(NULL, 0, GPSReadThreadFunc, NULL, 0, NULL);
	if(NULL != hGPSReadThread)
	{
		CloseHandle(hGPSReadThread);
	}
	else
	{
		GPSCloseDevice(g_hGPSPort); // Close comm port
		dwError = GetLastError();
		return NULL;
	}

	return g_hGPSPort;
}

//
//  FUNCTION: GPSGetPosition()
//
//  PURPOSE: Retrieves location information, including latitude and longitude.
//
//  COMMENTS: 
//
//  Parameters:
//    hGPSDevice 
//      Handle returned by a call to GPSOpenDevice. 
//      This parameter can also be NULL. If NULL, the GPS Intermediate Driver does not turn on the GPS hardware, 
//      but does return data if the data has already been received (through some other use of the GPS 
//      Intermediate Driver), and the data satisfies the criteria set by the dwMaximumAge parameter. 
//      Passing NULL enables applications that can use location information, but do not require it, 
//      to retrieve existing data without requiring that the GPS hardware consume power. 
//    pGPSPosition 
//      Pointer to a GPS_POSITION structure. On return, this structure is filled with location data 
//      obtained by the GPS Intermediate Driver. The dwValidFields member of the GPS_POSITION instance 
//      specifies which fields of the instance are valid. 
//    dwMaximumAge 
//      Maximum age, in milliseconds, of location information. The GPS Intermediate Driver only returns 
//      information that has been received within the time specified by this parameter. 
//      Any information that is older than this age is not returned. The elements of the GPS_POSITION 
//      instance that are valid for the given dwMaximumAge value are specified in the dwValidFields 
//      element of the instance. 
//    dwFlags 
//      Reserved. Must be 0. 
//
//  Return Values:
//    If successful, returns ERROR_SUCCESS. 
//    If unsuccessful, returns an error code.
//
DWORD GPSGetPosition(HANDLE hGPSDevice, GPS_POSITION *pGPSPosition, DWORD dwMaximumAge, DWORD dwFlags)
{
	pGPSPosition->dwVersion = g_gps_position.dwVersion;
	pGPSPosition->dwValidFields = g_gps_position.dwValidFields;
	pGPSPosition->dwFlags = g_gps_position.dwFlags;
	pGPSPosition->stUTCTime = g_gps_position.stUTCTime;
	pGPSPosition->dblLatitude = g_gps_position.dblLatitude;
	pGPSPosition->dblLongitude = g_gps_position.dblLongitude;
	pGPSPosition->flSpeed = g_gps_position.flSpeed;
	pGPSPosition->flHeading = g_gps_position.flHeading;
	pGPSPosition->dblMagneticVariation = g_gps_position.dblMagneticVariation;

	return ERROR_SUCCESS;
}

//
//  FUNCTION: GPSGetDeviceState()
//
//  PURPOSE: Retrieves information about the current state of the GPS hardware.
//
//  COMMENTS: 
//
//  Parameters:
//    pGPSDevice 
//      Pointer to a GPS_DEVICE structure. On return, this structure is filled with 
//      device data for the GPS hardware managed by the GPS Intermediate Driver. 

//  Return Values:
//    If successful, returns ERROR_SUCCESS. 
//    If unsuccessful, returns an error code.
//
DWORD GPSGetDeviceState(GPS_DEVICE *pGPSDevice)
{
	pGPSDevice->dwVersion = g_gps_device.dwVersion;
	pGPSDevice->dwDeviceState = g_gps_device.dwDeviceState;
	pGPSDevice->ftLastDataReceived = g_gps_device.ftLastDataReceived;

	return ERROR_SUCCESS;
}

//
//  FUNCTION: GPSCloseDevice()
//
//  PURPOSE: Closes the connection to the GPS Intermediate Driver.
//
//  COMMENTS: 
//
//  Parameters:
//    hGPSDevice 
//      Handle returned by a call to GPSOpenDevice. 
//
//  Return Values:
//    If successful, returns ERROR_SUCCESS. 
//    If unsuccessful, returns an error code.
//
DWORD GPSCloseDevice(HANDLE hGPSDevice)
{

	if(INVALID_HANDLE_VALUE != hGPSDevice)
	{
		CloseHandle(hGPSDevice);
		g_hGPSPort = INVALID_HANDLE_VALUE;
	} 
	else
	{
		if(INVALID_HANDLE_VALUE != g_hGPSPort)
		{
			CloseHandle(g_hGPSPort);
			g_hGPSPort = INVALID_HANDLE_VALUE;
		} 
	}

	return ERROR_SUCCESS;
}

// Thread function reads NMEA output from GPS device.
DWORD WINAPI GPSReadThreadFunc(LPVOID lpParam)
{
	DWORD dwBytesRead, dwEvtMask;
	char szSentence[1000], c;
	TCHAR szwcsSentence[1000];
	int nc = 0;

	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);

	// Specify a set of events to be monitored for the port.
	SetCommMask(g_hGPSPort, EV_RXCHAR | EV_ERR);

	// Init g_gps_position.
	g_gps_position.dwVersion = GPS_VERSION_1;
	g_gps_position.dwFlags = GPS_DATA_FLAGS_HARDWARE_ON;
	g_gps_position.dwValidFields = 0;

	// Init g_gps_device.
	g_gps_device.dwVersion = GPS_VERSION_1;
	g_gps_device.dwDeviceState = GPS_DEVICE_STATE_ON;

	// Send GPSDeviceStateChange ON event.
	if(NULL != g_hGPSDeviceStateChange)
	{
		SetEvent(g_hGPSDeviceStateChange);
	}

	while(INVALID_HANDLE_VALUE != g_hGPSPort)
	{
		// Waiting for EV_RXCHAR and EV_ERR event.
		WaitCommEvent(g_hGPSPort, &dwEvtMask, 0);

		// Again specify a set of events to be monitored for the port.
		SetCommMask(g_hGPSPort, EV_RXCHAR | EV_ERR);

		if(dwEvtMask == EV_ERR)
		{
			// Deal with communications error
			return GetLastError();
		}

		do
		{
			// If dwEvtMask == EV_RXCHAR
			if(!ReadFile(g_hGPSPort, &c, 1, &dwBytesRead, NULL))
			{
				return GetLastError();
			}

			if(dwBytesRead == 1)
			{
				if(c != '\n') // LF marks end of sentence
				{
					szSentence[nc++] = c;
				}
				else
				{
					// Remove trailing CR
					szSentence[nc-1] = '\0';
					nc = 0;
					if(strlen(szSentence) <= 6) 
					{
						break;
					}
					else if(szSentence[0] != '$')
					{
						break;
					}
					else
					{
						// Read a sentence. Convert to Unicode
						mbstowcs(szwcsSentence, szSentence, 1000);

						// Find sentence ID
						if(wcsncmp(&szwcsSentence[3], _T("RMC"), 3) == 0)
						{
							// Parse RMC data into g_gps_position and g_gps_device.
							ParseRMC(szwcsSentence);

							// Send GPSNewLocationData event.
							if((NULL != g_hGPSNewLocationData) && (0 != g_gps_position.dwValidFields))
							{
								SetEvent(g_hGPSNewLocationData); 
							}
						}
					}
				}
			}
		}
		while (dwBytesRead == 1);
	}

	// Mark the state flag from ON to OFF.
	g_gps_position.dwFlags = GPS_DATA_FLAGS_HARDWARE_OFF;
	g_gps_position.dwValidFields = 0;
	g_gps_device.dwDeviceState = GPS_DEVICE_STATE_OFF;

	// Send GPSDeviceStateChange OFF event.
	if(NULL != g_hGPSDeviceStateChange)
	{
		SetEvent(g_hGPSDeviceStateChange);
	}

	return ERROR_SUCCESS;
}

// Parses a RMC sentence which has the format:
// $GPRMC,195531,A,5326.986,N,00610.147,W,000.0,360.0,170500,007.2,W*7F
void ParseRMC(LPTSTR szSentence)
{
	TCHAR szToken[20];
	DWORD dwCheckSum = 0;
	DWORD dwSentenceCheckSum;
	LPTSTR lpEnd;

	GPS_POSITION gps_position;

	// Calculate the checksum. Exclude $ and work up to *
	for(UINT i = 1; i < wcslen(szSentence) && szSentence[i] != '*'; i++)
	{
		dwCheckSum ^= szSentence[i];
	}

	// lpNextTok points at ID $GPRMS, ignore this
	szSentence = GetNextToken(szSentence, szToken);

	// Time of Fix, convert to Unicode (UTC hhmmss)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.stUTCTime.wSecond = (WORD)wcstoul(szToken+4, &lpEnd, 10);
	szToken[4] = '\0';
	gps_position.stUTCTime.wMinute = (WORD)wcstoul(szToken+2, &lpEnd, 10);
	szToken[2] = '\0';
	gps_position.stUTCTime.wHour = (WORD)wcstoul(szToken, &lpEnd, 10);

	// Navigation receiver (GPS) warning
	szSentence = GetNextToken(szSentence, szToken);
	if(szToken[0] != 'A')
	{
		// Suspect signal
		g_gps_position.dwValidFields = 0;
		return;
	}

	// If Receiving OK
	// Latitude (ddmm.ss)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.dblLatitude = wcstod(szToken, NULL);

	// Latitude N or S
	szSentence = GetNextToken(szSentence, szToken);
	if (szToken[0] == 'S')
	{
		gps_position.dblLatitude = 0 - gps_position.dblLatitude;
	}

	// Longitude (dddmm.ss)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.dblLongitude = wcstod(szToken, NULL);

	// Longitude E or W
	szSentence = GetNextToken(szSentence, szToken);
	if (szToken[0] == 'W')
	{
		gps_position.dblLongitude = 0 - gps_position.dblLongitude;
	}

	// Speed (Knots)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.flSpeed = (float)wcstod(szToken, NULL);

	// Course made good (Deg)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.flHeading = (float)wcstod(szToken, NULL);

	// Date (ddmmyyyy)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.stUTCTime.wYear = (WORD)wcstoul(szToken+4, &lpEnd, 10);
	szToken[4] = '\0';
	gps_position.stUTCTime.wMonth = (WORD)wcstoul(szToken+2, &lpEnd, 10);
	szToken[2] = '\0';
	gps_position.stUTCTime.wDay = (WORD)wcstoul(szToken, &lpEnd, 10);

	// Magnetic Variation (Deg)
	szSentence = GetNextToken(szSentence, szToken);
	gps_position.dblMagneticVariation = wcstod(szToken, NULL);

	// Magnetic Variation E or W
	szSentence = GetNextToken(szSentence, szToken);
	if (szToken[0] == 'W')
	{
		gps_position.dblMagneticVariation = 0 - gps_position.dblMagneticVariation;
	}

	// Do the check sum
	szSentence = GetNextToken(szSentence, szToken);
	dwSentenceCheckSum = wcstoul(szToken, &lpEnd, 16);
	if(dwCheckSum == dwSentenceCheckSum)
	{
		// Checksum OK
		// Set g_gps_position Data.
		g_gps_position.dwValidFields = GPS_VALID_MAGNETIC_VARIATION;
		g_gps_position.stUTCTime = gps_position.stUTCTime;
		g_gps_position.dblLatitude = gps_position.dblLatitude;
		g_gps_position.dblLongitude = gps_position.dblLongitude;
		g_gps_position.flSpeed = gps_position.flSpeed;
		g_gps_position.flHeading = gps_position.flHeading;
		g_gps_position.dblMagneticVariation = gps_position.dblMagneticVariation;

		// Set g_gps_device Data.
		SystemTimeToFileTime(&g_gps_position.stUTCTime, &g_gps_device.ftLastDataReceived);
	}
	else
	{
		// Checksum ERROR
		g_gps_position.dwValidFields = 0;
	}
}

// Returns the next token from the sentence.
LPTSTR GetNextToken(LPTSTR lpSentence, LPTSTR lpToken)
{
	lpToken[0] = '\0';
	if(lpSentence == NULL) // empty sentence
	{
		return NULL;
	}
	if(lpSentence[0] == '\0') // end of sentence
	{
		return NULL;
	}
	if(lpSentence[0] == ',') // empty token
	{
		return lpSentence + 1;
	}
	while(*lpSentence != ',' && *lpSentence != '\0' && *lpSentence != '*')
	{
		*lpToken = *lpSentence;
		lpToken++;
		lpSentence++;
	}

	// Skip over comma that terminated the token.
	lpSentence++;
	*lpToken = '\0';

	return lpSentence;
}

⌨️ 快捷键说明

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