目前GPS(全球定位系統)定位應用市場日趨成熟,正在進入應用的高速發展時期。看到論壇里不斷有人提問關于GPS的問題。現將個人對GPS的了解寫出來跟大家一塊探討。
1、 GPS應用簡介
近年來GPS系統,已經在大地測繪、海上漁用、車輛定位監控、建筑、農業等各個領域得到廣泛應用。從九十年代我國引進GPS定位技術開始,經過十多年的市場培育,GPS定位應用進入了發展的最好時機,未來十年基于GPS的應用將會改變我們的生活和工作方式。
目前市場上的大部分GPS接受模塊都是通過RS232串口與MCU進行數據傳輸的。這些數據包括經度、緯度、海拔高度、時間、衛星使用情況等基本信息。開發人員再依據這些基本數據,進行數據處理來完成整套的定位系統軟件。
2、 數據格式
在進行數據接受編程之前,先介紹一下該模塊的數據格式。它支持NMEA-0183輸出格式。信息如下:
GGA位置測定系統定位資料(Global Positioning System Fix Data)
GSV 導航衛星資料(GNSS Satellites in View)
RMC導航衛星特定精簡資料(Recommended Minimum Specific GNSS Data)
VTG 方向及速度等相關資料(Course Over Ground and Ground Speed)
由于文章篇幅問題,筆者在這里只以接收GGA數據為例,格式如下:
$GPGGA,hhmmss,dddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,M,x.x,xxxx*CS
例:$GPGGA,033744,2446.5241,N,12100.1536,E,1,10,0.8,133.4,M,,,,*1F
說明見表:

上面例子中,我們可讀出位置信息:北緯24度46.5241分,西經121度00.1536分
格林威治時間:3點37分44秒
3 部分程序代碼(c++)- //初始化串口
- //入口:strComm(串口名)
- //返回:TRUE(成功);FALSE(失敗)
- BOOL CGPSDlg::InitComm(CString strComm)
- {
- int i;
- DCB dcb;
- COMMTIMEOUTS TimeOuts;
- for (i=0; i<3; i++) //串口最多初始化3次
- {
- m_hComm = CreateFile(strComm, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if (m_hComm != INVALID_HANDLE_VALUE)
- break;
- }
- if (i == 3) //串口初始化失敗
- {
- AfxMessageBox("串口初始化失敗...");
- return FALSE;
- }
-
- SetupComm(m_hComm, MAXLENGTH, MAXLENGTH); //設置發送接收緩沖區大小
-
- TimeOuts.ReadIntervalTimeout = 0; //設定5個超時參數
- TimeOuts.ReadTotalTimeoutMultiplier = 0;
- TimeOuts.ReadTotalTimeoutConstant = 500;
- TimeOuts.WriteTotalTimeoutMultiplier = 0;
- TimeOuts.WriteTotalTimeoutConstant = 500;
- SetCommTimeouts(m_hComm, &TimeOuts); //設置超時參數
-
- GetCommState(m_hComm, &dcb); //獲得通信狀態
- dcb.fAbortOnError = FALSE; //有錯誤不停止
- dcb.BaudRate = CBR_4800; //波特率4800
- dcb.ByteSize = 8; //8位
- dcb.Parity = NOPARITY; //奇校驗
- dcb.StopBits = ONESTOPBIT; //1位停止位
- SetCommState(m_hComm, &dcb); //設置通信狀態
- PurgeComm(m_hComm, PURGE_TXCLEAR|PURGE_RXCLEAR); //清空發送和接收緩沖區
-
- return TRUE;
- }
- //獲得GPS參數
- //注意:從GPS接收到的字符串已經在m_strRecv中,由于是定時接收,所以在這個字符串的頭和尾都可能存在
- // 不完整的NMEA輸出字符串,在處理時要特別注意
- //返回:TRUE(格式正確);FALSE(格式錯誤)
- BOOL CGPSDlg::GetGPSParam()
- {
- int i,j;
- CString str,strNEMA;
-
- //先判斷是否接收到數據
- if (m_strRecv.IsEmpty())
- return FALSE;
- //若字符串不是以'
- [/color][i][/i]
- 開頭的,必須刪掉這部分不完整的
- if (m_strRecv[0] != '
- [/color][i][/i]
- )
- {
- i = m_strRecv.Find('\n', 0);
- if (i == -1)
- return FALSE; //尾部未接收完整,必須等接收完后才能刪除
- m_strRecv.Delete(0, i+1); //尾部已接收完整(尾部為\r\n結束),刪除不完整的部分
- }
-
- //截取完整的NMEA-0183輸出語句(m_strRecv中可能有多條語句,每條間以\r\n分隔)
- for (;;)
- {
- i = m_strRecv.Find('\n', 0);
- if (i == -1)
- break; //所有的完整輸出語句都已經處理完畢,退出循環
-
- //截取完整的NMEA-0183輸出語句
- strNEMA = m_strRecv.Left(i+1);
- m_strRecv.Delete(0, i+1);
- //下面對各種輸出語句進行分別處理
- if (strNEMA.Find("$GPRMC",0) == 0)
- {
- //該輸出語句中的各項以','分隔
- for (i=j=0; strNEMA[i]!='\r'; i++) //j為逗號的計數器
- {
- if (strNEMA[i] == ',')
- {
- j++;
- str = "";
- for (i++; strNEMA[i]!=','&&strNEMA[i]!='\r'; i++)
- str += strNEMA[i]; //str為某項的值
- i--;
-
- //對各項數據分別處理
- switch (j)
- {
- case 1: //時間(UTC)
- m_strTime = str.Left(6);
- m_strTime.Insert(2, ':');
- m_strTime.Insert(5, ':');
- break;
- case 2: //狀態(A-數據有效;V-數據無效,還未定位)
- if (str == "A")
- m_strStatus = "有效數據";
- else if(str == "V")
- m_strStatus = "正在定位...";
- else
- m_strStatus = "非法數據格式";
- break;
- case 3: //緯度(ddmm.mmmm)
- str.Insert(2, "度");
- str += "分";
- m_strLatitude = str;
- break;
- case 4: //緯度指示(N-北緯;S-南緯)
- if (str == "N")
- m_strLatitude.Insert(0, "北緯");
- else
- m_strLatitude.Insert(0, "南緯");
- break;
- case 5: //經度(dddmm.mmmm)
- str.Insert(3, "度");
- str += "分";
- m_strLongitude = str;
- break;
- case 6: //經度指示(E-東經;W-西經)
- if (str == "E")
- m_strLongitude.Insert(0, "東經");
- else
- m_strLongitude.Insert(0, "西經");
- break;
- case 7: //速度(單位:節)
- m_strSpeed = str;
- break;
- case 8: //航向(單位:度)
- m_strCourse = str;
- break;
- case 9: //日期(UTC)
- m_strDate = "";
- m_strDate += "20";
- m_strDate += str[4];
- m_strDate += str[5];
- m_strDate += "-";
- m_strDate += str[2];
- m_strDate += str[3];
- m_strDate += "-";
- m_strDate += str[0];
- m_strDate += str[1];
- break;
- default:
- break;
- }
- }
- }
- }
- else if (strNEMA.Find("$GPGGA",0) == 0)
- {
-
- }
- else if (strNEMA.Find("$GPGSA",0) == 0)
- {
-
- }
- else if (strNEMA.Find("$GPGSV",0) == 0)
- {
-
- }
- else if (strNEMA.Find("$GPGLL",0) == 0)
- {
-
- }
- else if (strNEMA.Find("$GPVTG",0) == 0)
- {
-
- }
- else
- return FALSE; //格式錯誤
- }
- return TRUE;
- }
復制代碼
|