• Qt实现PSD信号接收程序


    项目描述

    利用窗口程序实现对PSD激光接收装置进行指令接收/发送。当成功连接装置后,能够通过设置绝对零位来校正坐标,点击信息获取后能够接收装置所发来的十六进制数据,按照设计协议对数据进行拆分,剥离出有用的数据信息后在窗口显示,并能够讲这些数据写入Excel文件当中进行保存。

    项目设计

    1. 设计窗口UI,绘制出大致的功能模型,并添加信号和槽以完成简单的逻辑实现。界面应包含文件存储地址选择,向装置发送信息获取信号,向装置发送绝对零位信号,信息获取展示表格等。
      请添加图片描述
    2. 首先我们应选择相应的端口进行连接,连接成功后设置数据保存文件地址。准备工作完成之后当我们点击获取数据按钮,便可接收到从PSD装置发送来的数据,对这些数据进行拆分解析并提取出相应的数据将它们写入表格当中进行展示。
    3. 输入授权密码后可对PSD装置设置绝对零位,将装置的坐标进行调整。

    项目实现

    1. 首先在project文件当中添加我们要用到的模块。如串口使用,Excel表格操作使用。
    QT       += core gui serialport axcontainer 
    
    • 1
    1. 引入相关头文件,定义所需的全局变量并声明槽函数。
    #ifndef WIDGET_H
    #define WIDGET_H
    
    //引入串口通信的两个头文件
    #include  //提供访问串口的功能
    #include //提供系统中存在的串口信息
    #include
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "QFileDialog"
    #include "QAxObject"
    #include "QFile"
    #include 
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
    
    private slots:
        //选择文件槽函数
        void on_BtnChooseFile_clicked();
        //发送接收数据指令槽函数
        void on_BtnRecive_clicked();
        //连接串口槽函数
        void on_BtnConnect_clicked();
        //获取密码槽函数
        void on_BtnKey_clicked();
        //设置绝对零位槽函数
        void on_BtnSetZero_clicked();
    
    private:
        Ui::Widget *ui;
        //    实例化串口类
        QSerialPort mSerialPort;
        //    记录表格当前行
        int rowNum = 1;
        //    创建Excel进程
        QAxObject *excel = new QAxObject(this);
        //    文件创建路径
        QString excel_path_1;
        //    定义工作簿
        QAxObject *workbooks;
        QAxObject *workbook;
        //    定义工作表
        QAxObject *worksheets;
        QAxObject *worksheet;
    
    };
    
    #endif // WIDGET_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    1. 初始化串口信息,对相关参数进行配置。
    
        //    设置端口默认值
        //    设置端口号
        mSerialPort.setPortName("COM4");
        //    设置波特率
        mSerialPort.setBaudRate(QSerialPort::Baud9600);
        //    设置校验位
        mSerialPort.setParity(QSerialPort::NoParity);
        //    设置数据位
        mSerialPort.setDataBits(QSerialPort::Data8);
        //    设置停止位
        mSerialPort.setStopBits(QSerialPort::OneStop);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 选择系统文件夹,在文件夹中创建Excel文件,将接收到的数据写入文件。
    • 选择文件夹
     //用户选择文件夹路径
        QFileDialog *fileDialog = new QFileDialog(this);
        fileDialog->setFileMode(QFileDialog::Directory);
        fileDialog->exec();
        auto selectDir = fileDialog->selectedFiles();
        ui->labelSetFile->setText(selectDir.at(0));
        excel_path_1 = selectDir.at(0) + QString::fromLocal8Bit("/PSD激光接收装置数据接收表.xlsx"); //设置文件路径、名、格式
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 初始化Excel表格配置
    //如果用户选择了路径
        if (selectDir.size()>0)
        {
            //设置Excel表格
            excel->setControl("Excel.Application");//连接Excel控件
            excel->dynamicCall("SetVisible (bool Visible)","false");//不显示窗体
            excel->setProperty("DisplayAlerts", true);//不显示任何警告信息。如果为true那么在关闭是会出现类似“文件已修改,是否保存”的提示
    
            workbooks = excel->querySubObject("WorkBooks");//获取工作簿集合
            workbooks->dynamicCall("Add");//新建一个工作簿
            workbook = excel->querySubObject("ActiveWorkBook");//获取当前工作簿
            worksheets = workbook->querySubObject("Sheets");//获取工作表集合
            worksheet = worksheets->querySubObject("Item(int)",1);//获取工作表集合的工作表1,即sheet1
    
            //标题行
            QAxObject *cell;
            cell=worksheet->querySubObject("Cells(int,int)", 1, 1);
            cell->dynamicCall("SetValue(const QString&)", QString::fromLocal8Bit("PSD激光接收装置数据接收表"));
            cell->querySubObject("Font")->setProperty("Size", 11);
            //合并标题行
            QString cellTitle;
            cellTitle.append("A1:");
            cellTitle.append(QChar(4 + 'A'));
            cellTitle.append(QString::number(1));
            QAxObject *range = worksheet->querySubObject("Range(const QString&)", cellTitle);
            range->setProperty("WrapText", true);
            range->setProperty("MergeCells", true);
            range->setProperty("HorizontalAlignment", -4108);//xlCenter
            range->setProperty("VerticalAlignment", -4108);//xlCenter
    
            // 定义Excel单元格
            QAxObject *cellA,*cellB,*cellC,*cellD,*cellE;
            int cellrow=2;
            QString A="A"+QString::number(cellrow);//设置要操作的单元格,如A1
            QString B="B"+QString::number(cellrow);
            QString C="C"+QString::number(cellrow);
            QString D="D"+QString::number(cellrow);
            QString E="E"+QString::number(cellrow);
            QString F="A"+QString::number(3);
            //获取单元格
            cellA = worksheet->querySubObject("Range(QVariant, QVariant)",A);
            cellB = worksheet->querySubObject("Range(QVariant, QVariant)",B);
            cellC = worksheet->querySubObject("Range(QVariant, QVariant)",C);
            cellD = worksheet->querySubObject("Range(QVariant, QVariant)",D);
            cellE = worksheet->querySubObject("Range(QVariant, QVariant)",E);
            //向单元格中写入数据
            cellA->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("接收器编号"));//设置单元格的值
            cellB->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("数据序号"));
            cellC->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("X轴"));
            cellD->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("Y轴"));
            cellE->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("ψ"));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    5.连接设备,对配置好的串口进行打开。

    //判断用户是打开连接还是关闭连接
        if(ui->BtnConnect->text() == QString::fromLocal8Bit("连接数据接口")){
            //设置打开方式
            mSerialPort.open(QSerialPort::ReadWrite);
            if(true == mSerialPort.isOpen()){
                ui->BtnConnect->setText(QString::fromLocal8Bit("关闭数据接口"));
                ui->labelPortConnect->setText(QString::fromLocal8Bit("端口已连接"));
            }else
            {
                qDebug() << "fail";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 连接设备并打开串口,点击获取信息按钮后能向装置发送相关指令。
        //发送同步信号
        QByteArray buffer;
        buffer.append('\xAA');
        buffer.append('\x01');
        buffer.append('\xBB');
        mSerialPort.write(buffer);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 通过定义信号与槽,自动接收装置发来的数据,并将它们进行解析展示。
    //定义信号接收槽(用于接收PSD向计算机发来的数据)
        connect(&mSerialPort,&QSerialPort::readyRead,
                [=]()
        {
            //接收到PSD发送来的一条数据
            const QByteArray info = mSerialPort.readAll().toHex();
            qDebug()<<"receive info:"<<info;
            //逐个拆分每一个字节进行解析
            qDebug()<<QString::fromLocal8Bit("第一个字节是:")<<info[0]<<info[1]<<endl;
            qDebug()<<QString::fromLocal8Bit("第二个字节是:")<<info[2]<<info[3]<<endl;
            qDebug()<<QString::fromLocal8Bit("第三个字节是:")<<info[4]<<info[5]<<endl;
            qDebug()<<QString::fromLocal8Bit("第四个字节是:")<<info[6]<<info[7]<<endl;
            qDebug()<<QString::fromLocal8Bit("第五个字节是:")<<info[8]<<info[9]<<endl;
    
            //写入传来的一条数据
            ui->tableWidget->setItem(rowNum,1,new QTableWidgetItem(QString::fromLocal8Bit("1号编辑器")));
            ui->tableWidget->setItem(rowNum,2,new QTableWidgetItem(QString::number(rowNum)));
            ui->tableWidget->setItem(rowNum,3,new QTableWidgetItem(QString::fromLocal8Bit("x轴数据")));
            ui->tableWidget->setItem(rowNum,4,new QTableWidgetItem(QString::fromLocal8Bit("y轴数据")));
            ui->tableWidget->setItem(rowNum++,5,new QTableWidgetItem(QString::fromLocal8Bit("ψ轴数据")));
            //如果数据量大于14条,需要继续追加行
            if(rowNum >= 14){
                ui->tableWidget->insertRow(rowNum);
            }
    
            //定义Excel单元格对象用来向Excel中添加数据
            QAxObject *cellA,*cellB,*cellC,*cellD,*cellE;
            int cellrow=rowNum+1;
            //设置要操作的单元格,如A1
            QString A="A"+QString::number(cellrow);
            QString B="B"+QString::number(cellrow);
            QString C="C"+QString::number(cellrow);
            QString D="D"+QString::number(cellrow);
            QString E="E"+QString::number(cellrow);
            //获取单元格
            cellA = worksheet->querySubObject("Range(QVariant, QVariant)",A);
            cellB = worksheet->querySubObject("Range(QVariant, QVariant)",B);
            cellC = worksheet->querySubObject("Range(QVariant, QVariant)",C);
            cellD = worksheet->querySubObject("Range(QVariant, QVariant)",D);
            cellE = worksheet->querySubObject("Range(QVariant, QVariant)",E);
            //向单元格中写入数据
            cellA->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("1号编辑器"));//设置单元格的值
            cellB->dynamicCall("SetValue(const QVariant&)",QString::number(rowNum-1));
            cellC->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("X轴"));
            cellD->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("Y轴"));
            cellE->dynamicCall("SetValue(const QVariant&)",QString::fromLocal8Bit("ψ"));
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    1. 当用户点击关闭连接按钮时,先关闭打开的串口,再将所有数据保存至Excel文件当中。
    if(true == mSerialPort.isOpen()){
                //关闭串口连接
                mSerialPort.close();
                ui->BtnConnect->setText(QString::fromLocal8Bit("连接数据接口"));
                ui->labelPortConnect->setText(QString::fromLocal8Bit("端口未连接"));
    
                //关闭Excel表格
                workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(excel_path_1));//保存至filepath,注意一定要用QDir::toNativeSeparators将路径中的"/"转换为"\",不然一定保存不了。
                workbook->dynamicCall("Close()");//关闭工作簿
                excel->dynamicCall("Quit()");//关闭excel
                delete excel;
                excel=NULL;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    成果展示

    请添加图片描述
    请添加图片描述

  • 相关阅读:
    【Linux kernel/cpufreq】framework ----cpufreq governor
    JS 原型的原理
    让Maven在你这里得心应手
    西邮计科嵌入式复习
    基于web的电子图书管理系统
    Transformers库中的pipeline模块支持的NLP任务
    代码随想录算法训练营第三十九天| 62.不同路径 63. 不同路径 II
    HIVE SQL regexp_extract和regexp_replace配合使用正则提取多个符合条件的值
    session、cookie的区别
    java类似stl建树代码(ACM)
  • 原文地址:https://blog.csdn.net/baldicoot_/article/details/125904870