• 小工具--串口


    功能实现:

      1. 接收串口数据;

      2.保存接收数据到TXT文档,主要是测试串口接收到数据,给python进行处理时的小应用(个人使用),避免长时间测试数据丢失的问题

      3.发送串口数据;

      4.发送文件;

    小细节:

       1.串口没有打开之前,不能进行发送数据等操作,需要在发送槽函数中进行判断串口是否打开;

      2.串口刷新监测;

       3.串口发送框允许输入的字符a-f ,A-F,0-9,以及空格符,正则表达式的运用以及过滤器QValidator的使用;

       4.接收框显示,发送数据什么格式,接收数据什么格式;

    代码:

    #include "serialportqmain.h"
    #include "ui_serialportqmain.h"
    
    #include <QFileDialog>
    #include<QMessageBox>
    #include<QTextStream>
    #include<QDebug>
    #include <QRegExp>
    #include<QValidator>
    #include<QSizePolicy>
    
    #include <QComboBox>
    #include <QTimer>
    #include<QDateTime>
    SerialPortQMain::SerialPortQMain(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::SerialPortQMain)
    {
        ui->setupUi(this);
    
        initSerial();
        //recv
        connect(ui->pushButton_Open,&QPushButton::clicked,this,&SerialPortQMain::slot_on_openSerial_clicked);
        connect(ui->pushButton_SaveRecv,&QPushButton::clicked,this,&SerialPortQMain::slot_on_saveRecvBtn_clicked);
        connect(ui->pushButton_ClearRecv,&QPushButton::clicked,this,&SerialPortQMain::slot_on_clearRecvBtn_clicked);
        //send
        connect(ui->pushButton_Send,&QPushButton::clicked,this,&SerialPortQMain::slot_on_sendBtn_clicked);
        connect(ui->pushButton_ClearSend,&QPushButton::clicked,this,&SerialPortQMain::slot_on_clearSendBtn_clicked);
        connect(ui->pushButton_OpenFile,&QPushButton::clicked,this,&SerialPortQMain::slot_on_openFileBtn_clicked);
        connect(ui->pushButton_SendFile,&QPushButton::clicked,this,&SerialPortQMain::slot_on_sendFileBtn_clicked);
        connect(ui->pushButton_StopSend,&QPushButton::clicked,this,&SerialPortQMain::slot_on_stopSend_clicked);//停止发送文件
    
        //输入自定义波特率
        connect(ui->comboBoxBaudRate, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(slot_on_baudRate(const QString &)));
    
        //周期发送
        connect(ui->checkBox_SendRegular,&QCheckBox::stateChanged,this,&SerialPortQMain::slot_on_periodSendCheckSelect);
        connect(ui->checkBox_Send,&QCheckBox::stateChanged,this,&SerialPortQMain::slot_on_StrOrHex);
    }
    
    SerialPortQMain::~SerialPortQMain()
    {
        delete ui;
    }
    
     void SerialPortQMain::slot_on_refreshCurrentTime()
     {
         currentTime=QTime::currentTime();
         strTime= currentTime.toString("HH:mm");
         currentDate =QDate::currentDate();
         strDate = currentDate.toString("yyyy-MM-dd dddd");
         strDate.append(strTime);
         currenttimeDisplay->setText("当前时间:"+strDate);
     }
    
    /*串口初始化*/
    void SerialPortQMain::initSerial()
    {
        /*查找可用串口*/
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            QSerialPort serialPort ;
            serialPort.setPort(info);
            if(serialPort.open(QIODevice::ReadWrite))
            {
                ui->comboBoxSerial->addItem(serialPort.portName());
                serialPort.close();
            }
        }
        //设置波特率下拉菜单默认显示第三项
        ui->comboBoxBaudRate->setCurrentIndex(3);
    
        //statusbar
        operateState = new QLabel;
        ui->statusBar->addPermanentWidget(operateState,1);
        operateState->setText("当前操作状态:"+operateStateChange);
        operateState->setFixedSize(200,20);
    
        currenttimeDisplay=new QLabel;
        ui->statusBar->addPermanentWidget(currenttimeDisplay,3);
    
        timerPeriodSend = new QTimer(this);  //周期发送数据定时器
    
        refreshSerialTimer = new QTimer(this);//刷新串口定时器
        connect(refreshSerialTimer, SIGNAL(timeout()), this, SLOT(slot_on_refreshComPort())); //定时刷新串口
        refreshSerialTimer->start(1000);
    
        currentTimer=new QTimer(this);
       connect(currentTimer, SIGNAL(timeout()), this, SLOT(slot_on_refreshCurrentTime())); //定时刷新串口
       currentTimer->start(1000);
    
        //发送输入规则
        QRegExp exp("[A-Fa-f0-9\s][A-Fa-f0-9\s]+$");
        QValidator *validator = new QRegExpValidator(exp,ui->lineEditSend);
        ui->lineEditSend->setValidator(validator);
    }
    /*刷新串口*/
    void SerialPortQMain::slot_on_refreshComPort()
    {
        ui->comboBoxSerial->clear(); //每次将之前信息监测到的串口删除,重新扫描
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            QSerialPort serialPort ;
            serialPort.setPort(info);
    
            if(serialPort.open(QIODevice::ReadWrite))
            {
                ui->comboBoxSerial->addItem(serialPort.portName());
                serialPort.close();
            }
        }
    }
    
    /*操作清除接收窗口按钮*/
    void SerialPortQMain::slot_on_clearRecvBtn_clicked()
    {
        ui->textEditRecv->clear();
    }
    /*操作保存接收窗口按钮*/
    void SerialPortQMain::slot_on_saveRecvBtn_clicked()
    {
        QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                        "/home",
                                                        tr("Text (*.txt *.*)"));
        if(fileName !="") //不为空
        {
            QFile saveFile(fileName);
            if(!saveFile.open(QIODevice::WriteOnly))
            {
                //操作提示
                operateStateDisplay("保存文件失败!");
    
                QMessageBox::about(this,"操作","操作错误");
            }
            else{
                QTextStream stream(&saveFile);
                stream<<ui->textEditRecv->toPlainText();
                stream.flush();
                saveFile.close();
            }
        }
    }
    /*操作打开串口按钮*/
    void SerialPortQMain:: slot_on_openSerial_clicked()
    {
        if(ui->pushButton_Open->text() == tr("打开串口"))
        {
            //若串口已经打开则不再继续刷新串口
            refreshSerialTimer->stop();
    
            serialPort = new QSerialPort;
            //设置串口名
            serialPort->setPortName(ui->comboBoxSerial->currentText());
            //打开串口模式
            serialPort->open(QIODevice::ReadWrite);
            //设置波特率
            serialPort->setBaudRate(ui->comboBoxBaudRate->currentText().toInt());
            //设置数据位
            switch (ui->comboBoxDataBit->currentIndex()) {
            case 8:serialPort->setDataBits(QSerialPort::Data8); break;
            case 7:serialPort->setDataBits(QSerialPort::Data7); break;
            default:
                break;
            }
    
            //设置奇偶校验位
            switch (ui->comboBoxOdd->currentIndex()) {
            case 0:serialPort->setParity(QSerialPort::NoParity); break;
            case 2:serialPort->setParity(QSerialPort::EvenParity);break;
            case 3:serialPort->setParity(QSerialPort::OddParity);break;
            case 4:serialPort->setParity(QSerialPort::SpaceParity);break;
            case 5:serialPort->setParity(QSerialPort::MarkParity);break;
            default:
                break;
            }
    
            //设置停止位
            switch(ui->comboBoxStopBit->currentIndex())
            {
    
            case 1: serialPort->setStopBits(QSerialPort::OneStop); break;
            case 2: serialPort->setStopBits(QSerialPort::TwoStop); break;
            case 3: serialPort->setStopBits(QSerialPort::OneAndHalfStop); break;
            default: break;
            }
            //设置流控制
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
            ui->pushButton_Open->setText(tr("关闭串口"));
            ui->pushButton_Open->setStyleSheet("background: lightgreen");
    
            //操作提示
            operateStateDisplay("打开串口成功!");
    
            if(ui->lineEdit_SaveRecv->text() != "") {
                save_TxtName = ui->lineEdit_SaveRecv->text();
    
                QFile recvfliesave(QString("./%1.txt").arg(save_TxtName));
                if(!recvfliesave.open(QFile::WriteOnly|QIODevice::Truncate|QIODevice::Text) )
                {
                    QMessageBox::warning(this,"提示","文件创建失败");
                    createTXTEnable = false;
                }
                else{
                    createTXTEnable = true;
                }
            }
            else
            {
                QMessageBox::warning(this,"提示","没有填写保存文件名称,可跳过;说明只显示,不保存");
            }
    
            isOpenSerial =true;
    
            //串口打开后,连接接收
            connect(serialPort,&QSerialPort::readyRead,this,&SerialPortQMain::slot_on_recvOperate,Qt::QueuedConnection);
        }
        else{
            serialPort->close();
            isOpenSerial=false;
            ui->pushButton_Open->setText(tr("打开串口"));
            ui->pushButton_Open->setStyleSheet("background:#e8e8e8");
            //操作提示
            operateStateDisplay("串口关闭!");
        }
    
    }
    /*接收数据,在接收区显示数据*/
    void SerialPortQMain::slot_on_recvOperate()
    {
        QByteArray readDataBuff(1024,0);
        static QByteArray buff;
        if(serialPort->bytesAvailable())
        {
            //操作提示
            operateStateDisplay("正在接收数据...");
            readDataBuff= serialPort->readAll();
            buff.append(readDataBuff);
    
    
            if(createTXTEnable)  //  允许写入Txt
            {
                writeRecvDataToTXT(buff);
            }
    
            //接收区显示
            if(ui->checkBox_RecvHex->checkState() == Qt::Unchecked){
                ui->textEditRecv->insertPlainText(QString(buff));
            }
            else if(ui->checkBox_RecvHex->checkState() == Qt::Checked)
                ui->textEditRecv->insertPlainText(buff.toHex());
            buff.clear(); //每次接收完成要清除;
        }
        //操作提示
        operateStateDisplay("数据接收完成!");
    }
    
    //接收内容写入TXT
    void SerialPortQMain::writeRecvDataToTXT(QByteArray data)
    {
        QFile recvfliesave(QString("./%1.txt").arg(save_TxtName));
        if(recvfliesave.open(QFile::WriteOnly|QFile::Append)){
            recvfliesave.write(data);
        }
    }
    
    //发送端操作
    /*发送数据*/
    void SerialPortQMain::slot_on_sendBtn_clicked()
    {
        if(!isOpenSerial)
        {
            QMessageBox::warning(this,"提示","串口没有打开!");
            return ;
        }
        slot_on_StrOrHex();
        serialPort->write(sendData);
    }
    
    //发送str 或者hex
    void SerialPortQMain::slot_on_StrOrHex()
    {
        if(ui->checkBox_Send->checkState() == Qt::Unchecked) //没有选中,说明 发送字符
        {
            sendData= ui->lineEditSend->text().toLatin1();
            ui->lineEditSend->setText(ui->lineEditSend->text());
        }
        else if(ui->checkBox_Send->checkState() == Qt::Checked)
        {
            StringToHex(ui->lineEditSend->text(),sendData);
            ui->lineEditSend->setText(ui->lineEditSend->text());
        }
    }
    
    //周期发送
    void SerialPortQMain::slot_on_periodSendCheckSelect()
    {
        int period = ui->lineEdit_time->text().toInt();
    
        if(ui->checkBox_SendRegular->checkState() == Qt::Checked)  //选中
        {
    
           timerPeriodSend->start(period);
            connect(timerPeriodSend, SIGNAL(timeout()), this, SLOT(slot_on_sendBtn_clicked())); //定时刷新串口
    
            ui->lineEdit_time->setEnabled(false);
        }
        else if(ui->checkBox_SendRegular->checkState() == Qt::Unchecked) //没选中
        {
            timerPeriodSend->stop();
            ui->lineEdit_time->setEnabled(true);
        }
    }
    
    /*打开文件*/
    void SerialPortQMain::slot_on_openFileBtn_clicked()
    {
        QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                        "/home",
                                                        tr("Text (*.txt *.*)"));
        ui->lineEdit_FilePath->setText(fileName);
        txtSendFilePathName = ui->lineEdit_FilePath->text();
        qDebug()<<txtSendFilePathName;
    }
    
    /*发送文件*/
    void SerialPortQMain::slot_on_sendFileBtn_clicked()
    {
        if(!isOpenSerial)
        {
            QMessageBox::warning(this,"提示","串口没有打开!");
            return ;
        }
    
        if(txtSendFilePathName!="")
        {
            QFile fileexample(txtSendFilePathName);
            if(!fileexample.open(QIODevice::ReadOnly))
                return ;
    
            while (!fileexample.atEnd()) {
                QByteArray line = fileexample.readLine();
                serialPort->write(line);
                //操作提示
                operateStateDisplay( "正在发送文件...");
                int p = fileexample.pos()/fileexample.size() *100;
                ui->progressBar_SendFile->setValue(p );
            }
            QMessageBox::warning(this,"提示","发送完成!");
            ui->progressBar_SendFile->setValue(0);
            //操作提示
            operateStateDisplay("文件发送完成...");
        }
        else{
            QMessageBox::warning(this,"提示","请先选择要发送文件!");
        }
    }
    
    //停止发送文件
    void SerialPortQMain::slot_on_stopSend_clicked()
    {
    
    }
    
    /*清空发送区*/
    void SerialPortQMain::slot_on_clearSendBtn_clicked()
    {
        ui->lineEditSend->clear();
    }
    
    //statebar显示
    QString SerialPortQMain::operateStateDisplay(QString operateStateChange)
    {
        ui->statusBar->addWidget(operateState);
        operateState->setText("当前操作状态:"+operateStateChange);
        return operateStateChange;
    }
    
    //自定义波特率
    void SerialPortQMain::slot_on_baudRate(const QString &text)
    {
        if(text == "custom")
        {
            ui->comboBoxBaudRate->setEditable(true);
        }
        else{
            ui->comboBoxBaudRate->setEditable(false);
        }
    }
    
    ////////////////////////
    void SerialPortQMain::StringToHex(QString str,QByteArray &senddata)
    {
        int hexdata,lowhexdata;
        int hexdatalen = 0;
        int len = str.length();
        senddata.resize(len/2);
        char lstr,hstr;
        for(int i=0; i<len; )
        {
            //char lstr,
            hstr=str[i].toLatin1();
            if(hstr == ' ')
            {
                i++;
                continue;
            }
            i++;
            if(i >= len)
                break;
            lstr = str[i].toLatin1();
            hexdata = ConvertHexChar(hstr);
            lowhexdata = ConvertHexChar(lstr);
            if((hexdata == 16) || (lowhexdata == 16))
                break;
            else
                hexdata = hexdata*16+lowhexdata;
            i++;
            senddata[hexdatalen] = (char)hexdata;
            hexdatalen++;
        }
        senddata.resize(hexdatalen);
    }
    
    char SerialPortQMain::ConvertHexChar(char ch)
    {
        if((ch >= '0') && (ch <= '9'))
            return ch-0x30;
        else if((ch >= 'A') && (ch <= 'F'))
            return ch-'A'+10;
        else if((ch >= 'a') && (ch <= 'f'))
            return ch-'a'+10;
        else return (-1);
    
    
    }
  • 相关阅读:
    2019年8月22日 星期四(杂谈)
    文件读写
    log4j
    java 读写 xlsx
    mongodb的增删改查
    mongodb安装与简单配置
    mondb的特性
    mongodb 的简单应用
    linux 学习1
    linux 安装MySql
  • 原文地址:https://www.cnblogs.com/whitewn/p/8964110.html
Copyright © 2020-2023  润新知