📄 gpsutil.cpp
字号:
wsprintf(szBufW, _T("%d度%d分%f秒(%c) %f"), n1,n2,d3,dire_longitude, longX);
::SendMessage(subhWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)(szBufW));
subhWnd = GetDlgItem(hWnd, IDC_VELOCITY);
wsprintf(szBufW, _T("%f"), velocity);
::SendMessage(subhWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)(szBufW));
subhWnd = GetDlgItem(hWnd, IDC_DIRECTION);
wsprintf(szBufW, _T("%f"), direction);
::SendMessage(subhWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)(szBufW));
//刷新星的位置图
RECT rt;
POINT pt;
int r;
subhWnd = GetDlgItem(hWnd, IDC_MAP);
GetWindowRect(subhWnd, &rt);
pt.x = (rt.left + rt.right)/2;
pt.y = (rt.top + rt.bottom)/2;
r = abs(rt.right - rt.left);
ScreenToClient(hWnd, &pt);
rt.left = pt.x - r/2 - 10;
rt.top = pt.y - r/2 - 10;
rt.right = pt.x + r/2 + 10;
rt.bottom = pt.y + r/2 + 10;
InvalidateRect(hWnd, &rt, false);
return ;
}
//启动GPS
bool GPSStart(HWND hWnd)
{
if( bGPSStart ) return( true );
wchar_t szPort[15];
DCB dcb;
pIDComDev = INVALID_HANDLE_VALUE;
wsprintf( szPort, _T("COM%d:"), nPort );
pIDComDev = CreateFile( szPort,//指向端口名的Pointer
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式(共享模式)
NULL,
OPEN_EXISTING,//打开而不是创建(创建方式)
0, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,//重叠方式(文件属性和标志)
NULL
);
if( pIDComDev == INVALID_HANDLE_VALUE)
{
DWORD dwError=GetLastError();
::MessageBox(0,_T("打开端口出错!请确定端口设备的使用情况后关闭重试."),_T("错误!"),MB_OK );
return false;
}
SetCommMask(pIDComDev, EV_RXCHAR);
PurgeComm(pIDComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts (szPort, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
if(!SetCommTimeouts( pIDComDev, &CommTimeOuts ))
{
//could not creatthe read thread;
::MessageBox (NULL,_T("不能设置延时参数"),_T("错误!"),MB_OK);
CloseHandle( pIDComDev );
return false;
}
/////////////端口设置
dcb.DCBlength = sizeof( DCB );
//获得端口设置信息
GetCommState( pIDComDev, &dcb );
//端口波特率
dcb.BaudRate = arrayBaud[nBaud];
dcb.ByteSize = nByteSize; // Number of bits/byte, 4-8
dcb.Parity = nParity; //NOPARITY; //old 2 // 0-4=no,odd,even,mark,space
dcb.StopBits = nStopBits;// ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
dcb.fOutxDsrFlow = false; // No DSR output flow control
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutxCtsFlow = false; // No CTS output flow control
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fOutX = false; // No XON/XOFF out flow control
dcb.fInX = false; //old true // No XON/XOFF in flow control
dcb.fBinary = true; // Binary mode; no EOF check
dcb.fParity = true; // Enable parity checking
// DTR flow control type
if( !SetCommState( pIDComDev, &dcb )||
!SetupComm( pIDComDev, 1024, 1024 ))
{
DWORD dwError = GetLastError();
CloseHandle( pIDComDev );
::MessageBox(0,_T("初始化端口不正确!"),_T("错误!"),MB_OK );
return( false );
}
// 创建一个读端口线程.
pReadThread = CreateThread (NULL, 0,
(LPTHREAD_START_ROUTINE)PortReadThread,
hWnd, 0, &dwThreadID);
if(pReadThread == NULL)
{
::MessageBox (NULL, _T("不能创建一个读端口线程"), _T("错误!"), MB_OK);
CloseHandle( pIDComDev );
return (false);
}
return( true );
}
//停止GPS
bool GPSEnd()
{
if( !bGPSStart )
return (true);
if(pReadThread != NULL)
{
CloseHandle(pReadThread);
pReadThread = NULL;
}
// Close the communication port.
SetCommMask(pIDComDev,0);
EscapeCommFunction(pIDComDev,CLRDTR);
PurgeComm(pIDComDev,PURGE_TXABORT|PURGE_RXABORT| PURGE_TXCLEAR|PURGE_RXCLEAR);
if (!CloseHandle (pIDComDev))
{
::MessageBox (NULL,_T("关闭端口错误"),_T("错误!"),MB_OK);
return (false);
}
return( true );
}
//读数线程
LRESULT CALLBACK PortReadThread(HWND hWnd)
{
//发启动信号"!"
/* DWORD dwNumByteWritten;
char star[256];
sprintf(star,("ASTRAL\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 1失败!!"),_T("RIGHT"),MB_OK);
return false;
}
sprintf(star,("$PRWIILOG,RMC,A,T,2,0\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 2失败!!"),_T("RIGHT"),MB_OK);
return false;
}
sprintf(star,("$PRWIILOG,GSA,A,T,5,0\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 3失败!!"),_T("RIGHT"),MB_OK);
return false;
}
sprintf(star,("$PRWIILOG,GSV,A,T,6,0\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 4失败!!"),_T("RIGHT"),MB_OK);
return false;
}
sprintf(star,("$PRWIILOG,GGA,A,T,4,0\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 5失败!!"),_T("RIGHT"),MB_OK);
return false;
}
sprintf(star,("$PRWIILOG,ZCH,V,,,\r\n"));
if(!WriteFile(pIDComDev, &star, strlen(star), &dwNumByteWritten, NULL))
{
::MessageBox (NULL,_T("发送启动命令 - 6失败!!"),_T("RIGHT"),MB_OK);
return false;
}
*/
// 指定监视的端口事件
DWORD dwCommModemStatus, dwBytesTransferred;
char ReadBuff[MAX_ONEREAD];
memset(ReadBuff, 0, MAX_ONEREAD);
SetCommMask (pIDComDev, EV_RXCHAR );
while (pIDComDev!= INVALID_HANDLE_VALUE)
{
// 等待端口事件
WaitCommEvent (pIDComDev, &dwCommModemStatus, 0);
// 重新指定监视的端口事件
SetCommMask (pIDComDev, EV_RXCHAR );
if (dwCommModemStatus & EV_RXCHAR)
{
// Read the data from the serial port.
ReadFile (pIDComDev, ReadBuff, MAX_ONEREAD, &dwBytesTransferred, 0);
// Display the data read.
if (dwBytesTransferred >= 1)
{
// 处理收到的字符
ReadBuff[dwBytesTransferred] = '\0';
GPSReadInfo(ReadBuff);
/*RECT rt;
GetClientRect(hWnd, &rt);
InvalidateRect(hWnd, &rt, true);*/
}
}
}
return true;
}
//读入一段信息后,处理
void GPSReadInfo(char *sMessage)
{
if(sMessage != NULL)
{
if(strlen(sReadBuff) + strlen(sMessage) >= 5*MAX_LENGTH-10)
{
strcpy(sReadBuff, "");
}
strcat(sReadBuff, sMessage);
ParseReadBuffer(sReadBuff);
}
}
//解析读入的缓冲
void ParseReadBuffer(char *sBuff)
{
if(strlen(sBuff) < 1)return;
int nlen;
int nstart, nend;
int i;
nlen = strlen(sBuff);
nstart = 0;
nend = 0;
i = 1;
//从第一个开始,这样保证当开始有'$'符号时,前面可以解析成一个字符串
while(*(sBuff+i) != '\0')
{
if(*(sBuff+i) == '$')
{
//获取上一个并解析
nend = i;
if(nend-nstart > MAX_LENGTH)
{
strcpy(sBuff, "");
return ;
}
else
{
memcpy(sSentence, sBuff+nstart, nend-nstart);
sSentence[nend-nstart] = '\0';
ParseSentence(sSentence);
}
nstart = i;
}
i++;
}
if(nstart != 0)
{
memmove(sBuff, sBuff+nstart, nlen - nstart);
sBuff[nlen - nstart] = 0;
}
return ;
}
//根据开始字符判断类型
int SortSentence(char *sBuff)
{
if(strlen(sBuff) < 1)return START_UNKNOW;
if(sBuff[0] != '$' ) return START_UNKNOW;
if(strstr(sBuff, "$GPGGA") != NULL)
{
return START_GPGGA;
}
else if(strstr(sBuff, "$GPGSA") != NULL)
{
return START_GPGSA;
}
else if(strstr(sBuff, "$GPGSV") != NULL)
{
return START_GPGSV;
}
else if(strstr(sBuff, "$GPRMC") != NULL)
{
return START_GPRMC;
}
return START_UNKNOW;
}
//根据类型解析出值
//如果解析正确,放回true, 否则false
BOOL ParseSentence(char *sBuff)
{
BOOL bRtn;
//首先判断格式的类型
int type = SortSentence(sBuff);
//根据不同类型,来解析值
switch(type)
{
case START_GPGGA:
bRtn = ParseGPGGA(sBuff);
if(bRtn)
{
// 位置改变
if (GPSMapWnd != NULL)
{
SendMessage(GPSMapWnd, GPSPOS_CHANGED,0,0);
}
}
break;
case START_GPGSA:
bRtn = ParseGPGSA(sBuff);
if(bRtn)
{
// 活动卫星改变
}
break;
case START_GPGSV:
bRtn = ParseGPGSV(sBuff);
if(bRtn)
{
// 可视卫星改变
}
break;
case START_GPRMC:
bRtn = ParseGPRMC(sBuff);
if(bRtn)
{
// 时间、速度、方向改变,
if (GPSMapWnd != NULL)
{
SendMessage(GPSMapWnd, GPSSPEED_CHANGED,0,0);
}
}
break;
case START_UNKNOW :
bRtn = false;
default:
bRtn = false;
break;
}
if(bRtn)
{
if(GPSStatushWnd != NULL)
{
SendMessage(GPSStatushWnd, GPSINFO_CHANGED,0,0);
}
}
return bRtn;
}
//解析GPGGA
BOOL ParseGPGGA(char *sBuff)
{
if(strlen(sBuff) < 1)return false;
int nstart, nend;
int i;
int index;
int num;
nstart = -1;
nend = 0;
i = 1;
index = 0;
//从第一个开始,这样保证但开始有'$'符号时,前面可以解析成一个字符串
while(*(sBuff+i) != '\0')
{
if(*(sBuff+i) == ',')
{
nend = i;
if(nend == nstart)
{
strcpy(sTempBuff, "");
}
else
{
nstart++; //保证除掉','
memcpy(sTempBuff, sBuff+nstart, nend-nstart);
sTempBuff[nend-nstart] = '\0';
}
nstart = i;
//获取上一个解析
switch(index){
case 1:
//时间
num =atoi(sTempBuff);
nhour = num/10000;
nminute = (num-nhour*10000)/100;
nsecond = num-nhour*10000-nminute*100;
break;
case 2:
//纬度
latitude = atof(sTempBuff);
break;
case 3:
//为北纬或南纬
dire_latitude = sTempBuff[0];
break;
case 4:
//经度
longitude = atof(sTempBuff);
break;
case 5:
//东经或西经
dire_longitude = sTempBuff[0];
break;
case 6:
//是否已定位
available = atoi(sTempBuff);
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -