当前位置: 首页 > article >正文

RK3588使用笔记:ubuntu/麒麟系统功能测试程序

一、前言

本编文章记录在使用嵌入式系统中的一些功能测试demo程序,大部分都是AI写的,哈哈哈,确实很有帮助,但是得根据自身设备实际情况和知道如何问AI,才能得出你想要的结果,本文就记录一些ubuntu/麒麟系统实际使用过程中测试程序。

目录

1.串口测试程序

2.CAN测试程序

3.背光测试程序(弥补系统pwm匹配异常)

4.电量获取程序(弥补底系统版本不支持电池管理)

5.GPIO测试程序控制状态led灯

6.时间测试程序

7.redis通信测试程序

8.温度、CPU主频测试程序

9.msata挂载稳定性测试程序

二、环境

RK3588(linux5.10.66+debian/ubuntu/麒麟是桌面文件系统)

调试笔记本window10,安装常用工具winscp,xshell,finalshell,secureRTP等等

VMware17+Ubuntu20.04源码开发环境(这里就依赖于各个硬件平台的厂家提供资料了)

QT5.7 

三、正文

程序都是QT环境开发的程序,程序内容放的都是核心代码,相关头文件简单补充,或者直接参考核心代码继续询问AI即可,大部分AI都是可以解决的

统一说明main.cpp引用了全局函数MySleep(),common.h也都是头文件

main.cpp

​//延时usetime:非阻塞时间  waittime:阻塞时间
void MySleep(uint usetime,ulong waittime)
{QCoreApplication::processEvents(QEventLoop::AllEvents, usetime);//进入此函数内给之前数据usetime毫秒时间处理,处理完立马退出执行之后,超时立马退出QThread::msleep(waittime);//阻塞延时waittime毫秒
}

 common.h

#ifndef COMMON_H
#define COMMON_H
#include <QVector>
#include <QMap>
#include <QApplication>
#include <QMainWindow>
#include <QtSql>
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
#include <QPixmap>
#include <QPaintEvent>
#include <QPainter>
#include <QScrollBar>
#include <QTableWidget>
#include <QListWidgetItem>
#include <QTimer>
#include <QTime>
#include <QSystemTrayIcon>
#include <QGridLayout>
#include <QPushButton>
#include <QDoubleSpinBox>
#include <QAbstractItemView>
#include <QDoubleSpinBox>
#include <QThread>extern void MySleep(uint usetime,ulong waittime);#endif // COMMON_H
1.串口测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowModality(Qt::ApplicationModal);this->setWindowTitle("RK3588 串口接口测试软件V1.0/20241016");//初始化串口open_serialport(0,NULL);//初始化串口connect(ui->pushButton_refresh,&QPushButton::clicked,[=](){//刷新串口按键回调函数ui->comboBox->clear();//遍历当前存在的串口端口号if(!serial->portName().isNull())ui->comboBox->addItem(serial->portName());//显示已经开启的串口到列表foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){QSerialPort serial;serial.setPort(info);if(serial.open(QIODevice::ReadWrite)){ui->comboBox->addItem(serial.portName());serial.close();}}});QTimer::singleShot(100,this,[=](){ui->pushButton_refresh->click();});//点击一次按键timeserialCOM=new QTimer(this);connect(timeserialCOM,&QTimer::timeout,[=](){timeserialCOM->stop();comBatAnalyze(allDataCOM);//处理串口得到的数据});//发送数据connect(ui->btn_send_1,&QPushButton::clicked,[=](){if(serial->isOpen()){QByteArray sd=QByteArray::fromHex("11223344556677889900aabbccddeeffAABBCCDDEEFF");serial->write(sd);}});QTimer *time1=new QTimer(this);time1->start(10);connect(time1,&QTimer::timeout,[=](){if(ui->checkBox_1->isChecked())ui->btn_send_1->click();});//清空数据connect(ui->btn_clear_1,&QPushButton::clicked,[=](){ui->textEdit_1->clear();});}MainWindow::~MainWindow()
{serial->clear();//先关闭之前的串口serial->close();delete ui;
}//初始化/复位串口
void MainWindow::open_serialport(bool reset,QString comstr)
{if(reset){serial->clear();//先关闭之前的串口serial->close();}serial = new QSerialPort(comstr,this);serial->open(QIODevice::ReadWrite);//读写打开serial->setBaudRate(QSerialPort::Baud115200);  //波特率QSerialPort::Baud9600serial->setDataBits(QSerialPort::Data8); //数据位serial->setParity(QSerialPort::NoParity);    //无奇偶校验serial->setStopBits(QSerialPort::OneStop);   //1停止位serial->setFlowControl(QSerialPort::NoFlowControl);  //无控制connect(serial,SIGNAL(readyRead()),this,SLOT(serialRead()));//连接串口读取函数bool open=serial->isOpen();if(open){ui->comboBox->setCurrentText(comstr);if(comstr.isNull())ui->label_324->setText("当前未开启串口,请选择");else ui->label_324->setText("当前开启串口:"+comstr);}else{if(comstr.isNull())ui->label_324->setText("当前未开启串口,请选择");else ui->label_324->setText("串口打开失败,无效或被占用");}
}
void MainWindow::serialRead()
{timeserialCOM->start(10);//设置判断10ms内接收完毕数据,在处理while (!serial->atEnd()){allDataCOM += serial->readAll().toHex();}
}void MainWindow::comBatAnalyze(QByteArray &allData)
{QByteArray dataTemp;dataTemp=allData.toUpper();
//    qDebug()<<"comBatAnalyze:"<<dataTemp;QString str;QByteArray aaa=QByteArray::fromHex(dataTemp);for(int i=0;i<aaa.size();i++)str.append(QString("%1 ").arg((uchar)aaa[i],2,16,QChar('0')).toUpper());ui->textEdit_1->append(QDateTime::currentDateTime().toString("hh:mm:ss zzz : ")+str);dataTemp.clear();//若没有需求的数据,则清除整个数据内容,重新接收判断allData=dataTemp;
}void MainWindow::on_comboBox_activated(const QString &arg1)
{open_serialport(1,arg1);//重新连接选择的串口ui->pushButton_refresh->click();//点击一次按键刷新串口资源
}

2.CAN测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowModality(Qt::ApplicationModal);this->setWindowTitle("RK3588 CAN接口测试软件V1.0/20240925");#ifndef WINDOWS//新建CAN连接//开启原生CAN2路startcan(0);//开启CAN0startcan(1);//开启CAN1
#endifMySleep(1000,500);//新建CAN连接//开启图莫斯1个CAN盒2路 CAN3 CAN4canThread=new canRevThread(this);connect(canThread,&canRevThread::threadRev1,this,&MainWindow::canAnalyze3);connect(canThread,&canRevThread::threadRev2,this,&MainWindow::canAnalyze4);canThread->start();//发送数据connect(ui->btn_send_1,&QPushButton::clicked,[=](){sendcan12(0);});connect(ui->btn_send_2,&QPushButton::clicked,[=](){sendcan12(1);});connect(ui->btn_send_3,&QPushButton::clicked,[=](){sendcan3();});connect(ui->btn_send_4,&QPushButton::clicked,[=](){sendcan4();});QTimer *time1=new QTimer(this);time1->start(10);connect(time1,&QTimer::timeout,[=](){if(ui->checkBox_1->isChecked())ui->btn_send_1->click();if(ui->checkBox_2->isChecked())ui->btn_send_2->click();if(ui->checkBox_3->isChecked())ui->btn_send_3->click();if(ui->checkBox_4->isChecked())ui->btn_send_4->click();});//清空数据connect(ui->btn_clear_1,&QPushButton::clicked,[=](){ui->textEdit_1->clear();});connect(ui->btn_clear_2,&QPushButton::clicked,[=](){ui->textEdit_2->clear();});connect(ui->btn_clear_3,&QPushButton::clicked,[=](){ui->textEdit_3->clear();});connect(ui->btn_clear_4,&QPushButton::clicked,[=](){ui->textEdit_4->clear();});}MainWindow::~MainWindow()
{stopcan();//程序退出,关闭当前开启的CAN1/2canThread->stopThread();//程序退出,关闭当前开启的CAN3/4delete ui;
}
///can1/2通讯配置(系统自带CAN2路)/
//开启can1/2
void MainWindow::startcan(int v)
{
#ifndef WINDOWSif(v == 0){
//        setuid(0);system("sudo ifconfig can0 down");system("sudo ip link set can0 up type can bitrate 500000 triple-sampling on");system("sudo ifconfig can0 up");//创建套接字//PF_CAN 为域位 同网络编程中的AF_INET 即ipv4协议//SOCK_RAW使用的协议类型 SOCK_RAW表示原始套接字 报文头由自己创建//CAN_RAW为使用的具体协议 为can总线协议socket1 =  ::socket(PF_CAN,SOCK_RAW,CAN_RAW);//创建套接字struct ifreq ifr;//接口请求结构体strcpy((char *)(ifr.ifr_name),v == 0 ? "can0" : "can1");//判断开启的是can0/1//fcntl(socket, F_SETFL, 1);        //标志FNDELAY可以保证read函数在端口上读不到字符的时候返回0fcntl(socket1, F_SETFL, 0);            //回到正常(阻塞)模式ioctl(socket1,SIOCGIFINDEX,&ifr);//指定 CAN0/1 设备addr1.can_family = AF_CAN;//协议类型addr1.can_ifindex = ifr.ifr_ifindex;//can总线外设的具体索引 类似 ip地址bind(socket1,(struct sockaddr*)&addr1,sizeof(addr1));//将套接字和canbus外设进行绑定,即套接字与 can0/1 绑定//禁用过滤规则,进程不接收报文,只负责发送,如需接受注释掉此函数即可//setsockopt(stSocket_LO, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);t1 = NULL;t1 = new Thread(socket1);//开启单独线程接受监听connect(t1,SIGNAL(message(QString,int,QString)),this,SLOT(msg1(QString,int,QString)));t1->start();}else{
//        setuid(0);system("sudo ifconfig can1 down");system("sudo ip link set can1 up type can bitrate 500000 triple-sampling on");system("sudo ifconfig can1 up");//创建套接字//PF_CAN 为域位 同网络编程中的AF_INET 即ipv4协议//SOCK_RAW使用的协议类型 SOCK_RAW表示原始套接字 报文头由自己创建//CAN_RAW为使用的具体协议 为can总线协议socket2 =  ::socket(PF_CAN,SOCK_RAW,CAN_RAW);//创建套接字struct ifreq ifr;//接口请求结构体strcpy((char *)(ifr.ifr_name),v == 0 ? "can0" : "can1");//判断开启的是can0/1//fcntl(socket, F_SETFL, 1);        //标志FNDELAY可以保证read函数在端口上读不到字符的时候返回0fcntl(socket2, F_SETFL, 0);            //回到正常(阻塞)模式ioctl(socket2,SIOCGIFINDEX,&ifr);//指定 CAN0/1 设备addr2.can_family = AF_CAN;//协议类型addr2.can_ifindex = ifr.ifr_ifindex;//can总线外设的具体索引 类似 ip地址bind(socket2,(struct sockaddr*)&addr2,sizeof(addr2));//将套接字和canbus外设进行绑定,即套接字与 can0/1 绑定//禁用过滤规则,进程不接收报文,只负责发送,如需接受注释掉此函数即可//setsockopt(stSocket_LO, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);t2 = NULL;t2 = new Thread(socket2);//开启单独线程接受监听connect(t2,SIGNAL(message(QString,int,QString)),this,SLOT(msg2(QString,int,QString)));t2->start();}
#endif
}
void MainWindow::stopcan()
{
#ifndef WINDOWSif(t1){//如果线程已经开启,关闭线程t1->stop();t1->deleteLater();}if(t2){//如果线程已经开启,关闭线程t2->stop();t2->deleteLater();}::close(socket1);::close(socket2);system("sudo ifconfig can0 down");//关闭CAN0system("sudo ifconfig can1 down");//关闭CAN1
#endif
}
void MainWindow::sendcan12(int v)
{
#ifndef WINDOWSstruct can_frame frame;memset(&frame,0,sizeof(struct can_frame));if(v==0){
//        frame.can_id = (0x00123456 & CAN_EFF_MASK) | CAN_EFF_FLAG;//扩展帧frame.can_id = (0x11 & CAN_SFF_MASK);//标准帧frame.can_dlc= 8;frame.data[0]= 0x11;frame.data[1]= 0xaa;frame.data[2]= 0x11;frame.data[3]= 0xaa;frame.data[4]= 0x11;frame.data[5]= 0xaa;frame.data[6]= 0x11;frame.data[7]= 0xaa;}else{
//        frame.can_id = (0x00abcdef & CAN_EFF_MASK) | CAN_EFF_FLAG;//扩展帧frame.can_id = (0x22 & CAN_SFF_MASK);//标准帧frame.can_dlc= 8;frame.data[0]= 0x22;frame.data[1]= 0xbb;frame.data[2]= 0x22;frame.data[3]= 0xbb;frame.data[4]= 0x22;frame.data[5]= 0xbb;frame.data[6]= 0x22;frame.data[7]= 0xbb;}//发送can数据:方式一//sendto(socket,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,sizeof(addr));//发送can数据:方式二if(v==0)write(socket1, &frame, sizeof(frame)); //发送 frameelse write(socket2, &frame, sizeof(frame)); //发送 framereturn;
#endif
}
//can1接收槽函数
void MainWindow::msg1(QString addr,int num,QString data)
{QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(addr).arg(num).arg(data);ui->textEdit_1->append(str);
}
//can2接收槽函数
void MainWindow::msg2(QString addr,int num,QString data)
{QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(addr).arg(num).arg(data);ui->textEdit_2->append(str);
}///can3/4通讯配置(图莫斯1个盒2路)/
//发送can3
void MainWindow::sendcan3()
{CAN_MSG CanMsg;CanMsg.ExternFlag = 0;//是否是扩展帧CanMsg.RemoteFlag = 0;//是否是远程帧CanMsg.ID = 0x33;CanMsg.DataLen = 8;CanMsg.Data[0]=0x33;CanMsg.Data[1]=0xcc;CanMsg.Data[2]=0x33;CanMsg.Data[3]=0xcc;CanMsg.Data[4]=0x33;CanMsg.Data[5]=0xcc;CanMsg.Data[6]=0x33;CanMsg.Data[7]=0xcc;canThread->sendcanData(0,CanMsg);
}
//发送can4
void MainWindow::sendcan4()
{CAN_MSG CanMsg;CanMsg.ExternFlag = 0;//是否是扩展帧CanMsg.RemoteFlag = 0;//是否是远程帧CanMsg.ID = 0x44;CanMsg.DataLen = 8;CanMsg.Data[0]=0x44;CanMsg.Data[1]=0xdd;CanMsg.Data[2]=0x44;CanMsg.Data[3]=0xdd;CanMsg.Data[4]=0x44;CanMsg.Data[5]=0xdd;CanMsg.Data[6]=0x44;CanMsg.Data[7]=0xdd;canThread->sendcanData(1,CanMsg);
}
//处理can3数据
void MainWindow::canAnalyze3(CAN_MSG *CanMsgtmp,char dwRel)
{for(int i = 0 ; i < dwRel ; i++){QString address=QString().sprintf("%08X",CanMsgtmp[i].ID&0x7fffffff);QString datastr=NULL;for(int j=0;j<CanMsgtmp[i].DataLen;j++)datastr.append(QString().sprintf("%02X",CanMsgtmp[i].Data[j]));QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(address).arg(CanMsgtmp[i].DataLen).arg(datastr);ui->textEdit_3->append(str);}
}
//处理can4数据
void MainWindow::canAnalyze4(CAN_MSG *CanMsgtmp, char dwRel)
{for(int i = 0 ; i < dwRel ; i++){QString address=QString().sprintf("%08X",CanMsgtmp[i].ID&0x7fffffff);QString datastr=NULL;for(int j=0;j<CanMsgtmp[i].DataLen;j++)datastr.append(QString().sprintf("%02X",CanMsgtmp[i].Data[j]));QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(address).arg(CanMsgtmp[i].DataLen).arg(datastr);ui->textEdit_4->append(str);}
}

 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include "common.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();protected:private slots://CAN12 linux自带的socketcanvoid sendcan12(int v);void stopcan();void startcan(int v);void msg1(QString addr, int num, QString data);void msg2(QString addr, int num, QString data);//CAN34 USB扩展图莫斯canvoid sendcan3();void sendcan4();void canAnalyze3(CAN_MSG *CanMsgtmp, char dwRel);void canAnalyze4(CAN_MSG *CanMsgtmp, char dwRel);private:Ui::MainWindow *ui;#ifndef WINDOWSint socket1;struct sockaddr_can addr1;//can总线的地址 同socket编程里面的 socketaddr结构体 用来设置can外设的信息Thread *t1;int socket2;struct sockaddr_can addr2;//can总线的地址 同socket编程里面的 socketaddr结构体 用来设置can外设的信息Thread *t2;
#endifcanRevThread *canThread;};#endif // MAINWINDOW_H

 thread

cpp
#include "thread.h"
#include "mainwindow.h"
Thread::Thread(int s,QObject *parent) :QThread(parent)
{socket  = s;running = true;
}void Thread::run()
{
#ifndef WINDOWS//qDebug()<<"start can receive Thread!";int nbytes;
//    int len;struct can_frame frame;
//    struct sockaddr_can addr;
//    char buf[8];while(running){
//        nbytes=recvfrom(socket,&frame,sizeof(struct can_frame),0,(struct sockaddr *)&addr,(socklen_t*)&len);//接收can数据:方式一
//        if(nbytes>0){
//            memset(buf,0,8);
//            strncpy(buf,(char*)frame.data,8);
//            //emit message(&addr,&len);
//             printf("id=%x,len=%d\n",(struct sockaddr *)&addr,(socklen_t*)&len);
//        }//接收can数据:方式二nbytes = read(socket, &frame, sizeof(frame)); //接收报文if(nbytes > 0){QString address=QString().sprintf("%08X",frame.can_id&0x7fffffff);QString data=NULL;for(int i=0;i<frame.can_dlc;i++)data.append(QString().sprintf("%02X",frame.data[i]));emit message(address,frame.can_dlc,data);
//            printf("iiid=%x,len=%d,data=%x%x%x%x%x%x%x%x\n",frame.can_id&0x7fffffff,frame.can_dlc,frame.data[0],frame.data[1],frame.data[2],frame.data[3],frame.data[4],frame.data[5],frame.data[6],frame.data[7]);}}
#endif
}void Thread::stop()
{running = false;
}h
#ifndef THREAD_H
#define THREAD_H#include <QThread>#ifndef WINDOWS
extern "C" {
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
}
#endif#ifndef PF_CAN
#define PF_CAN 29
#endif#ifndef AF_CAN
#define AF_CAN PF_CAN
#endifclass Thread : public QThread
{Q_OBJECT
public:explicit Thread(int s,QObject *parent = 0);signals:void message(QString addr,int num,QString data);
public slots:void run();void stop();private:int socket;bool running;};#endif // THREAD_H

 usbcanthread

cpp
#include "canrevthread.h"
#include <QMessageBox>canRevThread::canRevThread( QObject *parent):QThread(parent)
{DevHandle=0x04ff;stopped = 1;bool state;int ret;int DevHdle[10];//扫描查找设备ret = USB_ScanDevice(DevHdle);if(ret <= 0){qDebug()<<QString().sprintf("No device connected!");stopped=0;return;}else{qDebug()<<"handle:"<<DevHdle[0];}//打开设备DevHandle=DevHdle[0];state = USB_OpenDevice(DevHandle);if(!state){qDebug()<<QString().sprintf("Open device error!");stopped=0;return;}//初始化配置CANCAN_INIT_CONFIG CANConfig;// CANConfig.CAN_Mode = 1;//环回模式CANConfig.CAN_Mode = 0;//正常模式CANConfig.CAN_ABOM = 0;//禁止自动离线CANConfig.CAN_NART = 1;//禁止报文重传CANConfig.CAN_RFLM = 0;//FIFO满之后覆盖旧报文CANConfig.CAN_TXFP = 1;//发送请求决定发送顺序//配置波特率,波特率 = 42M/(BRP*(SJW+BS1+BS2))//can通信波特率500kCANConfig.CAN_BRP = 4;//4CANConfig.CAN_BS1 = 16;//16CANConfig.CAN_BS2 = 4;//4CANConfig.CAN_SJW = 1;//1CANConfig.CAN_Mode |= 0x80; //使能接入内部终端电阻ret = CAN_Init(DevHandle,0,&CANConfig);if(ret != CAN_SUCCESS){qDebug()<<QString().sprintf("Config CAN 3 failed!");stopped=0;return;}else{qDebug()<<QString().sprintf("Config CAN 3 Success!");}ret = CAN_Init(DevHandle,1,&CANConfig);if(ret != CAN_SUCCESS){qDebug()<<QString().sprintf("Config CAN 4 failed!");stopped=0;return;}else{qDebug()<<QString().sprintf("Config CAN 4 Success!");}//配置过滤器,必须配置,否则可能无法收到数据CAN_FILTER_CONFIG CANFilter;CANFilter.Enable = 1;CANFilter.ExtFrame = 0; //过滤的帧类型标志,为1 代表要过滤的为扩展帧,为0 代表要过滤的为标准帧。CANFilter.FilterIndex = 0;CANFilter.FilterMode = 0;CANFilter.MASK_IDE = 0;CANFilter.MASK_RTR = 0;CANFilter.MASK_Std_Ext = 0;CAN_Filter_Init(DevHandle,0,&CANFilter);CAN_Filter_Init(DevHandle,1,&CANFilter);}
canRevThread::~canRevThread()
{stopped = 0; requestInterruption();quit();wait();USB_CloseDevice(DevHandle);
}void canRevThread::sendcanData(uchar index,CAN_MSG &CanD)
{int SendedNum = CAN_SendMsg(DevHandle,index,&CanD,1);if(SendedNum <= 0){
//        qDebug()<<QString().sprintf("CAN1 send FAIL %1",SendedNum);}
}
void canRevThread::run()
{   CAN_MSG CanMsgBuffer1[100],CanMsgBuffer2[100];//最大支持100帧char CanNum1=0;char CanNum2=0;while(stopped){CanNum1 = CAN_GetMsg(DevHandle,0,CanMsgBuffer1);CanNum2 = CAN_GetMsg(DevHandle,1,CanMsgBuffer2);if(CanNum1 > 0){emit threadRev1(CanMsgBuffer1,CanNum1);}if(CanNum2 > 0){emit threadRev2(CanMsgBuffer2,CanNum2);}msleep(5);}
}
void canRevThread::stopThread()
{stopped = 0;
}h
#ifndef CANREVTHREAD_H
#define CANREVTHREAD_H#include <QThread>#include <QString>#include <QDebug>
#include <QtCore/qglobal.h>
//#define OS_UNIX
#include "usb_device.h"
#include "usb2can.h"
#if defined(CANTHREAD_COMPILE_LIBRARY)
#  define CANTHREAD_LIB_DECL Q_DECL_EXPORT
#elif defined(CANTHREAD_USE_LIBRARY)
#  define CANTHREAD_LIB_DECL Q_DECL_IMPORT
#else
#  define CANTHREAD_LIB_DECL
#endifclass CANTHREAD_LIB_DECL canRevThread: public QThread
{Q_OBJECT
signals:void threadRev1(CAN_MSG *data,char dwRel);void threadRev2(CAN_MSG *data,char dwRel);public:canRevThread(QObject *parent);~canRevThread();void sendcanData(uchar index,CAN_MSG &CanD);void run();void stopThread();
private:int stopped;int DevHandle;
};
#endif

pro

QT       += core gui sql network printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = RK3588porttest
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
DEPENDPATH += .
INCLUDEPATH += .# Input
HEADERS += \mainwindow.h \common.h \CustomWidget/Thread/thread.h \CustomWidget/usbcanthread/canrevthread.h \CustomWidget/usbcanthread/usb_device.h \CustomWidget/usbcanthread/usb2can.hSOURCES += \main.cpp \mainwindow.cpp \CustomWidget/Thread/thread.cpp \CustomWidget/usbcanthread/canrevthread.cppFORMS += \mainwindow.uiCONFIG += mobility
MOBILITY =win32{message($$QT_ARCH)contains(QT_ARCH, i386) {LIBS += -L$$PWD/CustomWidget/usbcanthread/window/ -lUSB2XXX} else {}
}unix:!macx{message($$QMAKE_HOST.arch)unix:contains(QMAKE_HOST.arch, x86_64){
#        LIBS += -L$$PWD/CustomWidget/usbcanthread/linux-A40i/ -lUSB2XXXLIBS += -L$$PWD/CustomWidget/usbcanthread/linux-RK3588/ -lUSB2XXX -lusb-1.0}unix:contains(QMAKE_HOST.arch, x86){}unix:contains(QMAKE_HOST.arch, aarch64){}unix:contains(QMAKE_HOST.arch, armv7){}unix:contains(QMAKE_HOST.arch, mips64){}
}win32: DEFINES += WINDOWS
!win32: DEFINES += OS_UNIX

前两路2是调用系统自带的CAN,用socketcan,可以参考我A40i帖子中的一个CAN文章

后两路CAN是其他厂家的一个USB转CAN模块,需要匹配相关的驱动,与厂家要驱动文件,引用,可能需要重新根据系统编译一下libusb-1.0.so,才能在交叉编译环境中编译通过

3.背光测试程序(弥补系统pwm匹配异常)

麒麟系统连接edp或mipi屏幕时,会出现pwm不受控现象,麒麟系统与硬件没有完成适配兼容,因为在系统设置中调节亮度不好使

下面通过第三方软件或其他方法尝试解决此问题

1第三方软件方式

未找到合适工具,最终通过自己写程序修改亮度

2自写脚本定时设置亮度方式。

命令参考手册的亮度设置章节

ls /sys/class/backlight

cat /sys/class/backlight/backlight-edp1/brightness

echo 0 > /sys/class/backlight/backlight-edp1/brightness

echo 125 > /sys/class/backlight/backlight-edp1/brightness

echo 255 > /sys/class/backlight/backlight-edp1/brightness

写了一个test_backlight测试程序,当检测到亮度为0时自动设置亮度信息为上次配置的

缺点是会出现一下黑屏,闪一下

最佳解决方式是后期更换稳定系统

后续测试高版本的linux源码尝试

#include "mainwindow.h"
#include <QVBoxLayout>
#include <QFile>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), currentBrightness(200)
{// 初始化滑动条和标签brightnessSlider = new QSlider(Qt::Horizontal, this);brightnessSlider->setRange(0, 255);brightnessSlider->setValue(currentBrightness);brightnessLabel = new QLabel("亮度: " + QString::number(currentBrightness), this);brightnessLabel->setFont(QFont("黑体",50));// 布局QWidget *centralWidget = new QWidget(this);centralWidget->setMinimumSize(500,300);QVBoxLayout *layout = new QVBoxLayout(centralWidget);layout->addWidget(brightnessLabel);layout->addWidget(brightnessSlider);centralWidget->setLayout(layout);setCentralWidget(centralWidget);// 连接滑动条信号connect(brightnessSlider, &QSlider::valueChanged, this, &MainWindow::onSliderValueChanged);// 初始化定时器brightnessTimer = new QTimer(this);connect(brightnessTimer, &QTimer::timeout, this, &MainWindow::checkAndRestoreBrightness);brightnessTimer->start(1000); // 每1s检查一次// 初始设置亮度setBrightness(currentBrightness);
}MainWindow::~MainWindow()
{delete brightnessSlider;delete brightnessLabel;delete brightnessTimer;
}void MainWindow::onSliderValueChanged(int value)
{currentBrightness = value;brightnessLabel->setText("亮度: " + QString::number(currentBrightness));setBrightness(currentBrightness);
}void MainWindow::checkAndRestoreBrightness()
{int actualBrightness = getBrightness();if (actualBrightness == 0) {qDebug() << "亮度被重置为 0,恢复为" << currentBrightness;setBrightness(currentBrightness);}
}void MainWindow::setBrightness(int value)
{QFile brightnessFile("/sys/class/backlight/backlight-edp1/brightness");if (brightnessFile.open(QIODevice::WriteOnly)) {brightnessFile.write(QString::number(value).toUtf8());brightnessFile.close();} else {qWarning() << "无法设置亮度,请检查权限或路径。";}
}int MainWindow::getBrightness()
{QFile brightnessFile("/sys/class/backlight/backlight-edp1/brightness");if (brightnessFile.open(QIODevice::ReadOnly)) {QString brightnessValue = brightnessFile.readAll().trimmed();brightnessFile.close();return brightnessValue.toInt();} else {qWarning() << "无法读取亮度,请检查权限或路径。";return -1;}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QSlider>
#include <QLabel>
#include <QTimer>class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onSliderValueChanged(int value);void checkAndRestoreBrightness();private:QSlider *brightnessSlider;QLabel *brightnessLabel;QTimer *brightnessTimer;int currentBrightness;void setBrightness(int value);int getBrightness();
};#endif // MAINWINDOW_H

4.电量获取程序(弥补底系统版本不支持电池管理)

麒麟系统V10 2303默认不支持电源管理功能,没有电池图标右下角的显示

使用xx电源模块在国防版麒麟系统可以显示电量信息,但是国防版系统镜像不好用缺图标

最终还是使用2303系统,需要自己通过软件获取电量信息

等以后有了2403系统,就没有这个问题了

方法:

upower -e

upower -i /org/freedesktop/UPower/devices/ups_hiddev0

后续写了一个demo程序 test_power,用于监测电源模块电量信息,等以后写程序可以集成在程序之中

#include "mainwindow.h"
#include <QApplication>
#include <QMenu>
#include <QAction>
#include <QProcess>
#include <QMessageBox>
#include <QDebug>
#include <QPainter>
#include <QFontMetrics>
#include <QVBoxLayout>
#include <QWidget>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), isCharging(false), batteryPercentage(0), timeToEmpty(0)
{// 创建托盘图标createTrayIcon();// 创建桌面 UIQWidget *centralWidget = new QWidget(this);QVBoxLayout *layout = new QVBoxLayout(centralWidget);percentageLabel = new QLabel("电量: 未知", centralWidget);timeToEmptyLabel = new QLabel("剩余时长: 未知", centralWidget);layout->addWidget(percentageLabel);layout->addWidget(timeToEmptyLabel);centralWidget->setLayout(layout);setCentralWidget(centralWidget);
centralWidget->show();// 定时器,每分钟更新一次电量信息timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &MainWindow::updateBatteryStatus);timer->start(60000); // 每分钟更新一次// 初始更新updateBatteryStatus();
}MainWindow::~MainWindow()
{delete trayIcon;delete timer;
}void MainWindow::createTrayIcon()
{trayIcon = new QSystemTrayIcon(this);updateTrayIcon(); // 初始化图标QMenu *menu = new QMenu(this);QAction *quitAction = new QAction("退出", this);connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);menu->addAction(quitAction);trayIcon->setContextMenu(menu);trayIcon->show();connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated);
}void MainWindow::updateBatteryStatus()
{QProcess process;process.start("upower -i /org/freedesktop/UPower/devices/ups_hiddev0");process.waitForFinished();QString output = process.readAllStandardOutput();parseBatteryStatus(output);// 更新托盘图标和桌面 UIupdateTrayIcon();updateDesktopUI();
}void MainWindow::parseBatteryStatus(const QString &output)
{QStringList lines = output.split("\n");for (const QString &line : lines) {if (line.contains("percentage")) {batteryPercentage = line.split(":").last().trimmed().replace("%", "").toInt();}if (line.contains("time to empty")) {timeToEmpty = line.split(":").last().trimmed().replace("hours", "").toDouble();// 如果剩余时长为 18.2 小时,则认为充电器接入isCharging = (timeToEmpty == 18.2);}}
}void MainWindow::updateTrayIcon()
{// 创建一个 64x64 的画布QPixmap pixmap(64, 64);pixmap.fill(Qt::transparent); // 透明背景QPainter painter(&pixmap);painter.setRenderHint(QPainter::Antialiasing);// 绘制电池外框painter.setPen(Qt::white);painter.setBrush(Qt::transparent);painter.drawRect(15, 20, 34, 20); // 电池外框// 绘制电池正极painter.drawRect(49, 25, 4, 10);// 绘制电量填充int fillWidth = static_cast<int>(32 * (batteryPercentage / 100.0));painter.setBrush(Qt::green);painter.drawRect(16, 21, fillWidth, 18);// 绘制百分比文字painter.setPen(Qt::white);QFont font = painter.font();font.setPixelSize(16); // 增大字体大小painter.setFont(font);// 计算文字居中位置QFontMetrics metrics(font);QString text = QString::number(batteryPercentage) + "%";int textWidth = metrics.width(text); // 使用 width 替代 horizontalAdvanceint textHeight = metrics.height();int textX = (pixmap.width() - textWidth) / 2;int textY = (pixmap.height() + textHeight) / 2;painter.drawText(textX, textY, text);// 如果是充电状态,绘制闪电符号if (isCharging) {QPolygon lightning;lightning << QPoint(32, 10) << QPoint(40, 20) << QPoint(32, 20)<< QPoint(44, 40) << QPoint(32, 30) << QPoint(40, 30);painter.setBrush(Qt::yellow);painter.drawPolygon(lightning);}// 设置托盘图标trayIcon->setIcon(QIcon(pixmap));
}void MainWindow::updateDesktopUI()
{// 更新电量百分比percentageLabel->setText(QString("电量: %1%").arg(batteryPercentage));// 更新剩余使用时长if (isCharging) {timeToEmptyLabel->setText("状态: 充电中");} else {timeToEmptyLabel->setText(QString("剩余时长: %1 小时").arg(timeToEmpty));}
}void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
{if (reason == QSystemTrayIcon::Trigger) {updateBatteryStatus();}
}

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QPixmap>
#include <QPainter>
#include <QLabel>class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void updateBatteryStatus();void iconActivated(QSystemTrayIcon::ActivationReason reason);private:QSystemTrayIcon *trayIcon;QTimer *timer;bool isCharging;int batteryPercentage;double timeToEmpty; // 剩余使用时长(小时)QLabel *percentageLabel;QLabel *timeToEmptyLabel;void createTrayIcon();void updateTrayIcon();void updateDesktopUI();void parseBatteryStatus(const QString &output);
};#endif // MAINWINDOW_H
5.GPIO测试程序控制状态led灯
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);static bool ledflag=false;
#ifdef WINDOWS#else//开机指令初始化指示灯gpiosystem("echo 24 > /sys/class/gpio/export");//led1system("echo out > /sys/class/gpio/gpio24/direction");system("echo 27 > /sys/class/gpio/export");//led2system("echo out > /sys/class/gpio/gpio27/direction");QTimer *timeled=new QTimer(this);timeled->start(500);connect(timeled,&QTimer::timeout,[=](){ledflag=!ledflag;if(ledflag){system("echo 0 > /sys/class/gpio/gpio24/value");system("echo 1 > /sys/class/gpio/gpio27/value");ui->label->setStyleSheet("background-color: rgb(0, 255, 0);");ui->label_2->setStyleSheet("background-color: rgb(255, 0, 0);");}else{system("echo 1 > /sys/class/gpio/gpio24/value");system("echo 0 > /sys/class/gpio/gpio27/value");ui->label->setStyleSheet("background-color: rgb(255, 0, 0);");ui->label_2->setStyleSheet("background-color: rgb(0, 255, 0);");}qDebug()<<"ledflag:"<<QString::number(ledflag);});//绑定定时分析数据函数槽
#endifqDebug()<<"ledflag:"<<QString::number(ledflag);ui->label->setStyleSheet("background-color: rgb(0, 255, 0);");ui->label_2->setStyleSheet("background-color: rgb(255, 0, 0);");}
MainWindow::~MainWindow()
{delete ui;
}
6.时间测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDate>
#include <QTime>
#include <QPalette>
#include <stdio.h>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);//setWindowState(Qt::WindowMaximized);setWindowFlags(Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);QPalette pal;pal.setColor(QPalette::Text,QColor(255,0,0));ui->year->setPalette(pal);ui->month->setPalette(pal);ui->day->setPalette(pal);ui->hour->setPalette(pal);ui->minute->setPalette(pal);ui->second->setPalette(pal);QDate d = QDate::currentDate();QTime t = QTime::currentTime();ui->year->setValue(d.year());ui->month->setValue(d.month());ui->day->setValue(d.day());ui->hour->setValue(t.hour());ui->minute->setValue(t.minute());ui->second->setValue(t.second());ui->year->setEnabled(false);ui->month->setEnabled(false);ui->day->setEnabled(false);ui->hour->setEnabled(false);ui->minute->setEnabled(false);ui->second->setEnabled(false);timer.start(1000,this);connect(ui->exitBtn, &QPushButton::clicked, this, [=](){close();		    });
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::timerEvent(QTimerEvent *event)
{QDate d = QDate::currentDate();QTime t = QTime::currentTime();if(ui->set->text()=="set"){ui->year->setValue(d.year());ui->month->setValue(d.month());ui->day->setValue(d.day());ui->hour->setValue(t.hour());ui->minute->setValue(t.minute());ui->second->setValue(t.second());}QWidget::timerEvent(event);
}void MainWindow::on_set_clicked()
{if(ui->set->text()=="set"){ui->set->setText("save");ui->year->setEnabled(true);ui->month->setEnabled(true);ui->day->setEnabled(true);ui->hour->setEnabled(true);ui->minute->setEnabled(true);ui->second->setEnabled(true);timer.stop();}else{char buf[128];ui->set->setText("set");memset(buf,0,128);sprintf(buf,"date -s '%4d-%02d-%02d %02d:%02d:%02d'",ui->year->text().toInt(),ui->month->text().toInt(),ui->day->text().toInt(),ui->hour->text().toInt(),ui->minute->text().toInt(),ui->second->text().toInt());system(buf);system("hwclock -w");ui->year->setEnabled(false);ui->month->setEnabled(false);ui->day->setEnabled(false);ui->hour->setEnabled(false);ui->minute->setEnabled(false);ui->second->setEnabled(false);timer.start(1000,this);}
}void MainWindow::closeEvent(QCloseEvent *)
{//system("killall matrix_gui");//system("/etc/init.d/qt.sh");exit(0);
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QBasicTimer>
#include <QTimerEvent>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();
protected:void timerEvent(QTimerEvent *event);void closeEvent(QCloseEvent *);
private slots:void on_set_clicked();private:Ui::MainWindow *ui;QBasicTimer timer;
};#endif // MAINWINDOW_H

7.redis通信测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);// 连接到 Redis 服务器,用于发布命令publishContext = redisConnect("127.0.0.1", 6379);if (publishContext == NULL || publishContext->err) {if (publishContext) {qDebug() << "Error: " << publishContext->errstr;ui->textEdit->setText(QString("Error: %1").arg(publishContext->errstr));redisFree(publishContext);} else {qDebug() << "Can't allocate redis context for publishing";ui->textEdit->setText("Can't allocate redis context for publishing");}return;}else {ui->textEdit->append("redis 发布 connect successful");}// 连接到 Redis 服务器,用于订阅命令subscribeContext = redisConnect("127.0.0.1", 6379);if (subscribeContext == NULL || subscribeContext->err) {if (subscribeContext) {qDebug() << "Error: " << subscribeContext->errstr;ui->textEdit->setText(QString("Error: %1").arg(subscribeContext->errstr));redisFree(subscribeContext);} else {qDebug() << "Can't allocate redis context for subscribing";ui->textEdit->setText("Can't allocate redis context for subscribing");}return;}else {ui->textEdit->append("redis 订阅 connect successful");}// 订阅结果频道if (subscribeContext && !subscribeContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(subscribeContext, "SUBSCRIBE numpy_result pandas_result tensorflow_result sklearn_result matplotlib_result"));if (reply) {freeReplyObject(reply);}}// 创建并启动 Redis 订阅线程subscriberThread = new RedisSubscriberThread(subscribeContext, this);connect(subscriberThread, &RedisSubscriberThread::messageReceived, this, [this](const QString &channel, const QString &message) {ui->textEdit->append(channel + ": " + message);});subscriberThread->start();
}MainWindow::~MainWindow()
{if (publishContext) {redisFree(publishContext);}if (subscribeContext) {redisFree(subscribeContext);}if (subscriberThread) {subscriberThread->quit();subscriberThread->wait();}delete ui;
}void MainWindow::on_pushButton_clicked()
{if (publishContext && !publishContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH numpy_command run_numpy"));if (reply) {if (reply->type == REDIS_REPLY_ERROR) {qDebug() << "Error publishing to Redis: " << reply->str;} else {qDebug() << "Message published successfully to numpy_command";}freeReplyObject(reply);} else {qDebug() << "Error: Failed to execute Redis command";}} else {qDebug() << "Redis publish context is invalid";}
}void MainWindow::on_pushButton_2_clicked()
{if (publishContext && !publishContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH pandas_command run_pandas"));if (reply) {if (reply->type == REDIS_REPLY_ERROR) {qDebug() << "Error publishing to Redis: " << reply->str;} else {qDebug() << "Message published successfully to pandas_command";}freeReplyObject(reply);} else {qDebug() << "Error: Failed to execute Redis command";}} else {qDebug() << "Redis publish context is invalid";}
}void MainWindow::on_pushButton_3_clicked()
{if (publishContext && !publishContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH tensorflow_command run_tensorflow"));if (reply) {if (reply->type == REDIS_REPLY_ERROR) {qDebug() << "Error publishing to Redis: " << reply->str;} else {qDebug() << "Message published successfully to tensorflow_command";}freeReplyObject(reply);} else {qDebug() << "Error: Failed to execute Redis command";}} else {qDebug() << "Redis publish context is invalid";}
}void MainWindow::on_pushButton_4_clicked()
{if (publishContext && !publishContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH sklearn_command run_sklearn"));if (reply) {if (reply->type == REDIS_REPLY_ERROR) {qDebug() << "Error publishing to Redis: " << reply->str;} else {qDebug() << "Message published successfully to sklearn_command";}freeReplyObject(reply);} else {qDebug() << "Error: Failed to execute Redis command";}} else {qDebug() << "Redis publish context is invalid";}
}void MainWindow::on_pushButton_5_clicked()
{if (publishContext && !publishContext->err) {redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH matplotlib_command run_matplotlib"));if (reply) {if (reply->type == REDIS_REPLY_ERROR) {qDebug() << "Error publishing to Redis: " << reply->str;} else {qDebug() << "Message published successfully to matplotlib_command";}freeReplyObject(reply);} else {qDebug() << "Error: Failed to execute Redis command";}} else {qDebug() << "Redis publish context is invalid";}
}void MainWindow::on_pushButton_6_clicked()
{ui->textEdit->clear();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QMetaObject>
#include "QtHiRedis/hiredis.h" // 包含 hiredis 头文件// 定义一个新的线程类来处理 Redis 订阅
class RedisSubscriberThread : public QThread {Q_OBJECT
public:RedisSubscriberThread(redisContext *context, QObject *parent = nullptr): QThread(parent), subscribeContext(context) {}signals:void messageReceived(const QString &channel, const QString &message);protected:void run() override {if (subscribeContext && !subscribeContext->err) {redisReply *reply;while (true) {int retval = redisGetReply(subscribeContext, (void**)&reply);if (retval == REDIS_OK && reply != NULL && reply->type == REDIS_REPLY_ARRAY && reply->elements == 3) {QString messageType = QString::fromUtf8(reply->element[0]->str);if (messageType == "message") {QString channel = QString::fromUtf8(reply->element[1]->str);QString result = QString::fromUtf8(reply->element[2]->str);emit messageReceived(channel, result);}}if (reply) {freeReplyObject(reply);}}}}private:redisContext *subscribeContext;
};namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();void on_pushButton_6_clicked();private:Ui::MainWindow *ui;redisContext *publishContext; // 使用 hiredis 的上下文redisContext *subscribeContext; // 使用 hiredis 的上下文RedisSubscriberThread *subscriberThread;
};#endif // MAINWINDOW_H

 

附件太多了,自己下载开源的,或者下载我的全套资源吧

文章参考链接

程序下载链接

8.温度、CPU主频测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);#ifdef WINDOWSm_path=qApp->applicationDirPath();
#elsem_path="/media/root/sata";//sata是更改挂载点后的文件名,默认是UUID,没法通过程序去识别每个设备的硬盘
#endif///timer定时器初始化,3秒进行一次数据分析,不管数据是否接收,定时分析数据以UDP形式发送到指定目标IPQTimer *time1=new QTimer(this);time1->start(3000);connect(time1,&QTimer::timeout,[=](){AnalyseData();});//绑定定时分析数据函数槽}
MainWindow::~MainWindow()
{delete ui;
}///******************************************************************定时分析数据**************************************************************///
//在时钟和硬盘挂载正常的情况下分析内存容量是否充足,大于80%要删除到60%以下,最少保留当天日期数据不可删除
//分析数据采集盒状态:时钟状态、时间、固态硬盘挂载状态、固态硬盘容量、CPU温度、CPU主频、采集盒版本信息,将数据打包放入待发送缓存中
//分析整车全部系统状态:xxx,将数据打包放入待发送缓存中
//
void MainWindow::AnalyseData()
{
///分析硬盘容量ui->textEdit->clear();qDebug()<<"\r\n";qDebug()<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");ui->textEdit->append(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));qDebug()<<"/*****************check disk used******************/";ui->textEdit->append("/*****************check disk used******************/");if(QFile::exists(m_path)){//判断硬盘状态是否正常,异常后出正常也不给予正常状态,只要出现判断不到即报错,单次即一直触发,不消除故障m_mSATAstatus=true;//mSATA挂载正常QTime get_disk_usetime;//记录查询日志数据列表消耗时间get_disk_usetime.start();//计算mSATA_size,mSATA_used,mSATA_persentQStorageInfo storage = QStorageInfo::root();storage.refresh();  //获得最新磁盘信息storage.device();storage.setPath(m_path);mSATA_size=storage.bytesTotal()/(1024*1024);//单位MBytemSATA_used=mSATA_size-storage.bytesFree()/(1024*1024);mSATA_persent=mSATA_used*100/mSATA_size;qDebug()<<"mSATA used:"<<getsize(mSATA_used)<<",mSATA allsize:"<<getsize(mSATA_size);qDebug()<<"mSATA use persent is "<<QString::number(mSATA_persent)<<"%,get mSATA used persent usetime:"<<QString::number(get_disk_usetime.elapsed())<<"ms";ui->textEdit->append("mSATA used:"+getsize(mSATA_used)+",mSATA allsize:"+getsize(mSATA_size));ui->textEdit->append("mSATA use persent is "+QString::number(mSATA_persent)+"%,get mSATA used persent usetime:"+QString::number(get_disk_usetime.elapsed())+"ms");}else{qDebug()<<"mSATA err!";ui->textEdit->append("mSATA err!");m_mSATAstatus=false;//赋值硬盘错误状态}
///获取数据采集盒状态QString m_freq0,m_freq4,m_temp;//本机工作频率和温度QString m_cpu0,m_cpu4;
#ifndef WINDOWSQFile file("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq");//获取cpu工作主频if (file.open(QIODevice::ReadOnly | QIODevice::Text)){m_freq0 = file.readLine();file.close();}QFile file2("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq");//获取cpu工作主频if (file2.open(QIODevice::ReadOnly | QIODevice::Text)){m_freq4 = file2.readLine();file2.close();}QFile file1("/sys/class/thermal/thermal_zone0/temp");//获取cpu工作温度if (file1.open(QIODevice::ReadOnly | QIODevice::Text)){m_temp = file1.readLine();file1.close();}QFile file3("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies");//获取cpu主频范围if (file3.open(QIODevice::ReadOnly | QIODevice::Text)){m_cpu0 = file3.readLine();file3.close();}QFile file4("/sys/devices/system/cpu/cpu4/cpufreq/scaling_available_frequencies");//获取cpu主频范围if (file4.open(QIODevice::ReadOnly | QIODevice::Text)){m_cpu4 = file4.readLine();file4.close();}
#elsem_freq0="99999";m_freq4="99999";m_temp="99.99";m_cpu0="";m_cpu4="";
#endifqDebug()<<"/*****************check CPU used******************/";qDebug()<<tr("cpu0 range %1").arg(m_cpu0);qDebug()<<tr("cpu4 range %1").arg(m_cpu4);qDebug()<<tr("cpu0 freq %1,cpu4 freq %2,now temp %3").arg(m_freq0).arg(m_freq4).arg(m_temp);qDebug()<<"/*****************check end******************/";ui->textEdit->append("/*****************check CPU used******************/");ui->textEdit->append(tr("cpu0 range %1").arg(m_cpu0));ui->textEdit->append(tr("cpu4 range %1").arg(m_cpu4));ui->textEdit->append(tr("cpu0 freq %1,cpu4 freq %2,now temp %3").arg(m_freq0).arg(m_freq4).arg(m_temp));ui->textEdit->append("/*****************check end******************/");
}
QString MainWindow::getsize(qint64 m_allsizie)
{QString fileSize;if (m_allsizie >= 0 && m_allsizie < 1024){fileSize = QString::number(m_allsizie) + "Byte";}else if (m_allsizie >= 1024 && m_allsizie < 1024 * 1024){fileSize = QString::number(m_allsizie / 1024.0, 'f', 2) + "KB";}else if (m_allsizie >= 1024 * 1024 && m_allsizie < 1024 * 1024 * 1024){fileSize = QString::number(m_allsizie / 1024 / 1024.0, 'f', 2) + "MB";}else if (m_allsizie >= 1024 * 1024 * 1024){fileSize = QString::number(m_allsizie / 1024 / 1024 / 1024.0, 'f', 2) + "GB";}return fileSize;
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include "header.h"namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();protected:private slots:void AnalyseData();QString getsize(qint64 m_allsizie);
private:Ui::MainWindow *ui;bool m_mSATAstatus=false;//固态硬盘是否正常,不正常不能建立文件夹存储数据QString m_path;//记录当前存储文件的路径,在WINDOWS的路径还是在linux中的固态硬盘中路径qint64 mSATA_size,mSATA_used,mSATA_persent;//mSATA硬盘总容量,已经使用容量,容量使用百分比};#endif // MAINWINDOW_H

9.msata挂载稳定性测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);//读取配置信息QString line_config;QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");if(file_config.open(QIODevice::ReadOnly|QIODevice::Text)){while(!file_config.atEnd()){line_config=file_config.readLine();}file_config.close();}else{file_config.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_config);in<<"0";line_config="0";file_config.close();}qDebug()<<"config:"<<line_config;ui->spinBox->setValue(line_config.toInt());if(line_config=="0")ui->checkBox->setChecked(false);else ui->checkBox->setChecked(true);//读取配置信息QString line_path;QFile file_path(qApp->applicationDirPath()+"/test_msata_path.txt");if(file_path.open(QIODevice::ReadOnly|QIODevice::Text)){while(!file_path.atEnd()){line_path=file_path.readLine();}file_path.close();}else{file_path.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_path);in<<"/dev/sda5";line_path="/dev/sda5";file_path.close();}qDebug()<<"path:"<<line_path;ui->lineEdit->setText(line_path);//读取配置信息QString line_history;QFile file_history(qApp->applicationDirPath()+"/test_msata_history.txt");if(file_history.open(QIODevice::ReadOnly|QIODevice::Text)){while(!file_history.atEnd()){line_history=file_history.readLine().replace("\n","");qDebug()<<"history:"<<line_history;if(line_history.contains("yes")){QTextCharFormat fmt;fmt.setForeground(Qt::green);ui->textEdit->setCurrentCharFormat(fmt);ui->textEdit->append(line_history);}else if(line_history.contains("err")){QTextCharFormat fmt;fmt.setForeground(Qt::red);ui->textEdit->setCurrentCharFormat(fmt);ui->textEdit->append(line_history);}}file_history.close();}QTimer *time1=new QTimer(this);time1->start(2000);//20sconnect(time1,&QTimer::timeout,[=](){AnalyseData();});//绑定定时分析数据函数槽}
MainWindow::~MainWindow()
{delete ui;
}///******************************************************************定时分析数据**************************************************************///void MainWindow::AnalyseData()
{
///获取数据采集盒状态QString m_temp="66666";//本机工作频率和温度QFile file1("/sys/class/thermal/thermal_zone0/temp");//获取cpu工作温度if (file1.open(QIODevice::ReadOnly | QIODevice::Text)){m_temp = file1.readLine();file1.close();}m_temp = QString::number((double)m_temp.toInt()/1000,'f',2);if(ui->checkBox->isChecked()){int num=ui->spinBox->value();if(num>0){ui->spinBox->setValue(num-1);QFile file(ui->lineEdit->text());if(file.exists()) {// 文件存在QTextCharFormat fmt;fmt.setForeground(Qt::green);ui->textEdit->setCurrentCharFormat(fmt);ui->textEdit->append(QString("%1,msata fstab yes,CPU temp %2,has %3").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(m_temp).arg(ui->spinBox->value()));}else {// 文件不存在QTextCharFormat fmt;fmt.setForeground(Qt::red);ui->textEdit->setCurrentCharFormat(fmt);ui->textEdit->append(QString("%1,msata fstab err,CPU temp %2,has %3").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(m_temp).arg(ui->spinBox->value()));}QFile file_path(qApp->applicationDirPath()+"/test_msata_history.txt");file_path.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_path);in<<ui->textEdit->toPlainText();file_path.close();qDebug()<<"重启";system("reboot");}
//        else
//            ui->textEdit->append("测试完毕!");}
}
//按键点击事件
void MainWindow::on_checkBox_clicked()
{
//    QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");
//    file_config.open(QIODevice::WriteOnly|QIODevice::Text);
//    QTextStream in(&file_config);
//    QString res;
//    if(ui->checkBox->isChecked()==false)
//        res="0";
//    in<<res;
//    file_config.close();
}
void MainWindow::on_pushButton_clicked()
{QFile file_path(qApp->applicationDirPath()+"/test_msata_path.txt");file_path.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_path);in<<ui->lineEdit->text();file_path.close();
}
void MainWindow::on_pushButton_2_clicked()
{QFile file_path(qApp->applicationDirPath()+"/test_msata_history.txt");file_path.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_path);in<<"";file_path.close();ui->textEdit->clear();
}void MainWindow::on_spinBox_valueChanged(int arg1)
{QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");file_config.open(QIODevice::WriteOnly|QIODevice::Text);QTextStream in(&file_config);in<<QString::number(arg1);file_config.close();
}

四、结语

未完待续。。。

可以用AI生成,很多平台都可以,描述清楚就可以对症下药,用起来

相关文章:

RK3588使用笔记:ubuntu/麒麟系统功能测试程序

一、前言 本编文章记录在使用嵌入式系统中的一些功能测试demo程序&#xff0c;大部分都是AI写的&#xff0c;哈哈哈&#xff0c;确实很有帮助&#xff0c;但是得根据自身设备实际情况和知道如何问AI&#xff0c;才能得出你想要的结果&#xff0c;本文就记录一些ubuntu/麒麟系统…...

Unity中优化绘制调用整理

DrawCall 指的是 CPU 向 GPU 发送渲染指令的过程&#xff0c;在 Unity 中&#xff0c;每次渲染一个网格时&#xff0c;CPU 都需要向 GPU 发送一系列的渲染指令&#xff0c;这个过程被称为一次绘制调用&#xff08;Draw Call&#xff09;。 1.GPU实例化 使用&#xff1a; 2.绘…...

ubuntu开启黑屏现象解决

文章目录 前言一、问题描述二、解决方案1. 检查显卡驱动解决步骤&#xff1a; 2. 修复 GRUB 配置解决步骤&#xff1a; 3. 使用恢复模式解决步骤&#xff1a; 三、验证与总结 前言 在使用 Ubuntu 操作系统时&#xff0c;一些用户可能会遇到开机后屏幕黑屏的现象。这种问题可能…...

深度学习deeplearn3

# Jupyter Notebook魔法命令&#xff0c;用于在Notebook中内联显示图表 %matplotlib inline# 导入NumPy库&#xff0c;用于高效的数值计算 import numpy as np# 从matplotlib_inline库导入backend_inline模块&#xff0c;用于设置图表显示格式 from matplotlib_inline import b…...

Mac强制解锁APP或文件夹

当Mac安装过火绒企业版、云安全访问服务之类的APP需要卸载的时候&#xff0c;会发现需要管理员密码&#xff0c;正常的卸载流程走不下去&#xff0c;直接删除APP&#xff0c;会提示“不能完成此操作&#xff0c;xxx已锁定”的信息&#xff0c;此处就记录一下如何关闭锁定状态&a…...

android开发:zxing-android-embedded竖屏扫描功能

Android 点击按钮调用竖屏二维码扫描 提示&#xff1a;zxing-android-embedded插件已过时&#xff0c;建议更换别的。 场景&#xff1a;Home页面上有个扫描按钮&#xff0c;点击后打开摄像头完成扫描功能&#xff0c;扫描时要求竖屏。 方案&#xff1a;使用zxing-android-embe…...

SQL语句(二)—— DML

目录 一、添加数据 1、给指定字段添加数据 2、给全部字段添加数据 3、批量添加数据 二、修改数据 1、修改数据的具体语法 2、案例分析 3、注意事项 三、删除数据 1、删除数据的具体语法 2、案例 3、注意事项 DML全称是Data Manipulation Language&#xff0c;即数据…...

2.2 路径问题专题:LeetCode 63. 不同路径 II

动态规划解决LeetCode 63题&#xff1a;不同路径 II&#xff08;含障碍物&#xff09; 1. 题目链接 LeetCode 63. 不同路径 II 2. 题目描述 一个机器人位于 m x n 网格的左上角&#xff0c;每次只能向右或向下移动一步。网格中可能存在障碍物&#xff08;标记为 1&#xff…...

Linux系统程序设计:从入门到高级Day02

这一篇 我带大家复习一下&#xff0c;C语言中的文件 那一部分 大家注意 这里的图并非原创 是当时我老师的图片 本片作用主要是 后续会有文件相关操作&#xff0c;这篇帮大家复习C语言文件中的内容 有助于大家后面的理解。 文章中代码大多是图片格式&#xff0c;是因为这是我…...

2025高频面试设计模型总结篇

文章目录 设计模型概念单例模式工厂模式策略模式责任链模式 设计模型概念 设计模式是前人总结的软件设计经验和解决问题的最佳方案&#xff0c;它们为我们提供了一套可复用、易维护、可扩展的设计思路。 &#xff08;1&#xff09;定义&#xff1a; 设计模式是一套经过验证的…...

【LeetCode 热题100】208:实现 Trie (前缀树)(详细解析)(Go语言版)

&#x1f680; 力扣热题 208&#xff1a;实现 Trie (前缀树)&#xff08;详细解析&#xff09; &#x1f4cc; 题目描述 力扣 208. 实现 Trie (前缀树) Trie&#xff08;发音类似 “try”&#xff09;是一种树形数据结构&#xff0c;用于高效地存储和检索字符串集合中的键。实…...

CSS 父类元素的伪类 选择器

父元素的 :hover 状态可以影响子元素的样式。当父元素处于 :hover 状态时&#xff0c;可以通过 CSS 的选择器为子元素设置样式。 .parent:hover .child 这种选择器叫做 后代选择器&#xff08;Descendant Selector&#xff09; &#xff0c;结合了 :hover 伪类。它的作用是&…...

目前来讲 有哪些三维重建算法,哪个算法效果好

三维重建是计算机视觉和图形学的重要研究方向&#xff0c;其算法在不同场景下的效果差异较大。以下是当前主流的三维重建算法及其特点&#xff0c;按技术路线分类整理&#xff1a; ‌1. 传统几何方法‌ &#xff08;1&#xff09;‌结构光&#xff08;Structured Light&#xf…...

快速掌握MCP——Spring AI MCP包教包会

最近几个月AI的发展非常快&#xff0c;各种大模型、智能体、AI名词和技术和框架层出不穷&#xff0c;作为一个业余小红书博主的我最近总刷到MCP这个关键字&#xff0c;看着有点高级我也来学习一下。 1.SpringAI与functionCall简单回顾 前几个月我曾写过两篇关于SpringAI的基础…...

KUKA机器人查看运行日志的方法

对于KUKA机器人的运行日志都是可以查看和导出的&#xff0c;方便查找问题。KUKA机器人的运行日志查看方法如下&#xff1a; 1、在主菜单下&#xff0c;选择【诊断】-【运行日志】-【显示】下打开&#xff1b; 2、显示出之前的机器人运行日志&#xff1b; 3、也可以通过【过滤器…...

MySQL 基础使用指南-MySQL登录与远程登录

MySQL 基础使用指南 1. 登录 MySQL 数据库的命令解析 命令格式&#xff1a; mysql -u用户名 -p密码参数说明&#xff1a; -u&#xff08;user 的缩写&#xff09;&#xff1a;指定登录用户。例如 -uroot 表示以 root 用户登录。-p&#xff08;password 的缩写&#xff09;&a…...

web-ui windows安装与配置

web-ui windows安装与配置 安装然后安装依赖 运行配置 安装 git clone https://github.com/browser-use/web-ui.git先把clone下来 需要有python环境 最好是 Python 3.11 这里就不赘述了 然后安装依赖 pip install -r requirements.txt运行 python webui.py --ip 127.0.0.1 …...

游戏引擎学习第201天

仓库:https://gitee.com/mrxiao_com/2d_game_5 回顾之前的内容&#xff0c;并遇到了一次一阶异常&#xff08;First-Chance Exception&#xff09;。 欢迎来到新一期的开发过程&#xff0c;我们目前正在编写调试接口代码。 当前&#xff0c;我们已经在布局系统上进行了一些工…...

Doris:打破 SQL 方言壁垒,构建统一数据查询生态

在大数据领域&#xff0c;不同的数据库系统往往使用不同的 SQL 方言。这就好比不同地区的人说着不同的语言&#xff0c;给数据分析师和开发人员带来极大的困扰。当企业需要整合多个数据源进行分析时&#xff0c;可能要花费大量时间和精力&#xff0c;在不同的 SQL 语法之间切换…...

github合并多个commit message以及rebase解决文件冲突

深度学习求解PDE相关代码全部在我的仓库添加链接描述&#xff0c;自取 github仓库合并多个commit message 问题描述如下&#xff1a; 第一步&#xff1a;确保自己在对应分支上 比如说现在我要合并issue/108分支的提交记录&#xff0c;使用git log --oneline查看提交记录一…...

【零基础入门unity游戏开发——2D篇】SortingGroup(排序分组)组件

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…...

系统与网络安全------Windows系统安全(5)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 磁盘分区管理 磁盘的分区管理 WinR运行&#xff0c;执行“diskmgmt.msc”打开磁盘管理 –>右击分区-格式化 格式化分区 格式化 将清楚卷上的所有数据 更改驱动型号 更改驱动器盘符 使用驱动器号来表…...

springboot—— Shiro实现认证和授权功能

一、数据库模板设计 在本文中&#xff0c;我们使用RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;模型设计用户&#xff0c;角色和权限间的关系。简单地说&#xff0c;一个用户拥有若干角色&#xff0c;每一个角色拥有若干权限。这样&a…...

牛客 除2问题

除2&#xff01; 贪心堆 让偶数入堆 注意点&#xff1a; 1.判断堆是否为空再进行操作 2. 为了防止超时&#xff0c;我们采取先求和的方式&#xff0c;后面调整之后再减掉&#xff0c;可以节省一次遍历的时间。 3.注意数据范围&#xff0c;要用long long #include<iost…...

Kafka - 消息零丢失实战

Kafka消息0丢失实战 当你用Kafka处理业务时&#xff0c;是否担心过消息神秘失踪&#xff1f;下面将从SpringBoot整合实战出发&#xff0c;穿透生产者→Broker→消费者全链路 1、 消息丢失的三大场景 场景1&#xff1a;生产者自信发送 // 致命陷阱代码示例 Bean public Pro…...

通信算法之256: 无人机Remote ID(远程识别)

Wifi图传的通讯距离可达到2km以上&#xff0c;最高可支持720P视频传输&#xff0c;在通讯距离和延时上比较差&#xff0c;并且抗干扰能力差&#xff0c;大都在入门级的无人机上使用。LightBridge图传技术相比wifi图传&#xff0c;通讯距离最远可以达到7km&#xff0c;最高支持1…...

【C++11】异步编程

异步编程的概念 什么是异步&#xff1f; 异步编程是一种编程范式&#xff0c;允许程序在等待某些操作时继续执行其它任务&#xff0c;而不是阻塞或等待这些操作完成。 异步编程vs同步编程&#xff1f; 在传统的同步编程中&#xff0c;代码按顺序同步执行&#xff0c;每个操作需…...

论文阅读笔记:Denoising Diffusion Implicit Models (4)

0、快速访问 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;1&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;2&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08…...

flux文生图部署笔记

目录 依赖库: 文生图推理代码cpu: cuda版推理: 依赖库: tensorrt安装: pip install nvidia-pyindex # 添加NVIDIA仓库索引 pip install tensorrt 文生图推理代码cpu: import torch from diffusers import FluxPipelinemodel_id = "black-forest-labs/FLUX.1-s…...

UltraScale+系列FPGA实现 IMX214 MIPI 视频解码转HDMI2.0输出,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 MIPI 编解码方案我已有的4K/8K视频处理解决方案 3、详细设计方案设计框图硬件设计架构FPGA开发板IMX214 摄像头MIPI D-PHYMIPI CSI-2 RX SubsystemBayer…...