?? gps.cpp
字號:
#include "stdafx.h"
#include "GPSManager.h"
#include "GPS.h"
#include "MainFrm.h"
#include "GPSManagerDoc.h"
#include "GPSManagerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*************************************************************************
*
* 函數名稱:
* GPSDataProc()
*
* 參數:
* LPVOID lpVoid - 參數指針
*
* 返回值:
* UINT - 線程返回代碼
*
* 說明:
* 本函數為線程處理函數,所完成的功能為異步數據接收
*
************************************************************************/
UINT GPSDataProc(LPVOID lpVoid)
{
CGPS* pGPS = (CGPS*)lpVoid;
if (pGPS == NULL)
return 1003;
// 參數復位
pGPS->ParamReset();
// GPS數據處理
pGPS->DoDataProc();
return 1004;
}
/////////////////////////////////////////////////////////////////////////////
// CGPS
CGPS::CGPS()
{
m_pView = NULL;
m_hCom = INVALID_HANDLE_VALUE;
m_hExitListenEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ParamReset();
}
CGPS::~CGPS()
{
m_hCom = INVALID_HANDLE_VALUE;
m_pReadThread = NULL;
CloseHandle(m_hExitListenEvent);
}
BEGIN_MESSAGE_MAP(CGPS, CWnd)
//{{AFX_MSG_MAP(CGPS)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGPS message handlers
/*************************************************************************
*
* 函數名稱:
* DoReadProc()
*
* 參數:
* 無
*
* 返回值:
* 無
*
* 說明:
* 對端口進行異步讀取
*
************************************************************************/
void CGPS::DoDataProc()
{
// 中間變量
DWORD dwErrorMask;
DWORD dwEvtMask = 0;
// 清空緩沖區
memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
// 串口狀態結構對象
COMSTAT comstat;
// 異步結構對象
OVERLAPPED ov, ovEvent;
ov.Internal = 0;
ov.InternalHigh = 0;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ovEvent.Internal = 0;
ovEvent.InternalHigh = 0;
ovEvent.Offset = 0;
ovEvent.OffsetHigh = 0;
ovEvent.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// 設置事件驅動的類型
if (!SetCommMask(m_hCom, EV_RXCHAR | EV_TXEMPTY))
return;
while (true)
{
// 等待接收事件
if (WaitCommEvent(m_hCom, &dwEvtMask, &ovEvent) == FALSE)
{
if (GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ovEvent.hEvent, INFINITE);
}
// 終止偵聽線程
if (m_bExitListen == TRUE)
{
// 線程退出事件置位
SetEvent(m_hExitListenEvent);
return;
}
// 數據到達事件發生后進行接收處理
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{
do
{
// 確定接收緩沖中處于等待的字節數
ClearCommError(m_hCom, &dwErrorMask, &comstat);
if (comstat.cbInQue == 0)
break;
// 異步讀取數據到幀緩沖
if (!ReadFile(m_hCom, m_cFrameBuf + m_dwPoint, comstat.cbInQue, &m_dwActRead, &ov))
{
if (GetLastError() == ERROR_IO_PENDING)
{
// 檢測數據是否接收完畢
while (!GetOverlappedResult(m_hCom, &ov, &m_dwActRead, FALSE))
{
// 數據尚未接收完畢
if (GetLastError() == ERROR_IO_INCOMPLETE)
continue;
}
// 接收數據處理
RecvDataProc();
// 手動復位
ResetEvent(ov.hEvent);
}
}
else
{
// 接收數據處理
RecvDataProc();
// 手動復位
ResetEvent(ov.hEvent);
}
} while (comstat.cbInQue > 0);
}
}
}
/*************************************************************************
*
* 函數名稱:
* OpenPort()
*
* 參數:
* CString sPort - 串口號("COM1","COM2","COM3","COM4")
* DWORD dwBaud - 波特率
*
* 返回值:
* BOOL - 打開成功與否
*
* 說明:
* 異步打開指定串口
*
************************************************************************/
BOOL CGPS::OpenPort(CString sPort, DWORD dwBaud)
{
// 打開串口
m_hCom = CreateFile(sPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (m_hCom == INVALID_HANDLE_VALUE)
return FALSE;
// 得到當前串口配置
DCB dcb;
dcb.DCBlength = sizeof(dcb);
GetCommState(m_hCom, &dcb);
// 基本配置
dcb.BaudRate = dwBaud;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// 不使用DSR--DTR流控方式
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
dcb.fTXContinueOnXoff = FALSE;
// 二進制傳輸
dcb.fBinary = TRUE;
// 配置串口設置
SetCommState(m_hCom, &dcb);
// 超時設置
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 2 * 9600 / dcb.BaudRate;
CommTimeOuts.WriteTotalTimeoutConstant = 25;
SetCommTimeouts(m_hCom, &CommTimeOuts);
// 設置緩沖區大小
SetupComm(m_hCom, 8192, 8192);
// 開啟數據接收線程
m_bExitListen = FALSE;
m_pReadThread = AfxBeginThread(GPSDataProc, this, THREAD_PRIORITY_TIME_CRITICAL);
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* ClosePort()
*
* 參數:
* 無
*
* 返回值:
* BOOL - 端口成功關閉與否
*
* 說明:
* 結束正在進行的數據收發任務后關閉端口
*
************************************************************************/
BOOL CGPS::ClosePort()
{
// 關閉端口釋放資源
if (m_hCom != INVALID_HANDLE_VALUE)
{
// 關閉偵聽線程
m_bExitListen = TRUE;
TerminateRecv();
// 終止端口操作,清空緩沖區
PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
CloseHandle(m_hCom);
// 端口復位
m_hCom = INVALID_HANDLE_VALUE;
}
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* RecvDataProc()
*
* 參數:
* 無
*
* 返回值:
* 無
*
* 說明:
* 對接收數據的處理過程
*
************************************************************************/
void CGPS::RecvDataProc()
{
// 當前緩沖區末尾
m_dwPoint += m_dwActRead;
if (m_dwActRead == 0 || m_dwActRead + m_dwPoint < 30)
return;
if (m_bInfoStart == FALSE)
{
// 尋找GPS幀頭
CString sData = (CString)m_cFrameBuf;
int nHead = sData.Find("$GPRMC", 0);
if ( nHead >= 0)
{
// 清除信息前的垃圾數據
for (DWORD i = nHead; i < m_dwPoint; i++)
m_cFrameBuf[i - nHead] = m_cFrameBuf[i];
m_dwPoint -= nHead;
m_dwActRead = 0;
m_cFrameBuf[m_dwPoint] = 0;
// 標記為找到幀頭
m_bInfoStart = TRUE;
// LF個數清零
m_nLFNum = 0;
}
else
{
// 清除緩沖區全部垃圾數據
m_dwPoint = 0;
m_dwActRead = 0;
memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
}
}
if (m_bInfoStart == TRUE)
{
// 尋找GPS幀頭
CString sData = CString(m_cFrameBuf);
int nEnd = sData.Find('\n', 0);
if (nEnd >= 0)
{
m_nLFNum++;
m_cFrameBuf[nEnd] = '\r';
if (m_nLFNum == 2)
{
// LF個數清零
m_nLFNum = 0;
// 清除信息后的垃圾數據
memset(m_cFrameBuf + nEnd, 0, m_dwPoint - nEnd);
m_dwPoint = nEnd;
m_dwActRead = 0;
m_cFrameBuf[m_dwPoint] = 0;
// GPS幀數據分析
AnalysisGPSFrame();
// 準備接收下一幀GPS數據
m_bInfoStart = FALSE;
// 變量復位
m_dwPoint = 0;
m_dwActRead = 0;
memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
}
}
}
// 清理接收緩沖區
PurgeComm(m_hCom, PURGE_RXCLEAR);
}
/*************************************************************************
*
* 函數名稱:
* AnalysisGPSFrame()
*
* 參數:
* 無
*
* 返回值:
* 無
*
* 說明:
* 對接收到的GPS幀數據進行解幀處理
*
************************************************************************/
void CGPS::AnalysisGPSFrame()
{
int nSectionID = 0;
char Temp[15];
memset(Temp, 0, sizeof(Temp));
int nIndex = 0;
CString sTemp = "";
BOOL bGetValue = false;
for (DWORD i = 0; i < m_dwPoint; i++)
{
Temp[nIndex] = m_cFrameBuf[i];
if (m_cFrameBuf[i] == ',')
{
nSectionID++;
Temp[nIndex] = 0;
bGetValue = true;
}
nIndex++;
if (bGetValue == TRUE)
{
bGetValue = false;
nIndex = 0;
switch(nSectionID)
{
case 2: // 時間
sTemp.Format("%c%c", Temp[0], Temp[1]);
m_lHour = atoi(sTemp);
sTemp.Format("%c%c", Temp[2], Temp[3]);
m_lMinute = atoi(sTemp);
sTemp.Format("%c%c", Temp[4], Temp[5]);
m_lSecond = atoi(sTemp);
break;
case 4: // 緯度
sTemp.Format("%c%c", Temp[0], Temp[1]);
m_dLat = atoi(sTemp);
sTemp.Format("%c%c%c%c%c%c", Temp[2], Temp[3], Temp[4], Temp[5], Temp[6], Temp[7]);
m_dLat = m_dLat + atof(sTemp) / 60.0f;
break;
case 6: // 經度
sTemp = CString(Temp);
sTemp.Format("%c%c%c", Temp[0], Temp[1], Temp[2]);
m_dLon = atoi(sTemp);
sTemp.Format("%c%c%c%c%c%c", Temp[3], Temp[4], Temp[5], Temp[6], Temp[7], Temp[8]);
m_dLon = m_dLon + atof(sTemp) / 60.0f;
break;
case 8: // 速度
m_dVelo = atof(Temp);
break;
case 9: // 方位角
m_dDirection = atof(Temp);
break;
case 10: // 日期
sTemp.Format("%c%c", Temp[0], Temp[1]);
m_lDay = atoi(sTemp);
sTemp.Format("%c%c", Temp[2], Temp[3]);
m_lMonth = atoi(sTemp);
sTemp.Format("%c%c", Temp[4], Temp[5]);
m_lYear = 2000 + atoi(sTemp);
break;
case 21: // 高度
m_dAlt = atof(Temp);
break;
}
}
}
// 修正時區
m_lHour += 8;
if (m_lHour >= 24)
{
m_lHour -= 24;
m_lDay ++;
// 2月閏年處理
if (m_lMonth == 2)
{
if (m_lYear % 4 == 0)
{
if (m_lDay > 29)
{
m_lDay = 1;
m_lMonth = 3;
}
}
else
{
if (m_lDay > 28)
{
m_lDay = 1;
m_lMonth = 3;
}
}
}
// 大月處理
if (m_lMonth == 1 || m_lMonth == 3 || m_lMonth == 5 || m_lMonth == 7 || m_lMonth == 8 || m_lMonth == 10 || m_lMonth == 12)
{
if (m_lDay > 31)
{
m_lDay = 1;
m_lMonth++;
if (m_lMonth > 12)
{
m_lMonth = 1;
m_lYear++;
}
}
}
// 小月處理
if (m_lMonth == 4 || m_lMonth == 6 || m_lMonth == 9 || m_lMonth == 11)
{
if (m_lDay > 30)
{
m_lDay = 1;
m_lMonth++;
if (m_lMonth > 12)
{
m_lMonth = 1;
m_lYear++;
}
}
}
}
// 向顯示視圖發送消息通知其顯示數據
if (m_pView != NULL)
m_pView->PostMessage(WM_SHOWGPSDATA, 0, 0);
}
/*************************************************************************
*
* 函數名稱:
* TerminateRecv()
*
* 參數:
* 無
*
* 返回值:
* 無
*
* 說明:
* 強行終止偵聽線程
*
************************************************************************/
void CGPS::TerminateRecv()
{
// 降低線程優先級到普通
if (m_pReadThread != NULL)
SetThreadPriority(m_pReadThread->m_hThread, THREAD_PRIORITY_NORMAL);
// 強行終止偵聽線程
if (m_pReadThread != NULL)
{
TerminateThread(m_pReadThread->m_hThread, 0);
m_pReadThread = NULL;
}
}
void CGPS::ParamReset()
{
m_pReadThread = NULL;
m_bInfoStart = FALSE;
m_dwPoint = 0;
m_dwActRead = 0;
memset(m_cFrameBuf, 0, sizeof(m_cFrameBuf));
m_bExitListen = FALSE;
m_nLFNum = 0;
m_lYear = 0;
m_lMonth = 0;
m_lDay = 0;
m_lHour = 0;
m_lMinute = 0;
m_lSecond = 0;
m_dLon = 0;
m_dLat = 0;
m_dAlt = 0;
m_dVelo = 0;
m_dDirection = 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -