GPS模块运用: 定位测试软件设计(上位机)

本文涉及的产品
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
全局流量管理 GTM,标准版 1个月
简介: GPS模块运用: 定位测试软件设计(上位机)

一、硬件介绍

GPS模块型号:  中科微电子ATGM336H-5N 系列模块


ATGM336H-5N 系列模块是 9.7X10.1 尺寸的高性能 BDS/GNSS 全星座定位导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗 GNSS SOC 单芯片—AT6558,支持多种卫星导航系统,包括中国的 BDS(北斗卫星导航系统),美国的 GPS,俄罗斯的 GLONASS,欧盟的 GALILEO,日本的 QZSS以及卫星增强系统 SBAS(WAAS,EGNOS,GAGAN,MSAS)。AT6558 是一款真正意义的六合一多模卫星导航定位芯片,包含 32 个跟踪通道,可以同时接收六个卫星导航系统的 GNSS 信号,并且实现联合定位、导航与授时。


二、软件功能介绍

解析GPS模块接收的数据,得到经纬度和速度。


软件支持GPS模式配置、指定的语句输出配置。


软件设计思路:


串口在子线程里完成数据接收,将解析的数据保存到全局类中,全局类里加了读写锁,防止多线程读写全局变量出现问题。


主UI线程里负责数据显示,解析的结果使用定时器2秒钟显示一次。


软件下载地址: https://download.csdn.net/download/xiaolong1126626497/12721684


软件运行效果:

image.png

GPS模块连线:

image.png

三、软件核心代码

3.1 uart_code.h

#ifndef UART_CODE_H
#define UART_CODE_H
#include <QSerialPort>
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QString>
#include "config.h"
class OBD_Data
{
public:
      QString V; //电瓶电压
      QString R; //转速
      QString S; //速度
      QString P; //绝对气门开度
      QString O; //发动机负荷
      QString C; //冷却液温度
      QString L; //油量
      QString M; //此次行程米
      QString F; //此次油耗L
      QString XM; //瞬时油耗、百公里油耗
      QString T; //运行时间
      //QString E; //发动机状态 0熄火 1点火 2自动启动
      QString A; //急加速次数
      QString B; //急刹车次数
      QString D; //故障码个数
      QString GX;//X
      QString GY;//Y
      QString GZ;//Z
      QString data;
};
class GPS_Data
{
private:
    double lat; //纬度
    double lng; //经度
    QString speed; //速度
    QReadWriteLock lock; //读写锁
    QString save_src_data; //原始数据
public:
    QString Data;
    //构造函数
    GPS_Data()
    {
        lat=0.0;
        lng=0.0;
        speed="0";
        save_src_data="";
    }
    //读取纬度
    double get_lat(void)
    {
        lock.lockForRead();
        double tmp_lat=lat;
        lock.unlock();
        return  tmp_lat;
    }
    //设置纬度
    void set_lat(double tmp_lat)
    {
        lock.lockForWrite();
        lat=tmp_lat;
        lock.unlock();
    }
    //读取经度
    double get_lng(void)
    {
        lock.lockForRead();
        double tmp_lng=lng;
        lock.unlock();
        return  tmp_lng;
    }
    //设置经度
    void set_lng(double tmp_lng)
    {
        lock.lockForWrite();
        lng=tmp_lng;
        lock.unlock();
    }
    //读取速度
    QString get_speed(void)
    {
        lock.lockForRead();
        QString tmp_speed=speed;
        lock.unlock();
        return  tmp_speed;
    }
    //设置速度
    void set_speed(QString tmp_speed)
    {
        lock.lockForWrite();
        speed=tmp_speed;
        lock.unlock();
    }
    //读取原始数据
    QString get_src_data(void)
    {
        lock.lockForRead();
        QString tmp_speed=save_src_data;
        lock.unlock();
        return  tmp_speed;
    }
    //设置原始数据
    void set_src_data(QString tmp_save_src_data)
    {
        lock.lockForWrite();
        save_src_data+=tmp_save_src_data;
        if(save_src_data>1024)save_src_data.clear();
        lock.unlock();
    }
    //清除原始数据
    void set_src_clear(void)
    {
        lock.lockForWrite();
        save_src_data.clear();
        lock.unlock();
    }
};
class UART_ReadWriteThread:public QObject
{
    Q_OBJECT
public:
    QByteArray byte_all;
    UART_ReadWriteThread(QObject* parent=nullptr):QObject(parent){}
    ~UART_ReadWriteThread();
    //成员变量
    QSerialPort *UART_Config=nullptr; //串口---数据接收串口
    int GPS_GetData(const char *gps_src,const char *find_head,char *buff,int cnt);
    int GPS_GetCheckSum(const char *src_str,const char *find_str);
public slots:
    void UART_ReadUasrtData(void);
    void run();
    void Open_UART(void);
    void Close_UART(void);
    void UART_Send(QString text);
signals:
    void LogSend(QString text);
    void SendUartState(qint8 state);  //发送串口状态   true 表示连接 否则表示断开
};
#endif // UART_CODE_H

3.2 uart_code.cpp

#include "uart_code.h"
#include "config.h"
QString current_SerialPort="";  //当前串口端口号
qint32 current_SerialBaudRate=0; //当前波特率
class OBD_Data obd_data;
class GPS_Data gps_data;
UART_ReadWriteThread::~UART_ReadWriteThread()
{
}
void UART_ReadWriteThread::run()
{
    //串口配置
    if(UART_Config)
    {
        UART_Config->close();
        delete UART_Config;
        UART_Config=nullptr;
    }
    UART_Config =new QSerialPort;
    //打开串口设备
    Open_UART();
}
//当串口打不开的时候,间隔一段时间再次重新测试
void UART_ReadWriteThread::Open_UART(void)
{
    //配置串口属性
    UART_Config->setBaudRate(current_SerialBaudRate);              //默认波特率
    UART_Config->setDataBits(QSerialPort::Data8);  //数据位
    UART_Config->setParity(QSerialPort::NoParity); //奇偶校验
    UART_Config->setStopBits(QSerialPort::OneStop);//停止位
    UART_Config->setFlowControl(QSerialPort::NoFlowControl); //流控开关
    UART_Config->setPortName(current_SerialPort);    //COM的名称
    //1 数据传输串口连接 2 数据传输串口断开
    if(!(UART_Config->open(QIODevice::ReadWrite)))      //打开的属性权限
    {
        LogSend("数据传输串口打开失败.\n");
        SendUartState(2); //发送信号 通知状态改变
    }
    else
    {
        LogSend("数据传输串口打开成功.\n");
        SendUartState(1); //发送信号 通知状态改变
        //关联数据读信号
        connect(UART_Config,SIGNAL(readyRead()),this,SLOT(UART_ReadUasrtData()),Qt::QueuedConnection);
    }
}
//读取串口数据
void UART_ReadWriteThread::UART_ReadUasrtData()
{
    QString byte;
    /*读取串口缓冲区所有的数据*/
    byte=UART_Config->readAll();
    LogSend(byte);
    /*读取串口缓冲区所有的数据*/
    gps_data.Data+=byte;
    //完整的1帧VTG--RMC数据在109字节左右
    //if(gps_data.Data.size()>=200)
    if(gps_data.Data.count("\r\n")>=2 && gps_data.Data.count("$GNRMC")>=1 && gps_data.Data.count("$GNVTG")>=1)
    {
        //保存原始数据
        gps_data.set_src_data(gps_data.Data);
        char *gps_p;
        char gps_tmp_buff[50];
        gps_p=gps_data.Data.toLocal8Bit().data();
        //计算$GNRMC校验和
        if(GPS_GetCheckSum(gps_p,"$GNRMC")==0)
        {
            //qDebug()<<"$GNRMC 校验和计算成功.\n";
           // LogSend("$GNRMC 校验和计算成功\n");
            //提取定位状态数据
            GPS_GetData(gps_p,"$GNRMC",gps_tmp_buff,2);
            //判断定位数据是否有效
            if(gps_tmp_buff[0]=='A')
            {
                SendUartState(3); //发送信号 通知状态改变  定位成功
                //qDebug()<<"定位成功.";
                //提取纬度
                GPS_GetData(gps_p,"$GNRMC",gps_tmp_buff,3);
                QString lat=gps_tmp_buff;  //得到纬度
                //提取经度
                GPS_GetData(gps_p,"$GNRMC",gps_tmp_buff,5);
                QString lng=gps_tmp_buff;  //得到经度
               // qDebug()<<"当前纬度:"<<lat;
               //qDebug()<<"当前经度:"<<lng;
                unsigned int int_data;
                double s_Longitude,s_latitude;
                //转换纬度
                s_latitude=lat.toDouble();
                s_latitude=s_latitude/100;
                int_data=s_latitude;//得到纬度整数部分
                s_latitude=s_latitude-int_data;//得到纬度小数部分
                s_latitude=(s_latitude)*100;
                gps_data.set_lat(int_data+(s_latitude/60.0)); //得到转换后的值
                //转换经度
                s_Longitude=lng.toDouble();
                s_Longitude=s_Longitude/100;
                int_data=s_Longitude;//得到经度整数部分
                s_Longitude=s_Longitude-int_data; //得到经度小数部分
                s_Longitude=s_Longitude*100;
                //gai guo le
                gps_data.set_lng(int_data+(s_Longitude/60.0));
            }
            else
            {
                SendUartState(4); //发送信号 通知状态改变  定位失败
                //GPS经纬度置0
                gps_data.set_lat(0.0);
                gps_data.set_lng(0.0);
            }
        }
        else
        {
            //GPS经纬度置0
            gps_data.set_lat(0.0);
            gps_data.set_lng(0.0);
        }
        //计算GNVTG校验和
        if(GPS_GetCheckSum(gps_p,"$GNVTG")==0)
        {
            //提取速度
            GPS_GetData(gps_p,"$GNVTG",gps_tmp_buff,7);
            gps_data.set_speed(gps_tmp_buff);
        }
        else
        {
            gps_data.set_speed("0");//当前速度置0
        }
        //清空数据
        gps_data.Data.clear();
    }
}
//关闭串口
//1 数据传输串口连接 2 数据传输串口断开
void UART_ReadWriteThread::Close_UART(void)
{
    SendUartState(2); //发送信号 通知状态改变
    if(UART_Config->isOpen())
    {
       UART_Config->close();
    }
}
//发送数据
void UART_ReadWriteThread::UART_Send(QString text)
{
   //qDebug()<<text;
    //如果串口处于打开状态就发送数据
    if(UART_Config->isOpen())
    {
        QByteArray byte=text.toLocal8Bit();
        UART_Config->write(byte);
    }
}
/*
函数功能: 根据逗号位置提取数据
函数参数:
char *gps_src GPS源字符串地址
char *buff 存放提取的数据
char *find_head 查找的GPS数据头  例如:$GNVTG
int cnt  逗号的偏移量
返回值:提取的字节数。
*/
int UART_ReadWriteThread::GPS_GetData(const char *gps_src,const char *find_head,char *buff,int cnt)
{
    const char *p;
    int number=0; //提取的数量
    int a=0;
    p=strstr(gps_src,find_head);
    if(p!=nullptr)
    {
        //查找逗号的位置
        while(*p!='\0')
        {
            if(*p==',')a++; //记录逗号的数量
            if(a==cnt)break; //逗号找成功了
            p++;
        }
        p++; //跨过当前逗号
        //提取数据
        while(*p!='\0')
        {
            if(*p==',')break; //遇到逗号停止提取数据
            buff[number]=*p;
            p++;
            number++;
        }
        buff[number]='\0';
    }
    return number;
}
/*
 * 计算GPS数据指定数据的校验和
 * char *src_str GPS源字符串
 * char *find_str GPS数据头  例如:$GNVTG
 * 返回值: -1表示失败  0表示成功
*/
int UART_ReadWriteThread::GPS_GetCheckSum(const char *src_str,const char *find_str)
{
    const char *tmp_p;
    /*1. 开始解析数据*/
    tmp_p=strstr(src_str,find_str);
    if(tmp_p!=nullptr)
    {
        unsigned char data=0;
        tmp_p++;
        //计算校验和
        while(*tmp_p!='*' && *tmp_p!='\0')
        {
            data^=*tmp_p;
            tmp_p++;
        }
        QString sum_str=QString::number(data,16);
        QString sum_val;
        //提取校验和
        sum_val[0]=*(tmp_p+1);
        sum_val[1]=*(tmp_p+2);
        //qDebug()<<"sum_val:"<<sum_val;
        //qDebug()<<"sum_str:"<<sum_str;
        //判断校验和,不区分大小写
        if(sum_str.compare(sum_val,Qt::CaseInsensitive)==0)
        {
            return 0; //校验正确
        }
    }
    return -1;
}

3.3 widget.h代码

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSerialPortInfo>
#include <QSerialPort>
#include <QPlainTextEdit>
#include <QScrollBar>
#include <QTimer>
#include <QThread>
#include <QDebug>
#include "uart_code.h"
#include "config.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = NULL);
    ~Widget();
    void GetDeviceList();
    /*构造一个列表*/
    QList<QSerialPortInfo> usart_device_list;
    QSerialPort *UART_Config; //串口
    QTimer timer;
    qint8 connect_state=0; //串口连接状态
    //串口线程
    UART_ReadWriteThread uart_WorkClass; //串口读写-工作函数
    QThread uart_Workthread; //串口读写--线程
private slots:
    void Log_Text_Display(QString text);
    void Log_Text_Display2(QString text);
    void UART_State_Display(qint8 state);  //串口状态显示
    void update();
    void on_pushButton_2_clicked();
    void on_pushButton_clicked();
    void on_pushButton_send_data_clicked();
    void on_pushButton_mode_set_clicked();
    void on_pushButton_open_all_clicked();
    void on_pushButton_close_all_clicked();
    void on_pushButton_open_rmc_clicked();
    void on_pushButton_open_vtg_clicked();
signals:
    void Start_Uart_Read();
    void Uart_SendData(QString text);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

3.4 widget.cpp代码

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("GPS数据解析工具");
    GetDeviceList();
    connect(&timer, SIGNAL(timeout()), this, SLOT(update()));
    timer.start(2000);
    //串口初始化
    //连接串口的日志信息
    connect(&uart_WorkClass,SIGNAL(LogSend(QString)),this,SLOT(Log_Text_Display(QString)));
    connect(&uart_WorkClass,SIGNAL(SendUartState(qint8)),this,SLOT(UART_State_Display(qint8)));
    //连接串口初始化函数
    connect(this,SIGNAL(Start_Uart_Read()),&uart_WorkClass,SLOT(run()));
    //连接串口发送函数
    connect(this,SIGNAL(Uart_SendData(QString)),&uart_WorkClass,SLOT(UART_Send(QString)));
    //将串口工作对象移动到子线程里工作
    uart_WorkClass.moveToThread(&uart_Workthread);
}
Widget::~Widget()
{
    delete ui;
}
void Widget::GetDeviceList()
{
    ui->comboBox->clear();
    //获取系统串口设备
    usart_device_list=QSerialPortInfo::availablePorts();
    /*打印出支持的串口名称*/
    for(int i=0;i<usart_device_list.count();i++)
    {
        ui->comboBox->addItem(usart_device_list.at(i).portName());
    }
}
void Widget::on_pushButton_2_clicked()
{
    GetDeviceList();
}
void Widget::on_pushButton_clicked()
{
    current_SerialPort=ui->comboBox->currentText();  //当前串口端口号
    current_SerialBaudRate=ui->comboBox_baud->currentText().toInt(); //当前波特率
    if(ui->pushButton->text()=="打开串口")
    {
        if(current_SerialPort.isEmpty()||current_SerialBaudRate<=0)
        {
            QMessageBox::information(this,"提示","请先选择串口COM和波特率\n在菜单栏的设置页面找到串口设置按钮.",
            QMessageBox::Ok,QMessageBox::Ok);
        }
        else
        {
            ui->pushButton->setText("关闭串口");
            uart_Workthread.start(); //启动串口线程
            Start_Uart_Read(); //发送信号启动串口工作
        }
    }
    else
    {
        uart_WorkClass.Close_UART(); //关闭串口
        uart_Workthread.quit(); //退出线程
        uart_Workthread.wait(); //等待线程退出
        ui->pushButton->setText("打开串口");
    }
}
/*日志显示*/
void Widget::Log_Text_Display(QString text)
{
    QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit;
    //设置光标到文本末尾
    plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
    //当文本数量超出一定范围就清除
    if(plainTextEdit_log->toPlainText().size()>4096)
    {
        plainTextEdit_log->clear();
    }
    plainTextEdit_log->insertPlainText(text);
    //移动滚动条到底部
    QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
    if(scrollbar)
    {
        scrollbar->setSliderPosition(scrollbar->maximum());
    }
}
/*日志显示*/
void Widget::Log_Text_Display2(QString text)
{
    QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit2;
    //设置光标到文本末尾
    plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
    //当文本数量超出一定范围就清除
    if(plainTextEdit_log->toPlainText().size()>4096)
    {
        plainTextEdit_log->clear();
    }
    plainTextEdit_log->insertPlainText(text);
    //移动滚动条到底部
    QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
    if(scrollbar)
    {
        scrollbar->setSliderPosition(scrollbar->maximum());
    }
}
void Widget::update()
{
    QString text="";
    QString gps_text=gps_data.get_src_data();
    gps_data.set_src_clear(); //清除保存的原始数据
    gps_text=gps_text.remove("\r");
    gps_text=gps_text.remove("\n");
    //串口连接成功的情况下才需要打印
    if(connect_state==1)
    {
        text="GPS:";
        text+=tr("纬度=%1,").arg(gps_data.get_lat(),0,'g',13); //纬度
        text+=tr("经度=%1,").arg(gps_data.get_lng(),0,'g',13); //经度
        text+=tr("速度=%1\n").arg(gps_data.get_speed());//速度
        Log_Text_Display2(text);
        text+=tr("原始数据:%1\n").arg(gps_text);//原始数据
        Log_Text_Display2(text);
    }
}
//串口状态显示
//1 数据传输串口连接 2 数据传输串口断开
void Widget::UART_State_Display(qint8 state)
{
   if(state==1)
   {
       connect_state=state;
       Log_Text_Display("串口连接\n");
   }
   if(state==2)
   {
       connect_state=state;
       Log_Text_Display("串口断开\n");
   }
   if(state==3)  //GPS定位成功
   {
       ui->label_gps_stat->setText("GPS定位状态: 定位成功");
   }
   if(state==4)  //GPS定位失败
   {
       ui->label_gps_stat->setText("GPS定位状态: 正在定位中..请稍等");
   }
}
//发送数据
void Widget::on_pushButton_send_data_clicked()
{
    QString text=ui->lineEdit_send_data->text();
    if(ui->checkBox->isChecked())
    {
        text+="\r\n";
        Uart_SendData(text);
    }
    else
    {
        Uart_SendData(text);
    }
}
void Widget::on_pushButton_mode_set_clicked()
{
     Uart_SendData("$PCAS11,3*1E\r\n");
}
void Widget::on_pushButton_open_all_clicked()
{
    Uart_SendData("$CCRMO,GGA,4,1*38\r\n");
}
void Widget::on_pushButton_close_all_clicked()
{
    Uart_SendData("$CCRMO,GGA,3,1*3F\r\n");
}
void Widget::on_pushButton_open_rmc_clicked()
{
    Uart_SendData("$CCRMO,RMC,2,1*23\r\n");
}
void Widget::on_pushButton_open_vtg_clicked()
{
     Uart_SendData("$CCRMO,VTG,2,1*3A\r\n");
}


目录
相关文章
|
4月前
|
安全 Linux 网络安全
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(一)
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(一)
96 2
|
4月前
|
Python Windows 网络安全
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(二)
Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块(二)
112 2
|
1月前
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的16psk调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的16PSK调制解调系统的硬件测试版本。系统在原有仿真基础上增加了ILA在线数据采集和VIO在线SNR设置模块,支持不同信噪比下的性能测试。16PSK通过改变载波相位传输4比特信息,广泛应用于高速数据传输。硬件测试操作详见配套视频。开发板使用及移植方法也一并提供。
37 6
|
2月前
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的QPSK调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的QPSK调制解调系统的硬件实现与仿真效果。系统包含测试平台(testbench)、高斯信道模块、误码率统计模块,支持不同SNR设置,并增加了ILA在线数据采集和VIO在线SNR设置功能。通过硬件测试验证了系统在不同信噪比下的性能,提供了详细的模块原理及Verilog代码示例。开发板使用说明和移植方法也一并给出,确保用户能顺利在不同平台上复现该系统。
82 15
|
1月前
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的8PSK调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于FPGA实现8PSK调制解调系统,包含高斯信道、误码率统计、ILA数据采集和VIO在线SNR设置模块。通过硬件测试和Matlab仿真,展示了不同SNR下的星座图。8PSK调制通过改变载波相位传递信息,具有高频谱效率和抗干扰能力。开发板使用及程序移植方法详见配套视频和文档。
44 7
|
2月前
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的2FSK调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的2FSK调制解调系统,包含高斯信道、误码率统计模块及testbench。系统增加了ILA在线数据采集和VIO在线SNR设置模块,支持不同SNR下的硬件测试,并提供操作视频指导。理论部分涵盖频移键控(FSK)原理,包括相位连续与不连续FSK信号的特点及功率谱密度特性。Verilog代码实现了FSK调制解调的核心功能,支持在不同开发板上移植。硬件测试结果展示了不同SNR下的性能表现。
80 6
|
4月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
79 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
8月前
|
监控 测试技术 UED
软件测试中的性能瓶颈定位与优化策略
在软件开发的生命周期中,性能测试是确保产品质量的关键步骤之一。本文深入探讨了性能测试的重要性,并提出了一套系统的性能瓶颈定位与优化策略。通过分析现代软件系统中常见的性能问题,结合最新的研究成果和行业最佳实践,文章详细介绍了如何运用科学严谨的方法来识别和解决性能瓶颈。此外,本文还强调了逻辑严密的问题分析框架和数据驱动的决策过程对于提升软件性能的重要性。
|
4月前
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
199 3
|
5月前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
318 4
Android性能测试——发现和定位内存泄露和卡顿

热门文章

最新文章