📄 gps_receive c++.c
字号:
/*GPS的每帧数据以'$'开始,以'\r\n'结尾。中间以','分隔每字段。
需要处理的帧数据有:分别以"$GPRMC", "$GPGGA","$GPGSV"开始的数据帧。
只需将经度、纬度、卫星个数、速度等字段取出保存即可。
1、GPRMC
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,*hh<CR><LF>
<1>定位时UTC时间hhmmss 格式
<2>状态A=定位V=导航
<3>纬度dd mm mmmm 格式(非0)
<4>纬度方向 N或S
<5>经度ddd mm mmmm 格式(非0)
<6>经度方向E或W
<7>速率
<8>方位敬爱(二维方向指向,相当于二维罗盘)
<9>当前UTC日期ddmmyy 格式
<10>太阳方位
<11>太阳方向
2、GPGGA
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M, <11>,<12>*hh<CR><LF>
<1>UTC时间,hh mm ss格式(定位它的)
<2>纬度dd mm mmmm 格式(非0)
<3>纬度方向 N或S
<4>经度ddd mm mmmm 格式(非0)
<5>经度方向E或W
<6>GPS状态批示0-未定位 1-无差分定位信息 2-带差分定位信息
<7>使用卫星号(00~08)
<8>精度百分比
<9>海平面高度
<10>*大地随球面相对海平面的高度
<11>差分GPS信息
<12>差分站ID号 0000-123
3、GPGSV
$GPGSV,<1>,<2>,<3>,<4>,<5>,<6>,<7><4>,<5>,<6>,<7>*hh<CR><LF>
<1>GSV语句的总数目
<2>当前GSV语句数目
<3>显示卫星的总数目00~12
<4>卫星的PRV号星号
<5>卫星仰角
<6>卫星旋角
<7>信操比 */
//4、参考代码
void CThreadGPS::DealWithRecv(std::deque<unsigned char>& _dRecvBuf)
{
assert(GetCurrentThreadId() == m_dwThreadId);
std::deque<unsigned char>::iterator iter, iterbegin, iterend;
iterbegin = _dRecvBuf.begin();
iterend = _dRecvBuf.begin();
for (iter = _dRecvBuf.begin(); iter != _dRecvBuf.end(); ++iter)
{
if (*iter == '$') // 开始符
{
iterbegin = iter;
}
else if ((iter - iterbegin) >= 2 && *(iter-1) == '\r' && *iter == '\n')// 结束符
{
iterend = iter + 1;
if (iterend > iterbegin)
{
m_strFrame.erase();
std::deque<unsigned char>::iterator i;
for (i = iterbegin; i != iterend-2; ++i)
{
m_strFrame += *i;
}
DealWithFrame(m_strFrame);
}
}
}
_dRecvBuf.erase(_dRecvBuf.begin(), iterend);
}
void CThreadGPS::DealWithFrame(std::string& _strFrame)
{
assert(GetCurrentThreadId() == m_dwThreadId);
std::string strTemp;
//*********************************
std::string strSign; //hdw
//*********************************
//////////////////////////////////////////////////////////////////////////
// 记录前一个点,用来判断是否移动了
m_ptGPSpre.dLon = m_stGPSDataTemp.dLon;
m_ptGPSpre.dLat = m_stGPSDataTemp.dLat;
if (_strFrame.find("$GPRMC") == 0)
{
//'****************************************************************
//' 最简特性 (RMC)
//' $GPRMC、<1>、<2>、<3>、<4>、<5>、<6>、<7>、<8>、<9>、<10>、<11>、*hh<CR><LF>
//' <1>定位时UTC时间hhmmss 格式
//' <2>状态A=定位V=导航
//' <3>纬度dd mm mmmm 格式(非0)
//' <4>纬度方向 N或S
//' <5>经度ddd mm mmmm 格式(非0)
//' <6>经度方向E或W
//' <7>速率
//' <8>方位敬爱(二维方向指向,相当于二维罗盘)
//' <9>当前UTC日期ddmmyy 格式
//' <10>太阳方位
//' <11>太阳方向
//'****************************************************************
//读取经度
if (ExtractSubString(strTemp,_strFrame.c_str(), 5, ','))
{
int iLon = atoi(strTemp.c_str()) / 100;
double dLon = (atof(strTemp.c_str()) - iLon * 100) / 60.0+iLon;
if (dLon != 0)
{
//hdw**************************************
ExtractSubString(strSign,_strFrame.c_str(), 6, ',');
if(strSign.find("W")==0)
m_stGPSDataTemp.dLon = -1.0*dLon;//填充CGPS结构
else
m_stGPSDataTemp.dLon = dLon;//填充CGPS结构
}
}
//读取纬度
if (ExtractSubString(strTemp,_strFrame.c_str(), 3, ','))
{
int iLat = atoi(strTemp.c_str()) / 100;
double dLat = (atof(strTemp.c_str()) - iLat * 100) / 60.0+iLat;
if (dLat != 0)
{
//hdw**************************************
ExtractSubString(strSign,_strFrame.c_str(), 4, ',');
if(strSign.find("S")==0)
m_stGPSDataTemp.dLat = -1*dLat;//填充CGPS结构
else
m_stGPSDataTemp.dLat = dLat;//填充CGPS结构
}
}
//读取速率
if (ExtractSubString(strTemp,_strFrame.c_str(), 7, ','))
{
m_stGPSDataTemp.fSpeed = atof(strTemp.c_str())*1.852;
}
}
else if (_strFrame.find("$GPGGA") == 0)
{
//'**************************************************************************
//'GPGGA,083859,2214.495,N,11334.389,E,1,04,2.1,140.5,M,-3.1,M,,*5E
//'$GPGGA、<1>、<2>、<3>、<4>、<5>、<6>、<7>、<8>、<9>、M, <11>、<12>*hh<CR><LF>
//' <1>UTC时间,hh mm ss格式(定位它的)
//' <2>纬度dd mm mmmm 格式(非0)
//' <3>纬度方向 N或S
//' <4>经度ddd mm mmmm 格式(非0)
//' <5>经度方向E或W
//' <6>GPS状态批示0-未定位 1-无差分定位信息 2-带差分定位信息
//' <7>使用卫星号(00~08)
//' <8>精度百分比
//' <9>海平面高度
//' <10>*大地随球面相对海平面的高度
//' <11>差分GPS信息
//' <12>差分站ID号 0000-123
//'**************************************************************************
//读取经度
if (ExtractSubString(strTemp,_strFrame.c_str(), 4, ','))
{
int iLon = atoi(strTemp.c_str()) / 100; // "STDLIB.H" //atoi() 把字符串转成整数
double dLon = (atof(strTemp.c_str()) - iLon * 100) / 60.0+iLon; //atof() 把字符串换成双精度数
if (dLon != 0)
{
//hdw**************************************
ExtractSubString(strSign,_strFrame.c_str(), 6, ',');
if(strSign.find("W")==0)
m_stGPSDataTemp.dLon = -1.0*dLon;//填充CGPS结构
else
m_stGPSDataTemp.dLon = dLon;//填充CGPS结构
}
}
//读取纬度
if (ExtractSubString(strTemp,_strFrame.c_str(), 2, ','))
{
int iLat = atoi(strTemp.c_str()) / 100;
double dLat = (atof(strTemp.c_str()) - iLat * 100) / 60.0+iLat;
if (dLat != 0)
{
//hdw**************************************
ExtractSubString(strSign,_strFrame.c_str(), 4, ',');
if(strSign.find("S")==0)
m_stGPSDataTemp.dLat = -1*dLat;//填充CGPS结构
else
m_stGPSDataTemp.dLat = dLat;//填充CGPS结构
}
}
//读取海平面高度
if (ExtractSubString(strTemp,_strFrame.c_str(),9,','))
{
m_stGPSDataTemp.fHeight = atof(strTemp.c_str());
}
}
else if (_strFrame.find("$GPGSV") == 0)
{
//'******************************************************************
//' 当前GPS卫星状态 (GSV)
//' $GPGSV、<1>、<2>、<3>、<4>、<5>、<6>、<7><4>、<5>、<6>、<7>*hh<CR><LF>
//' <1>GSV语句的总数目
//' <2>当前GSV语句数目
//' <3>显示卫星的总数目00~12
//' <4>卫星的PRV号星号
//' <5>卫星 仰角
//' <6>卫星 旋角
//' <7>信操比
//'******************************************************************
//读取卫星的总数目00~12
if (ExtractSubString(strTemp,_strFrame.c_str(),3,','))
{
m_stGPSDataTemp.chState = char(atoi(strTemp.c_str()));
}
}
//////////////////////////////////////////////////////////////////////////
// 判断是否移动了
if((m_ptGPSpre.dLat-m_stGPSDataTemp.dLat>0.0000001 || m_ptGPSpre.dLat-m_stGPSDataTemp.dLat<-0.0000001)
||(m_ptGPSpre.dLon-m_stGPSDataTemp.dLon>0.0000001 || m_ptGPSpre.dLon-m_stGPSDataTemp.dLon<-0.0000001))
{
// 改变了
::EnterCriticalSection(&m_syncGPSData);
m_stGPSData = m_stGPSDataTemp;
::LeaveCriticalSection(&m_syncGPSData);
// 通知主模块去读取
assert(m_hWndRecv);
assert(m_uMsgGPSPoint);
if (!::PostMessage(m_hWndRecv, m_uMsgGPSPoint, 0, 0))
{
assert(false);
}
// 通知接收线程保存成文件
assert(m_dwRecvThreadId);
assert(m_uMsgRecvThreadSaveGPS);
if (!::PostThreadMessage(m_dwRecvThreadId, m_uMsgRecvThreadSaveGPS, 0, 0))
{
assert(false);
}
}
}
// 取得由分隔符分隔的子字符串
bool CThreadGPS::ExtractSubString(std::string& rString, const char* lpszFullString,int iSubString, char chSep)
{
if (lpszFullString == NULL)
return false;
while (iSubString--)
{
lpszFullString = strchr(lpszFullString, chSep);
if (lpszFullString == NULL)
{
return false;
}
lpszFullString++; // point past the separator
}
char* lpchEnd = strchr(lpszFullString, chSep);
int nLen = (lpchEnd == NULL) ?
strlen(lpszFullString) : (int)(lpchEnd - lpszFullString);
assert(nLen >= 0);
rString.assign(lpszFullString, nLen);
return true;
}
// 接收数据
CSerialToThread m_SerialToThread; // 串口
enum {m_RecvBufLen = 1024}; // 接收串口缓冲区的大小
unsigned char m_byRecvBuf[m_RecvBufLen]; // 接收串口缓冲区
std:: deque<unsigned char> m_dRecvBuf; // 接收串口缓冲区队列
std:: string m_strFrame; // 从上队列分解出来的一帧数据。GPS数据是字符串
//////////////////////////////////////////////////////////////////////////
//
HWND m_hWndRecv; //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -