?? nmea0183.cpp
字號:
///////////////////////////////////////////////////////////////////////////////
// Nmea0183.cpp : implementation of the CNmea0183 class
//
// Copyright (c) 2004,上海合眾思壯科技有限責任公司GIS部
//
// All rights reserved
//
// 文件名稱:Nmea0183.cpp
//
// 摘要 :Nmea0183協議類
//
// 作者 :Hansom
//
// 當前版本:1.1
//
// 完成日期:2004年04月12日
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Nmea0183.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////////////////
// Construction
CNmea0183::CNmea0183()
{
m_nWritePtr = 0;
m_nAllSatNum = 0;
m_nRevSatNum = 0;
m_nRevFrmNum = 0;
m_pchProBuf = new char[BUFFER_SIZE];
memset(m_SatData, 0, sizeof(ST_SAT_DATA) * SAT_NUMBER);
}
///////////////////////////////////////////////////////////////////////////////
// Destruction
CNmea0183::~CNmea0183()
{
if(m_pchProBuf != NULL)
{
delete [] m_pchProBuf;
m_pchProBuf = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
// 得到坐標轉換參數
double CNmea0183::GetCoor(const double dbIn)const
{
int nDu = (int)(dbIn / 100);
return nDu + (dbIn - nDu * 100) / 60;
}
///////////////////////////////////////////////////////////////////////////////
// 從接收緩沖區的數據搜索完整一幀,并將其轉換為具體的數據結構
int CNmea0183::SearchOneFrame(char *pchRevBuf, const int nRevLen, int &nReadPtr,
const int nWritePtr, ST_MSG *pMsg)
{
int nFrmNum = 0;
int ntempReadPtr = nReadPtr;
byte bdata;
static BOOL bIsHead = FALSE;
while(ntempReadPtr != nWritePtr)
{
// 接收緩沖區內容未處理完
bdata=pchRevBuf[ntempReadPtr];
ntempReadPtr++;
if(ntempReadPtr >= nRevLen)
{
ntempReadPtr = 0;
}
if(bdata == '$')
{
// 找到起始符
m_nWritePtr=0;
bIsHead = TRUE;
}
else if(!bIsHead)
{
// 尚未找到起始符
continue;
}
else if(bdata == 0x0d)
{
// 找到結束符
m_pchProBuf[m_nWritePtr] = 0;
bIsHead = FALSE;
if(ProOneFrm(pMsg))
{
// 正確處理,返回一幀數據
nFrmNum = 1;
m_nWritePtr=0;
break;
}
else
{
// 丟掉該幀,繼續處理之后字節
m_nWritePtr=0;
continue;
}
}
m_pchProBuf[m_nWritePtr] = bdata;
m_nWritePtr++;
if(m_nWritePtr >= BUFFER_SIZE)
{
// 緩沖區已滿還未收全一幀,放棄當前緩沖區數據,繼續處理之后字節
m_nWritePtr=0;
continue;
}
}
nReadPtr = ntempReadPtr;
return nFrmNum;
}
///////////////////////////////////////////////////////////////////////////////
// 判斷數據檢驗是否正確,如果正確則生成具體數據結構
BOOL CNmea0183::ProOneFrm(ST_MSG *pMsg)
{
BOOL bRtn = FALSE;
char *p, check[2];
char xor_chk, val;
// 計算校驗
p = strchr(m_pchProBuf, '*');
if(p == NULL)
{
return bRtn;
}
p++;
strncpy(check, p, 2);
xor_chk = '$';
// 計算校驗
for(int i=0; ; i++)
{
if(m_pchProBuf[i] == '*')
{
break;
}
xor_chk ^= m_pchProBuf[i];
}
if((check[0] >= '0') && (check[0] <= '9'))
{
val = (check[0] - '0') * 16;
}
else
{
val = (check[0] - 0x37) * 16;
}
if((check[1] >= '0') && (check[1] <= '9'))
{
val += (check[1] - '0');
}
else
{
val += (check[1] - 0x37);
}
if(val != xor_chk)
{
return bRtn; // 校驗錯
}
char* pchMsName[] = {"GPRMC", "GPGSA", "GPGSV", "GPGGA"};
int nMsNum = sizeof(pchMsName) / sizeof(pchMsName[0]);
GPS_DATA_TYPE emMsType = ENUM_All_GPS;
for(int nType = 0; nType < nMsNum; nType++)
{
if(memcmp(pchMsName[nType], &m_pchProBuf[1], 5) == 0)
{
emMsType = (GPS_DATA_TYPE)(ENUM_GPSDATA + nType);
break;
}
}
switch(emMsType)
{
case ENUM_GPSDATA: // GPS主要數據
{
int nTmp;
// 時間
p = strchr(m_pchProBuf, ',');
nTmp = atoi(++p);
// 是否定位
p = strchr(p, ',');
if(*(++p) != 'A')
{
// GPS不定位
m_GpsData.byFixType = 0;
}
else
{
m_GpsData.byFixType = 1;
}
m_GpsData.UtcTime.wHour = nTmp / 10000;
m_GpsData.UtcTime.wMinute = nTmp / 100 % 100;
m_GpsData.UtcTime.wSecond = nTmp % 100;
m_GpsData.UtcTime.wMilliseconds = 0;
// 緯度
double dbCoor;
p = strchr(p, ',');
dbCoor = atof(++p);
m_GpsData.dbLat = GetCoor(dbCoor);
p = strchr(p, ',');
if(*(++p) == 'S')
{
m_GpsData.dbLat *= -1;
}
// 經度
p = strchr(p, ',');
dbCoor = atof(++p);
m_GpsData.dbLong = GetCoor(dbCoor);
p = strchr(p, ',');
if(*(++p) == 'W')
{
m_GpsData.dbLong *= -1;
}
// 速度
p = strchr(p, ',');
m_GpsData.dbSpeed = atof(++p);
m_GpsData.dbSpeed = m_GpsData.dbSpeed * Knot2Meter * 1000/3600; //節->米/秒
//方位角
p = strchr(p, ',');
if(*(++p) == ',')
{
m_GpsData.bIsAzimuth = FALSE;
m_GpsData.dbAzimuth = 0;
}
else
{
m_GpsData.bIsAzimuth = TRUE;
m_GpsData.dbAzimuth = atof(p);
// 對-180-179.9而言
if(m_GpsData.dbAzimuth < 0)
{
m_GpsData.dbAzimuth = m_GpsData.dbAzimuth + 360;
}
}
//日期
p = strchr(p,',');
nTmp = atoi(++p);
m_GpsData.UtcTime.wDay = nTmp/10000;
m_GpsData.UtcTime.wMonth = nTmp/100%100;
m_GpsData.UtcTime.wYear = nTmp%100 + 2000;
pMsg->MsgHead.enumMsgType = emMsType;
pMsg->MsgHead.nMsgLen = sizeof(ST_GPS_DATA);
memcpy(pMsg->pMsg, &m_GpsData, sizeof(ST_GPS_DATA));
}
bRtn = TRUE;
break;
case ENUM_DOP:
{
// 定位解算精度的幾何圖形(DOP)
ST_DOP_DATA DopData;
p = strchr(m_pchProBuf, ',');
p = strchr(++p, ',');
p = strchr(++p, ',');
//active sat
int nID;
DopData.nNum = 0;
for(int i = 0; i<12; i++)
{
nID = atoi(++p);
if(nID > 0)
{
DopData.nUsedID[DopData.nNum] = nID;
DopData.nNum++;
}
p = strchr(p, ',');
}
DopData.dbPdop = atof(++p);
p = strchr(p, ',');
DopData.dbHdop = atof(++p);
p = strchr(p, ',');
DopData.dbVdop = atof(++p);
pMsg->MsgHead.enumMsgType = emMsType;
pMsg->MsgHead.nMsgLen = sizeof(ST_DOP_DATA);
memcpy(pMsg->pMsg, &DopData, sizeof(ST_DOP_DATA));
}
bRtn = TRUE;
break;
case ENUM_SAT:
{
int nSatFrmNum, nCurFrmNo, nSatNum;
p = strchr(m_pchProBuf, ',');
nSatFrmNum = atoi(++p);
p = strchr(p, ',');
nCurFrmNo = atoi(++p);
p = strchr(p, ',');
nSatNum = atoi(++p);
if(nCurFrmNo == 1)
{
// 第一幀衛星數據
m_nRevSatNum = 0;
m_nRevFrmNum = 0;
if(nSatNum > 20)
{
return bRtn;
}
m_nAllSatNum = nSatNum;
}
if(nCurFrmNo == ++m_nRevFrmNum)
{
// 收到的幀序號正確
for(int i = 0; i < 4; i++)
{
// 解一幀數據
p = strchr(p, ',');
if((p == NULL) || (*(++p) == ','))
{
break;
}
m_SatData[m_nRevSatNum].nSatID = atoi(p);
p = strchr(p, ',');
m_SatData[m_nRevSatNum].nElevation = atoi(++p);
p = strchr(p, ',');
m_SatData[m_nRevSatNum].nAzimuth = atoi(++p);
p = strchr(p, ',');
if(*(++p) == ',')
{
m_SatData[m_nRevSatNum].nSNR = -1;
}
else
{
m_SatData[m_nRevSatNum].nSNR = atoi(p);
}
m_nRevSatNum++;
}
if((nCurFrmNo >= nSatFrmNum) || (m_nRevSatNum >= m_nAllSatNum))
{
// 衛星已經收齊
pMsg->MsgHead.enumMsgType = emMsType;
pMsg->MsgHead.nMsgLen = sizeof(ST_SAT_DATA) * m_nRevSatNum;
memcpy(pMsg->pMsg, m_SatData, sizeof(ST_SAT_DATA) * m_nRevSatNum);
bRtn = TRUE;
return bRtn;
}
}
else
{
m_nRevSatNum = 0;
m_nRevFrmNum = 0;
m_nAllSatNum = 0;
}
}
break;
case ENUM_ALT:
{
// 高程
p = strchr(m_pchProBuf, ',');
for(int nID = 0 ; nID < 5 ; nID++)
{
p = strchr(++p, ',');
}
//高程
p = strchr(++p, ',');
p = strchr(++p, ',');
p = strchr(++p, ',');
m_GpsData.dbAlt = atof(++p);
}
break;
default:
break;
}
return bRtn;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -