目录
目标:
使用QT,读取gps模块的串口数据,并解析其中的经纬高数据,然后进行处理
一、QT读取串口数据
变量定义
QSerialPort *serial;
QSerialPortInfo SerialPortInfo;
QByteArray lineData;
串口初始化
//初始化串口
void serialPort::initSerialPort() {
serial = new QSerialPort;
QList<QSerialPortInfo> listCom;//获取串口列表
listCom = QSerialPortInfo::availablePorts();
for (int i = 0; i < listCom.size(); i++)
qDebug() << "串口名称:" << listCom[i].portName();//打印串口信息
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())//搜索串口,获取串口列表
{
if (info.portName() == "COM3") {//在串口列表中查找
//此处使用的是判断串口描述说明相同
SerialPortInfo = info;//储存串口信息
serial->setPort(info);//设置串口
break;//找到所需要的串口信息,退出循环
}//使用if语句判断是否所需串口
}
if (SerialPortInfo.portName() == "COM3") {
qDebug() << "所需串口已找到,具体信息如下:";
qDebug() << "Name : " << SerialPortInfo.portName();//串口名称,比如com3
qDebug() << "Description : " << SerialPortInfo.description();//串口描述说明
qDebug() << "Manufacturer: " << SerialPortInfo.manufacturer();
qDebug() << "Serial Number: " << SerialPortInfo.serialNumber();//串口号
qDebug() << "System Location: " << SerialPortInfo.systemLocation();//系统位置
}
else {
qDebug() << "串口信息未找到,请检查设备是否连接";
}
serial->setBaudRate(QSerialPort::Baud9600);//设置串口波特率(9600)
serial->setDataBits(QSerialPort::Data8);//设置数据位(8)
serial->setParity(QSerialPort::NoParity); //设置奇偶校检(无)
serial->setStopBits(QSerialPort::OneStop);//设置停止位(一位)
serial->setFlowControl(QSerialPort::NoFlowControl);//设置流控制(无)
serial->open(QIODevice::ReadOnly);//打开串口,并设置串口为只读模式
if (serial->isOpen())
qDebug() << "串口已经打开";
connect(serial, SIGNAL(readyRead()), this, SLOT(slot_read_from_port()));
}
二、解析数据
因为串口每次读取不定长的字符,因此需要对每一条GPS数据进行拼接,遇到回车符\n拼接结束,进行解析。
void serialPort::slot_read_from_port() {
QByteArray byteArray = serial->readAll();
lineData.append(byteArray);
if (lineData.contains('\n'))//只有等到\n的时候才能进入
{
QString lineQstring = QString::fromLocal8Bit(lineData);
qDebug() << "lineQstring: " << lineQstring;
QString parseName = "GNGGA";
//解析GPGGA数据
if (lineQstring.contains(parseName)) { //如果解析北斗数据,换为 BDGGA 格洛纳斯:GLGGA
//qDebug()<<"parse data: " << lineQstring;
//通过逗号分割数据
QList<QString>d = lineQstring.split(',');
/*
(1)UTC时间,格式为hhmmss.ss;
(2)纬度,格式为ddmm.mmmmm(度分格式);
(3)纬度半球,N或S(北纬或南纬);
(4)经度,格式为dddmm.mmmmm(度分格式);
(5)经度半球,E或W(东经或西经);
(9) 海拔高度(-9999.9~99999.9)
*/
//时间转为秒
_flyData.time = d[1].mid(0, 2).toInt() * 60 * 60 + d[1].mid(2, 2).toInt() * 60 + d[1].mid(4, 2).toInt();
//纬度
if (d[3] == "N") {
_flyData.lat = parseLngLat(d[2].toDouble());
}
else if (d[3] == "S") {
_flyData.lat = -parseLngLat(d[2].toDouble());
}
//经度
if (d[5] == "E") {
_flyData.lng = parseLngLat(d[4].toDouble());
}
else if (d[5] == "W") {
_flyData.lng = -parseLngLat(d[4].toDouble());
}
//高度
_flyData.alt = d[9].toDouble();
//qDebug() << d[1] << " " << _flyData.lng << " " << _flyData.lat << " " << _flyData.alt;
}
lineData.clear();
}
}
//解析经纬度至小数
double serialPort::parseLngLat(double LL) { //例如:4546.40891
//度
int d = int(LL / 100);
int m = int(LL - d * 100);
double s = ((LL - d * 100) - m) * 60;
//组合为小数
return (d + m / 60.0 + s / 3600.0);
}