基于Qt的车载GPS监控系统(6)GPS信息处理
GPS模块(NEO-6M UBLOX)
GPS模块通过串口同tiny6410开发板连接,向开发板传递GPS定位信息(NMEA-0183协议)。
NMEA-0183 协议简介
NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式。目前业已成了GPS导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议。
NMEA-0183协议采用ASCII码来传递GPS定位信息,我们称之为帧。
$GPRMC(推荐定位信息,Recommended Minimum Specific GPS/Transit Data)
GPRMC语句的基本格式如下: GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)
例如:
$GPRMC,033308.00,A,3022.29739,N,11454.04296,E,0.044,,111116,,,A*75(1) UTC时间,hhmmss(时分秒)
(2) 定位状态,A=有效定位,V=无效定位
(3) 纬度ddmm.mmmmm(度分)
(4) 纬度半球N(北半球)或S(南半球)
(5) 经度dddmm.mmmmm(度分)
(6) 经度半球E(东经)或W(西经)
(7) 地面速率(000.0~999.9节)
(8) 地面航向(000.0~359.9度,以真北方为参考基准)
(9) UTC日期,ddmmyy(日月年)
(10)磁偏角(000.0~180.0度,前导位数不足则补0)
(11) 磁偏角方向,E(东)或W(西)
(12) 模式指示(A=自主定位,D=差分,E=估算,N=数据无效)
串口接收GPS完整数据
$GPRMC,033308.00,A,3022.29739,N,11454.04296,E,0.044,,111116,,,A*75
$GPVTG,,T,,M,0.044,N,0.081,K,A*2A
$GPGGA,033308.00,3022.29739,N,11454.04296,E,1,08,0.96,115.5,M,-9.0,M,,*4D
$GPGSA,A,3,05,02,06,19,12,09,25,29,,,,,1.75,0.96,1.46*02
$GPGSV,4,1,14,02,63,013,38,05,64,281,33,06,43,074,31,07,01,084,*71
$GPGSV,4,2,14,09,18,043,27,12,24,249,32,13,24,179,,15,02,203,*7F
$GPGSV,4,3,14,17,13,148,,19,30,147,20,20,14,249,18,25,16,288,27*7F
$GPGSV,4,4,14,29,12,321,25,30,01,113,*72
$GPGLL,3022.29739,N,11454.04296,E,033308.00,A,A*6B
GPS信息解析函数
//GPS信息
struct st_gps_info{
double latitude; //经度
double longitude; //纬度
float speed; //速度
float direction; //航向
unsigned char NS;
unsigned char EW;
};
int GpsDialog::getGPSinfo(QString& str)
{
st_gps_info gps;
QString cHead = "$GPRMC";
QString tmp;
bool ok;
str = str.mid(str.indexOf(cHead,1),100);
str = str.section('$',1,1);
qDebug() << str;
tmp = str.section(',',2,2);
if(tmp == "V"){
postion = tr("无效定位");
return -1;
}
tmp = str.section(',',3,3);
qDebug() << tmp;
gps.longitude = tmp.toDouble(&ok)/100;
tmp = str.section(',',5,5);
gps.latitude = tmp.toDouble(&ok)/100;
tmp = str.section(',',4,4);
if(tmp == "N")
gps.NS = 'N';
else
gps.NS = 'S';
tmp = str.section(',',6,6);
if(tmp == "E")
gps.EW = 'E';
else
gps.EW = 'W';
tmp = str.section(',',7,7);
gps.speed = tmp.toFloat(&ok)*1.85;
tmp = str.section(',',8,8);
gps.direction = tmp.toFloat(&ok);
if(gps.NS == 'N')
postion = tr("北纬: ");
else
postion = tr("南纬: ");
postion += QString::number(gps.longitude,'f',2);
postion += " ";
if(gps.EW == 'E')
postion += tr("东经: ");
else
postion += tr("西经: ");
postion += QString::number(gps.latitude,'f',2);
speed = tr("时速: ");
speed += QString::number(gps.speed,'f',2);
speed += " Km/H";
speed += " ";
speed += tr("方向(北偏): ");
speed += QString::number(gps.direction,'f',2);
speed += tr("度");
return 0;
}
GPS调试信息
com_info=====
"$GPRMC,045424.00,A,3022.29979,N,11454.03987,E,0.516,,111116,,,A*79
$GPVTG,,T,,M,0.516,N,0.956,K,A*2B
$GPGGA,045424.00,3022.29979,N,11454.03987,E,1,09,1.02,124.6,M,-9.0,M,,*4F
$GPGSA,A,3,05,02,06,07,20,29,13,30,15,,,,1.82,1.02,1.50*04
$GPGSV,3,1,12,02,57,095,29,04,71,104,31,05,59,009,27,06,22,112,17*7D
$GPGSV,3,2,12,07,06,051,15,12,03,219,10,13,64,169,20,15,37,209,14*73
$GPGSV,3,3,12,20,37,282,30,25,03,254,,29,41,302,32,30,14,081,28*7B
$GPGLL,3022.29979,N,11454.03987,E,045424.00,A,A*65
"
section======
"GPRMC,045424.00,A,3022.29979,N,11454.03987,E,0.516,,111116,,,A*79
"
tmp=====
"3022.29979"
Qt程序运行界面
头文件
#ifndef GPSDIALOG_H
#define GPSDIALOG_H
#include <QtGui>
#include "mapwidget.h"
#define COM0 "/dev/ttyUSB0"
class GpsDialog:public QDialog
{
Q_OBJECT
public:
GpsDialog(QWidget *parent = 0);
int gpsInit(void);
int getGPSinfo(QString& str);
public slots:
void gpsRun(void);
private:
int fd_gps;
char* buff;
QString postion;
QString speed;
MapWidget *mapGps;
QGridLayout *layout;
QLabel *labelBg;
QLineEdit *lineGps;
QLineEdit *lineSpeed;
QToolButton *toolButton;
};
#endif // GPSDIALOG_H
实现源程序
#include "gpsdialog.h"
#include "dht9000.h"
GpsDialog::GpsDialog( QWidget *parent)
: QDialog( parent)
{
this->setMinimumSize(800,480);
this->setMaximumSize(800,480);
//窗口标题
this->setWindowIcon(QPixmap( ":/images/1.png") );
this->setWindowTitle(tr("GP9001车载GPS监控系统"));
//窗口背景
labelBg = new QLabel(this);
labelBg->setGeometry(QRect(0, 0, 800, 480));
labelBg->setPixmap(QPixmap(":/images/9001bg.jpg"));
labelBg->setScaledContents(true);
//计时器对象,1秒钟发送一个timeout()信号,调用showState()函数
QTimer *timer = new QTimer(this);
timer->start(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(gpsRun()));
postion = "GPS no init.";
buff = (char*)malloc(1024);
mapGps = new MapWidget(this);
lineGps = new QLineEdit(this);
lineGps->setReadOnly(true);
lineGps->setAlignment(Qt::AlignHCenter);
lineGps->setText(tr("经度:123.44 纬度:34.54"));
lineSpeed = new QLineEdit(this);
lineSpeed->setReadOnly(true);
lineSpeed->setAlignment(Qt::AlignHCenter);
lineSpeed->setText(QString::number(12.55,'f',2)+tr("公里/小时"));
toolButton = new QToolButton(this);
toolButton->setText( tr( "返 回" ) );
toolButton->setIcon( QPixmap( ":/images/6.png") );
toolButton->setIconSize( QPixmap( ":/images/6.png").size() );
toolButton->setAutoRaise( TRUE );
toolButton->setToolButtonStyle( Qt::ToolButtonTextUnderIcon);
connect(toolButton,SIGNAL(clicked()),this,SLOT(accept()));
gpsInit();
layout = new QGridLayout;
layout->setSpacing(5);
layout->addWidget(mapGps,1,0,1,3);
layout->addWidget(lineGps,2,0);
layout->addWidget(toolButton,2,1);
layout->addWidget(lineSpeed,2,2);
setLayout(layout);
}
int GpsDialog::getGPSinfo(QString& str)
{
st_gps_info gps;
QString cHead = "$GPRMC";
QString tmp;
bool ok;
str = str.mid(str.indexOf(cHead,1),100);
str = str.section('$',1,1);
qDebug() << "section======" <<endl << str;
tmp = str.section(',',2,2);
if(tmp == "V"){
postion = tr("无效定位");
return -1;
}
tmp = str.section(',',3,3);
qDebug() << "tmp=====" <<endl << tmp;
gps.longitude = tmp.toDouble(&ok)/100;
tmp = str.section(',',5,5);
gps.latitude = tmp.toDouble(&ok)/100;
tmp = str.section(',',4,4);
if(tmp == "N")
gps.NS = 'N';
else
gps.NS = 'S';
tmp = str.section(',',6,6);
if(tmp == "E")
gps.EW = 'E';
else
gps.EW = 'W';
tmp = str.section(',',7,7);
gps.speed = tmp.toFloat(&ok)*1.85;
tmp = str.section(',',8,8);
gps.direction = tmp.toFloat(&ok);
if(gps.NS == 'N')
postion = tr("北纬: ");
else
postion = tr("南纬: ");
postion += QString::number(gps.longitude,'f',2);
postion += " ";
if(gps.EW == 'E')
postion += tr("东经: ");
else
postion += tr("西经: ");
postion += QString::number(gps.latitude,'f',2);
speed = tr("时速: ");
speed += QString::number(gps.speed,'f',2);
speed += " Km/H";
speed += " ";
speed += tr("方向(北偏): ");
speed += QString::number(gps.direction,'f',2);
speed += tr("度");
return 0;
}
void GpsDialog::gpsRun(){
int nread;
QString gpsInfo;
memset(buff,0,1024);
if((nread = read(fd_gps,buff,1024))>0){
gpsInfo = buff;
qDebug() << "com_info=====" << endl << gpsInfo;
if(gpsInfo.length()>0)
this->getGPSinfo(gpsInfo);
}else{
postion = "GPS recvie error.";
speed = postion;
}
lineGps->setText(postion);
lineSpeed->setText(speed);
}
int GpsDialog::gpsInit(void){
fd_gps = ::open(COM0,O_RDONLY);
if(fd_gps < 0){
postion = "Can't Open Serial Port!";
postion += COM0;
return -1;
}
if(init_com(fd_gps) < 0){
postion = "Serial Init error!";
return -1;
}
postion = "GPS init OK.";
lineGps->setText(postion);
return 0;
}