📄 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
#if defined(UNICODE) || defined (_UNICODE)
#define WinMain wWinMain
#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))
while(!WaitForSingleObject(ov.hEvent,INFINITE))
{
// 数据尚未接收完毕
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(_T("$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 = _T("");
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(_T("%c%c"), Temp[0], Temp[1]);
m_lHour = _wtoi(sTemp);
sTemp.Format(_T("%c%c"), Temp[2], Temp[3]);
m_lMinute = _wtoi(sTemp);
sTemp.Format(_T("%c%c"), Temp[4], Temp[5]);
m_lSecond = _wtoi(sTemp);
break;
case 4: // 纬度
sTemp.Format(_T("%c%c"), Temp[0], Temp[1]);
m_dLat = _wtoi(sTemp);
sTemp.Format(_T("%c%c%c%c%c%c"), Temp[2], Temp[3], Temp[4], Temp[5], Temp[6], Temp[7]);
m_dLat = m_dLat + wcstod(sTemp,NULL) / 60.0f;
break;
case 6: // 经度
sTemp = CString(Temp);
sTemp.Format(_T("%c%c%c"), Temp[0], Temp[1], Temp[2]);
m_dLon = _wtoi(sTemp);
sTemp.Format(_T("%c%c%c%c%c%c"), Temp[3], Temp[4], Temp[5], Temp[6], Temp[7], Temp[8]);
m_dLon = m_dLon + wcstod(sTemp,NULL) / 60.0f;
break;
case 8: // 速度
m_dVelo = atof(Temp);
break;
case 9: // 方位角
m_dDirection = atof(Temp);
break;
case 10: // 日期
sTemp.Format(_T("%c%c"), Temp[0], Temp[1]);
m_lDay = _wtoi(sTemp);
sTemp.Format(_T("%c%c"), Temp[2], Temp[3]);
m_lMonth = _wtoi(sTemp);
sTemp.Format(_T("%c%c"), Temp[4], Temp[5]);
m_lYear = 2000 + _wtoi(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 + -