?? gps.cpp
字號:
/*-----------------------------------------
* Copyright (c) 2008 Eric Wong
* 本版緊供讀者參考,不得用于任何商業行為
*
* 文件名稱: GPS.h
* 文件標識:
* 摘要:用于封裝GPS通訊協議
*
* 當前版本: 1.0
* 作者: 汪兵 Eric Wong
* 完成日期: 2008年1月29日
*
* 取代版本:
* 原作者:
* 完成日期:
----------------------------------------*/
#include "StdAfx.h"
#include "GPS.h"
//構造函數
CGPS::CGPS()
{
m_gpsDev_State = GPS_DEV_NOTOPENED; //GPS狀態
m_hGpsThread = NULL; //GPS檢測線程句柄
ZeroMemory(&m_gpsCurData,sizeof(m_gpsCurData)); //GPS當前數據
ZeroMemory(&m_gpsLastData,sizeof(m_gpsLastData)); //GPS上一次數據
}
//析構函數
CGPS::~CGPS(void)
{
}
/*
*函數介紹:打開GPS設備
*入口參數:pWnd :使用此GPS類的窗體句柄
portNo :串口號
baud :波特率
parity :奇偶校驗
databits :數據位
stopbits :停止位
*出口參數:(無)
*返回值:TRUE:成功打開GPS設備;FALSE:打開GPS設備失敗
*/
BOOL CGPS::Open(CWnd *pWnd , /*擁有者窗口句柄*/
UINT portNo, /*串口號*/
UINT baud, /*波特率*/
UINT parity, /*奇偶校驗*/
UINT databits, /*數據位*/
UINT stopbits /*停止位*/
)
{
m_pWnd = pWnd; //儲存窗口句柄
//創建GPS檢測線程退出事件
m_hThreadQuitEvent = CreateEvent(NULL,false,false,L"EVENT_GPS_THREAD");
//指定串口讀回調函數
m_ceSeries.m_OnSeriesRead = GpsOnSeriesRead;
//打開GPS設備串口
BOOL bResult = m_ceSeries.OpenPort(this,portNo,baud,parity,databits,stopbits);
if (bResult)
{
//設置當前GPS狀態
m_gpsDev_State = GPS_DEV_OPENED;
//發送GPS狀態變化消息
::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_OPENED),1);
//創建GPS狀態檢測線程
m_hGpsThread = CreateThread(NULL,0,GpsCheckThreadFunc,this,0,&m_dwGpsThreadID);
}
else
{
//設置當前GPS狀態
m_gpsDev_State = GPS_DEV_NOTOPENED;
//發送GPS狀態變化消息
::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_NOTOPENED),1);
}
return bResult;
}
/*
*函數介紹:關閉GPS設備
*入口參數:(無)
*出口參數:(無)
*返回值:TRUE:成功關閉GPS設備;FALSE:關閉GPS設備失敗
*/
void CGPS::Close()
{
//先退出GPS檢測線程
if (m_hGpsThread != NULL)
{
//發送線程退出信號
SetEvent(m_hThreadQuitEvent);
//等待線程退出
if (WaitForSingleObject(m_hGpsThread,1000) == WAIT_TIMEOUT)
{
TerminateThread(m_hGpsThread,0);
}
}
m_hGpsThread = NULL;
CloseHandle(m_hThreadQuitEvent);
//將接收數據回掉函數置空
m_ceSeries.m_OnSeriesRead = NULL;
//關閉GPS串口
m_ceSeries.ClosePort();
//設置GPS狀態
m_gpsDev_State = GPS_DEV_NOTOPENED;
//發送GPS狀態變化消息
::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_NOTOPENED),1);
}
/*
*函數介紹:獲取GPS設備狀態
*入口參數:(無)
*出口參數:(無)
*返回值:返回GPS設備狀態
*/
GPSDEV_STATE CGPS::GetGpsState()
{
return m_gpsDev_State;
}
/*
*函數介紹:得到當前GPS數據
*入口參數:(無)
*出口參數:(無)
*返回值:返回GPS設備當前GPS數據
*/
GPSData CGPS::GetCurGpsData()
{
return m_gpsCurData;
}
/*--------------------------------------------------------------------
【函數介紹】: 在pArray緩沖區,查找subString字符串,如存在,返回當前位置,否則返回-1
【入口參數】: pArray:指定接收到的緩沖區隊列
【出口參數】: pArray:指定接收到的緩沖區隊列,解析后需要進行適當修改
【返回 值】: -1表示沒有找到指定的子串,>=0表示發現第1個子串的位置
---------------------------------------------------------------------*/
int CGPS::Pos(LPCSTR subString , CByteArray * pArray,int iPos)
{
//得到子串長度
int subLen = strlen(subString);
//得到緩沖區的長度
int bufLen = pArray->GetUpperBound()+1;
bool aResult = TRUE;
//
for ( int i=iPos;i<bufLen-subLen+1;i++)
{
aResult = TRUE;
for (int j=0;j<subLen;j++)
{
if (pArray->GetAt(i+j) != *(subString + j))
{
aResult = FALSE;
break;
}
int k = 0;
}
if (aResult)
{
return i;
}
}
return -1;
}
/*
*函數介紹:判斷是否存在有效GPS數據
*入口參數:aRecvStr :緩沖數據
*出口參數:aRecvStr : 緩沖數據,outStr:得到的一個完整的GPS數據
*返回值:TRUE : 成功初始化 , FALSE : 初始化失敗
*/
BOOL CGPS::HaveValidGPSData(CByteArray * pArray,CString &outStr)
{
int tmpPos1,tmpPos2;
tmpPos1 = Pos("$GPRMC",pArray,0);
tmpPos2 = Pos("$GPRMC",pArray,tmpPos1+6);
if (tmpPos2 >= 0) //代表已包含兩個$GPRMC
{
if (tmpPos1 >= 0 )
{
BYTE *pBuf = pArray->GetData();
char *sBuf = new char[tmpPos2-tmpPos1+1];
ZeroMemory(sBuf,tmpPos2-tmpPos1+1);
CopyMemory(sBuf,pBuf+tmpPos1,tmpPos2-tmpPos1+1);
outStr = CString(sBuf);
//釋放內存
delete[] sBuf;
sBuf = NULL;
pArray->RemoveAt(0,tmpPos2);
return TRUE;
}
}
return FALSE;
}
/*
*函數介紹:解析GPS數據
*入口參數:aRecvStr :指待解析的GPS緩沖數據
*出口參數:(無)
*返回值:指CGPSData結構體的指針,如果無效即為:NULL;
*/
PGPSData CGPS::AnalyseGpsData(CString &aRecvStr)
{
CString tmpTime;
CString tmpState;
CString tmpDate;
CString tmpLONG;
CString tmpLONGType;
CString tmpLAT;
CString tmpLATType;
CString tmpSpeed;
LPSTR pStrDate = NULL;
LPSTR pStrTime = NULL;
LPSTR pStrLong = NULL;
LPSTR pStrLongType = NULL;
LPSTR pStrLat = NULL;
LPSTR pStrLatType = NULL;
LPSTR pStrSpeed = NULL;
PGPSData pGpsData = NULL;
int tmpPos,tmpPos1;
int len;
tmpPos = aRecvStr.Find(',',0); //第1個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
//得到時間
tmpTime = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
tmpTime = tmpTime.Mid(0,2)+L":"+tmpTime.Mid(2,2)+L":"+tmpTime.Mid(4,2);
len = tmpTime.GetLength();
pStrTime = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpTime.GetBuffer(len),len
,pStrTime,len ,NULL,NULL);
//數據狀態,是否有效
tmpPos = aRecvStr.Find(',',tmpPos+1); //第2個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpState = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
if (tmpState != 'A')//代表數據無效,返回
{
if (m_gpsDev_State != GPS_INVALID_DATA)
{
//設置GPS狀態
m_gpsDev_State = GPS_INVALID_DATA;
//發送GPS狀態變化消息
::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_INVALID_DATA),1);
}
LocalFree(pStrTime);
return NULL;
}
else //代表數據有效
{
if (m_gpsDev_State != GPS_VALID_DATA)
{
//設置GPS狀態
m_gpsDev_State = GPS_VALID_DATA;
//發送GPS狀態變化消息
::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_VALID_DATA),1);
}
}
//得到緯度值
tmpPos = aRecvStr.Find(',',tmpPos+1);//第3個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpLAT = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
len = tmpLAT.GetLength();
pStrLat = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLAT.GetBuffer(len),len
,pStrLat,len ,NULL,NULL);
tmpPos = aRecvStr.Find(',',tmpPos+1);//第4個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpLATType = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
len = tmpLATType.GetLength();
pStrLatType = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLATType.GetBuffer(len),len
,pStrLatType,len ,NULL,NULL);
//得到經度值
tmpPos = aRecvStr.Find(',',tmpPos+1);//第5個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpLONG = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
len = tmpLONG.GetLength();
pStrLong = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLONG.GetBuffer(len),len
,pStrLong,len ,NULL,NULL);
tmpPos = aRecvStr.Find(',',tmpPos+1);//第6個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpLONGType = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
len = tmpLONGType.GetLength();
pStrLongType = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLONGType.GetBuffer(len),len
,pStrLongType,len ,NULL,NULL);
//得到車速
tmpPos = aRecvStr.Find(',',tmpPos+1);////第7個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
tmpSpeed = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
len = tmpSpeed.GetLength();
pStrSpeed = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpSpeed.GetBuffer(len),len
,pStrSpeed,len ,NULL,NULL);
tmpPos = aRecvStr.Find(',',tmpPos+1);////第8個值
//得到日期
tmpPos = aRecvStr.Find(',',tmpPos+1);////第9個值
tmpPos1 = aRecvStr.Find(',',tmpPos+1);
//格式化一下
tmpDate = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
tmpDate = L"20"+tmpDate.Mid(4,2)+L"-"+tmpDate.Mid(2,2)+L"-"+tmpDate.Mid(0,2);
len = tmpDate.GetLength();
pStrDate = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpDate.GetBuffer(len),len
,pStrDate,len ,NULL,NULL);
pGpsData = new GPSData();
ZeroMemory(pGpsData,sizeof(GPSData));
//得到GPS數據指針
CopyMemory(pGpsData->date,pStrDate,10);
CopyMemory(pGpsData->time,pStrTime,8);
CopyMemory(pGpsData->latitude_type,pStrLatType,1);
CopyMemory(pGpsData->latitude,pStrLat,9);
CopyMemory(pGpsData->longitude_type,pStrLongType,1);
CopyMemory(pGpsData->longitude,pStrLong,10);
//先置默認速度0
FillMemory(pGpsData->speed,5,'0');
CopyMemory(pGpsData->speed,pStrSpeed,5);
//釋放內存
LocalFree(pStrTime);
LocalFree(pStrDate);
LocalFree(pStrLatType);
LocalFree(pStrLat);
LocalFree(pStrLongType);
LocalFree(pStrLong);
LocalFree(pStrSpeed);
return pGpsData;
}
//GPS接收數據事件
void CALLBACK CGPS::GpsOnSeriesRead(void * powner,BYTE* buf,DWORD dwBufLen)
{
CGPS * pGps = (CGPS*)powner;
//得到本類指針
CByteArray * pArray = &(pGps->m_aRecvBuf);
//得到緩沖區大小
int iMaxSize = pArray->GetSize();
//得到緩沖區所使用的大小
int iUpperBound = pArray->GetUpperBound();
for (int i=0;i<dwBufLen;i++)
{
pArray->Add(*(buf+i));
}
//將收到的數據發給主程序顯示出來
char* pRecvBuf = new char[dwBufLen+1];
ZeroMemory(pRecvBuf,dwBufLen+1);
CopyMemory(pRecvBuf,buf,dwBufLen);
//發送接收串口原始數據WINDOWS消息通知
//消息處理完畢后,應釋放內存
::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_RECV_BUF,WPARAM(pRecvBuf),dwBufLen+1);
CString strGps;
//檢查是否已經存在有效的GPS數據
if (pGps->HaveValidGPSData(pArray,strGps))
{
PGPSData pGpsData = NULL;
pGpsData = pGps->AnalyseGpsData(strGps);
if (pGpsData != NULL)
{
//將接收到的GPS數據填充到最新當前數據
pGps->m_gpsCurData = (*pGpsData);
//發送接收有效GPS位置信息WINDOWS消息通知
//由消息處理函數釋放內存
::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_RECV_VALID_LONGLAT,WPARAM(pGpsData),0);
}
}
}
//檢測GPS當前數據
DWORD WINAPI CGPS::GpsCheckThreadFunc(LPVOID lparam)
{
//得到當前GPS指針
CGPS *pGps = (CGPS*)lparam;
int iRecCount = 0;
//然后開始做循環檢測,間隔為1秒
while (TRUE)
{
//判斷兩次收到的時間是否相同
if (strcmp(pGps->m_gpsCurData.time,pGps->m_gpsLastData.time) == 0)
{
//計數加1
iRecCount++;
}
else
{
//將當前的GPS數據賦給歷史值
pGps->m_gpsLastData = pGps->m_gpsCurData;
iRecCount = 0 ;
}
//代表連續三次沒有收到數據
if (iRecCount == 3)
{
if (pGps->m_gpsDev_State != GPS_NODATA)
{
//將GPS狀態置為“無數據”
pGps->m_gpsDev_State = GPS_NODATA;
//發送GPS狀態改變消息
::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_NODATA),1);
}
}
//延時1秒
for (int i =0; i<10;i++)
{
//線程退出
if (WaitForSingleObject(pGps->m_hThreadQuitEvent,100) == WAIT_OBJECT_0)
{
goto finish;
}
}
}
finish:
TRACE(L"GPS 檢測線程退出\n");
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -