QT—串口调试助手

QT—串口调试助手

功能描述

检测并列举系统中的可用串口

配置波特率,校验位,停止位,数据位

多文本发送

启动串口

发送数据

接收数据

界面展示

在这里插入图片描述

串口调试助手自动检测串口号

QList<QSerialPortInfo> serialList=QSerialPortInfo::availablePorts(); //检测串口
for(QSerialPortInfo serialInfo:serialList)
{
    qDebug()<<serialInfo.portName();  //打印串口号
    ui->comboBox_serialNum_2->addItem(serialInfo.portName());//把检测的串口追加到控件中
}

串口助手实现打开串口

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btnCloseOropenSerial_clicked();

private:
    Ui::Widget *ui;
    QSerialPort *serialport;
};
#endif // WIDGET_H

widget.cpp

 serialport=new QSerialPort;

    ui->comboBox_boautrate_2->setCurrentIndex(6);//设置默认波特率为115200
    ui->comboBox_datait_2->setCurrentIndex(3);//设置默认数据位为8位

//打开串口
void Widget::on_btnCloseOropenSerial_clicked()
{
    //1.选择端口号
    serialport->setPortName(ui->comboBox_serialNum_2->currentText());
    //2.配置波特率
    serialport->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
    //3.配置数据位
    serialport->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
    //4.配置校验位
    switch(ui->comboBox_jiaoyan_2->currentIndex())
    {
    case 0:
        serialport->setParity(QSerialPort::NoParity);
        break;
    case 1:
        serialport->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        serialport->setParity(QSerialPort::OddParity);
        break;
    case 3:
        serialport->setParity(QSerialPort::SpaceParity);
        break;
    case 4:
        serialport->setParity(QSerialPort::MarkParity);
        break;
    default:
        serialport->setParity(QSerialPort::UnknownParity);
        break;
    }
    //5.配置停止位
    serialport->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
    //6.流控
    if(ui->comboBox_fileCon_2->currentText()=="None")
    {
        serialport->setFlowControl(QSerialPort::NoFlowControl);
    }
    //7.打开串口
    if(serialport->open(QIODevice::ReadWrite))
    {
        qDebug()<<"serial open  success!";
    }
}

串口调试助手实现自发自收

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QWidget>

QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
QT_END_NAMESPACE

    class Widget : public QWidget
    {
        Q_OBJECT

            public:
        Widget(QWidget *parent = nullptr);
        ~Widget();

        private slots:
        void on_btnCloseOropenSerial_clicked();

        void on_btnSendContext_clicked();

        void on_SerialData_readyToRead();
        private:
        Ui::Widget *ui;
        QSerialPort *serialPort;
    };
#endif // WIDGET_H

widget.cpp

connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);

//打开串口
void Widget::on_btnCloseOropenSerial_clicked()
{
    //1.选择端口号
    serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
    //2.配置波特率
    serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
    //3.配置数据位
    serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
    //4.配置校验位
    switch(ui->comboBox_jiaoyan_2->currentIndex())
    {
    case 0:
        serialPort->setParity(QSerialPort::NoParity);
        break;
    case 1:
        serialPort->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        serialPort->setParity(QSerialPort::OddParity);
        break;
    case 3:
        serialPort->setParity(QSerialPort::SpaceParity);
        break;
    case 4:
        serialPort->setParity(QSerialPort::MarkParity);
        break;
    default:
        serialPort->setParity(QSerialPort::UnknownParity);
        break;
    }
    //5.配置停止位
    serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
    //6.流控
    if(ui->comboBox_fileCon_2->currentText()=="None")
    {
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
    }
    //7.打开串口
    if(serialPort->open(QIODevice::ReadWrite))
    {
        qDebug()<<"serial open  success!";
    }
}

//发数据
void Widget::on_btnSendContext_clicked()
{
    const char* sendData=ui->lineEditsendcontext->text().toStdString().c_str();
    serialPort->write(sendData);
    qDebug()<<"send Ok!"<<sendData;
    ui->textEditRecord->append(sendData);
}

//收数据
void Widget::on_SerialData_readyToRead()
{
     QString recvMessage=serialPort->readAll();
     qDebug()<<"getMessage:"<<recvMessage;
     ui->textEditRev->append(recvMessage);
}

串口发送状态更新

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QWidget>

QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
QT_END_NAMESPACE

    class Widget : public QWidget
    {
        Q_OBJECT

            public:
        Widget(QWidget *parent = nullptr);
        ~Widget();

        private slots:
        void on_btnCloseOropenSerial_clicked();

        void on_btnSendContext_clicked();

        void on_SerialData_readyToRead();
        private:
        Ui::Widget *ui;
        QSerialPort *serialPort;
        int writeCntTotal;
        int readCntTotal;
        QString sendbak;
    };
#endif // WIDGET_H

widget.cpp

//发数据
void Widget::on_btnSendContext_clicked()
{
    int writeCnt=0;
    const char* sendData=ui->lineEditsendcontext->text().toStdString().c_str();
    writeCnt=serialPort->write(sendData);
    if(writeCnt==-1) //发送失败
    {
         ui->labelSendStaus->setText("send Error!");
    }
    else  //发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug()<<"send Ok!"<<sendData;
        ui->labelSendStaus->setText("send OK!");
        ui->labelSendcnt->setNum(writeCntTotal);
        if(strcmp(sendData,sendbak.toStdString().c_str())!=0)
        {
              ui->textEditRecord->append(sendData);
              sendbak=QString(sendData) ; //保存上一次记录
        }
    }
}

//收数据
void Widget::on_SerialData_readyToRead()
{
     QString recvMessage=serialPort->readAll();
     if(recvMessage!=NULL)
     {
         qDebug()<<"getMessage:"<<recvMessage;
         ui->textEditRev->append(recvMessage);
         readCntTotal+=recvMessage.size();
         ui->labelRevcnt->setNum(readCntTotal);
     }
}

串口发送状态界面优化

串口打开状态的优化

方式一

在这里插入图片描述

void Widget::on_btnCloseOropenSerial_clicked(bool checked)
{
    if(checked) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //串口打开置为没打开
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
    }
}

方式二

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btnCloseOropenSerial_clicked();

    void on_btnSendContext_clicked();

    void on_SerialData_readyToRead();
    void on_btnCloseOropenSerial_clicked(bool checked);

private:
    Ui::Widget *ui;
    QSerialPort *serialPort;
    int writeCntTotal;
    int readCntTotal;
    QString sendbak;
    bool serialstatus;
};
#endif // WIDGET_H

widget.cpp

 if(!serialstatus) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
            serialstatus=true; //串口打开
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //串口打开置为没打开
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
        serialstatus=false; //串口失败
    }

串口调试助手实现自动发送

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QTimer>
#include <QWidget>

QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
QT_END_NAMESPACE

    class Widget : public QWidget
    {
        Q_OBJECT

            public:
        Widget(QWidget *parent = nullptr);
        ~Widget();

        private slots:
        void on_btnCloseOropenSerial_clicked();

        void on_btnSendContext_clicked();

        void on_SerialData_readyToRead();
        void on_btnCloseOropenSerial_clicked(bool checked);

        void on_checkBSendInTime_clicked(bool checked);

        private:
        Ui::Widget *ui;
        QSerialPort *serialPort;
        int writeCntTotal;
        int readCntTotal;
        QString sendbak;
        bool serialstatus;
        QTimer *timer;
    };
#endif // WIDGET_H


widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setLayout(ui->gridLayoutGlobal);

    writeCntTotal=0;
    readCntTotal=0;
    serialstatus=false;
    serialPort=new QSerialPort(this);
    timer=new QTimer(this);
    ui->btnSendContext->setEnabled(false);
    ui->checkBSendInTime->setEnabled(false);

    connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);  //接收数据
    connect(timer,&QTimer::timeout,[=](){
           on_btnSendContext_clicked();  //定时发送
    });

    ui->comboBox_boautrate_2->setCurrentIndex(6);//设置默认波特率为115200
    ui->comboBox_datait_2->setCurrentIndex(3);//设置默认数据位为8位

    QList<QSerialPortInfo> serialList=QSerialPortInfo::availablePorts(); //检测串口
    for(QSerialPortInfo serialInfo:serialList)
    {
        qDebug()<<serialInfo.portName();  //打印串口号
        ui->comboBox_serialNum_2->addItem(serialInfo.portName());//把检测的串口追加到控件中
    }

}

Widget::~Widget()
{
    delete ui;
}



//打开串口
void Widget::on_btnCloseOropenSerial_clicked()
{
    /*
    if(!serialstatus) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
            serialstatus=true; //串口打开
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //串口打开置为没打开
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
        serialstatus=false; //串口失败
    }
    */
}

//发数据
void Widget::on_btnSendContext_clicked()
{
    int writeCnt=0;
    const char* sendData=ui->lineEditsendcontext->text().toStdString().c_str();
    writeCnt=serialPort->write(sendData);
    if(writeCnt==-1) //发送失败
    {
        ui->labelSendStaus->setText("send Error!");
    }
    else  //发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug()<<"send Ok!"<<sendData;
        ui->labelSendStaus->setText("send OK!");
        ui->labelSendcnt->setNum(writeCntTotal);
        if(strcmp(sendData,sendbak.toStdString().c_str())!=0)
        {
            ui->textEditRecord->append(sendData);
            sendbak=QString(sendData) ; //保存上一次记录
        }
    }
}

//收数据
void Widget::on_SerialData_readyToRead()
{
    QString recvMessage=serialPort->readAll();
    if(recvMessage!=NULL)
    {
        qDebug()<<"getMessage:"<<recvMessage;
        ui->textEditRev->append(recvMessage);
        readCntTotal+=recvMessage.size();
        ui->labelRevcnt->setNum(readCntTotal);
    }
}



//打开串口
void Widget::on_btnCloseOropenSerial_clicked(bool checked)
{
    if(checked) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
            ui->checkBSendInTime->setEnabled(true);
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //串口打开置为没打开
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
        ui->checkBSendInTime->setEnabled(false);
        ui->checkBSendInTime->setCheckState(Qt::Unchecked);
//        ui->lineEditTimeeach->setEnabled(false);
//        ui->lineEditsendcontext->setEnabled(false);
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditsendcontext->setEnabled(true);
    }
}

//定时发送
void Widget::on_checkBSendInTime_clicked(bool checked)
{
    //qDebug()<<"checked:"<<checked;
    if(checked)
    {
        timer->start(ui->lineEditTimeeach->text().toInt());
        ui->lineEditTimeeach->setEnabled(false);
        ui->lineEditsendcontext->setEnabled(false);
        //on_btnSendContext_clicked();
    }
    else
    {
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditsendcontext->setEnabled(true);
    }
}

串口调试助手保存接收记录

//清空接收
void Widget::on_btnrevClear_clicked()
{
    ui->textEditRev->setText("");
}


//保存接收
void Widget::on_btnrevSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "F:/Qt/serialData.txt",
                                                    tr("Text(*.txt)"));
    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        out << ui->textEditRev->toPlainText();
        file.close();
    }
}

串口调试助手时间显示

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QTimer>
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btnCloseOropenSerial_clicked();

    void on_btnSendContext_clicked();

    void on_SerialData_readyToRead();
    void on_btnCloseOropenSerial_clicked(bool checked);

    void on_checkBSendInTime_clicked(bool checked);

    void on_btnrevClear_clicked();

    void on_btnrevSave_clicked();

    void timer_reflash();


private:
    Ui::Widget *ui;
    QSerialPort *serialPort;
    int writeCntTotal;
    int readCntTotal;
    QString sendbak;
    QString myTime;
    bool serialstatus;
    QTimer *timer;
    void getSysTime();
};
#endif // WIDGET_H

widget.cpp

QTimer* getSysTimeTimer=new QTimer(this);
connect(getSysTimeTimer,SIGNAL(timeout()),this,SLOT(timer_reflash()));
getSysTimeTimer->start(100);


//刷新时间
void Widget::timer_reflash()
{
    getSysTime();
    ui->labelCurrentTime->setText(myTime);
}

//获得系统时间
void Widget::getSysTime()
{

    QDateTime currentTime=QDateTime::currentDateTime();
    QDate date=currentTime.date();
    int year=date.year();
    int month=date.month();
    int day=date.day();

    QTime time=currentTime.time();
    int hour=time.hour();
    int min=time.minute();
    int sec=time.second();

    myTime=QString("%1-%2-%3 %4:%5:%6")
        .arg(year,2,10,QChar('0'))
        .arg(month,2,10,QChar('0'))
        .arg(day,2,10,QChar('0'))
        .arg(hour,2,10,QChar('0'))
        .arg(min,2,10,QChar('0'))
        .arg(sec,2,10,QChar('0'));

}

串口调试助手关联HEX接收

//HEX显示
void Widget::on_checkBoxHexDisplay_clicked(bool checked)
{
    if(checked)
    {
        //1.读取TextEdit上的内容
        QString tmp=ui->textEditRev->toPlainText();
        //2.转换成HEX
        QByteArray qtmp=tmp.toUtf8();
        qtmp=qtmp.toHex();
        //3.显示
        ui->textEditRev->setText(qtmp);
    }
    else
    {
        QString tmpHexString=ui->textEditRev->toPlainText();
        QByteArray tmpHexQByteArray=tmpHexString.toUtf8();
        QByteArray tmpQByteString=QByteArray::fromHex(tmpHexQByteArray);
        ui->textEditRev->setText(tmpQByteString);
    }
}

//收数据
void Widget::on_SerialData_readyToRead()
{
    QString recvMessage=serialPort->readAll();
    if(recvMessage!=NULL)
    {
        //qDebug()<<"getMessage:"<<recvMessage;

        if(ui->checkBoxHexDisplay->isChecked())
        {
            //新接收的内容
            QByteArray tmpHexString=recvMessage.toUtf8().toHex();
            //原来控件的内容
            QString tmpStringHex=ui->textEditRev->toPlainText();
            tmpHexString=tmpStringHex.toUtf8()+tmpHexString;
            ui->textEditRev->setText(tmpHexString);
        }
        else
        {
            if(ui->checkBrevTime->checkState()==Qt::Unchecked)
            {
                ui->textEditRev->append(recvMessage);
            }
            else if(ui->checkBrevTime->checkState()==Qt::Checked)
            {
                getSysTime();
                ui->textEditRev->append("【"+myTime+"】"+recvMessage);
            }
        }
        readCntTotal+=recvMessage.size();
        //ui->labelRevcnt->setNum(readCntTotal);
        ui->labelRevcnt->setText("Received:"+QString::number(readCntTotal));
    }
}

串口调试助手HEX发送

if(ui->checkBHexSend->isChecked()) //按下HEX发送按键
{

    QString tmp=ui->lineEditsendcontext->text(); //读出字符串内容
    //1.判断是否是偶数位
    QByteArray tmpArray=tmp.toLocal8Bit();
    if(tmpArray.size()%2!=0)
    {
        ui->labelSendStaus->setText("Error Input");
        return;
    }
    //2.判断是否符合16进制的表达
    for(char c:tmpArray)
    {
        if(!std::isxdigit(c))
        {
            ui->labelSendStaus->setText("Error Input");
            return;
        }
    }
    //3.转换成16进制发送,输入1,变成1
    QByteArray arraySend=QByteArray::fromHex(tmpArray);
    writeCnt=serialPort->write(arraySend);
}

优化HEX显示

QString lastShow;
tmp=QString::fromUtf8(qtmp);
for(int i=0;i<tmp.size();i+=2)
{
    lastShow+=tmp.mid(i,2)+" ";
}
ui->textEditRev->setText(lastShow.toUtf8());

加入发送新行和自动换行

//发数据
void Widget::on_btnSendContext_clicked()
{
    int writeCnt=0;
    const char* sendData=ui->lineEditsendcontext->text().toLocal8Bit().constData();
    if(ui->checkBHexSend->isChecked()) //按下HEX发送按键
    {

        QString tmp=ui->lineEditsendcontext->text();
        //1.判断是否是偶数位
        QByteArray tmpArray=tmp.toLocal8Bit();
        if(tmpArray.size()%2!=0)
        {
            ui->labelSendStaus->setText("Error Input");
            return;
        }
        //2.判断是否符合16进制的表达
        for(char c:tmpArray)
        {
            if(!std::isxdigit(c))
            {
                ui->labelSendStaus->setText("Error Input");
                return;
            }
        }
        if(ui->checkBSendnewLine->isChecked())
        {
            tmpArray.append("\r\n");
        }
        //3.转换成16进制发送,输入1,变成1
        QByteArray arraySend=QByteArray::fromHex(tmpArray);


        writeCnt=serialPort->write(arraySend);

    }
    else //没按下HEX发送按键
    {

        if(ui->checkBSendnewLine->isChecked()) //发送新行
        {
            qDebug()<<"发送新行";
            QByteArray arrySendData(sendData,strlen(sendData));
            arrySendData.append("\r\n");
            writeCnt=serialPort->write(arrySendData);
        }
        else
        {
            writeCnt=serialPort->write(sendData);
        }
    }

    if(writeCnt==-1) //发送失败
    {
        ui->labelSendStaus->setText("send Error!");
    }
    else  //发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug()<<"send Ok!"<<sendData<<"sendcnt"<<writeCnt;
        ui->labelSendStaus->setText("send OK!");
        //ui->labelSendcnt->setNum(writeCntTotal);
        ui->labelSendcnt->setText("Sent:"+QString::number(writeCntTotal));
        if(strcmp(sendData,sendbak.toStdString().c_str())!=0)
        {
            ui->textEditRecord->append(sendData);
            sendbak=QString::fromUtf8(sendData) ; //保存上一次记录
        }
    }
}

//收数据
void Widget::on_SerialData_readyToRead()
{
    QString recvMessage=serialPort->readAll();
    if(recvMessage!=NULL)
    {
        qDebug()<<"getMessage:"<<recvMessage<<"getMessage:"<<recvMessage.size();

        if(ui->checkBoxLine->isChecked())
        {
            recvMessage.append("\r\n");

        }


        if(ui->checkBoxHexDisplay->isChecked())
        {
            //新接收的内容
            QByteArray tmpHexString=recvMessage.toUtf8().toHex().toUpper();
            //原来控件的内容
            QString tmpStringHex=ui->textEditRev->toPlainText();
            tmpHexString=tmpStringHex.toUtf8()+tmpHexString;
            ui->textEditRev->setText(tmpHexString);
        }
        else
        {
            if(ui->checkBrevTime->checkState()==Qt::Unchecked)
            {
                ui->textEditRev->insertPlainText(recvMessage);
            }
            else if(ui->checkBrevTime->checkState()==Qt::Checked)
            {
                getSysTime();
                ui->textEditRev->insertPlainText("【"+myTime+"】"+recvMessage);
            }
        }
        readCntTotal+=recvMessage.size();
        //ui->labelRevcnt->setNum(readCntTotal);
        ui->labelRevcnt->setText("Received:"+QString::number(readCntTotal));

    }
}

显示面板和显示历史

//显示或隐藏面板
void Widget::on_btnhideTable_clicked(bool checked)
{
    if(checked)
    {
        ui->btnhideTable->setText("拓展面板");
        ui->groupBoxTexts->hide();
    }
    else
    {
        ui->btnhideTable->setText("显示面板");
        ui->groupBoxTexts->show();
    }
}

//显示或隐藏历史
void Widget::on_btnHidehistory_clicked(bool checked)
{
    if(checked)
    {
        ui->btnHidehistory->setText("显示历史");
        ui->groupBoxRecord->hide();
    }
    else
    {
        ui->btnHidehistory->setText("隐藏历史");
        ui->groupBoxRecord->show();
    }
}

串口名字列表刷新

mycombobox.h

#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H

#include <QWidget>
#include <QComboBox>

class MyComboBox : public QComboBox
{
    Q_OBJECT;

public:
    MyComboBox(QWidget *parent);
protected:
    void mousePressEvent(QMouseEvent *e) override;
signals:
     void refresh();

};

#endif // MYCOMBOBOX_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QTimer>
#include <QWidget>
#include"mycombobox.h"

QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
QT_END_NAMESPACE

    class Widget : public QWidget
    {
        Q_OBJECT

            public:
        Widget(QWidget *parent = nullptr);
        ~Widget();

        private slots:
        void on_btnCloseOropenSerial_clicked();

        void on_btnSendContext_clicked();

        void on_SerialData_readyToRead();
        void on_btnCloseOropenSerial_clicked(bool checked);

        void on_checkBSendInTime_clicked(bool checked);

        void on_btnrevClear_clicked();

        void on_btnrevSave_clicked();

        void timer_reflash();


        void on_checkBoxHexDisplay_clicked(bool checked);

        void on_btnhideTable_clicked(bool checked);

        void on_btnHidehistory_clicked(bool checked);

        void refreshSerialName();

        private:
        Ui::Widget *ui;
        QSerialPort *serialPort;
        int writeCntTotal;
        int readCntTotal;
        QString sendbak;
        QString myTime;
        bool serialstatus;
        QTimer *timer;
        void getSysTime();
    };
#endif // WIDGET_H

mycombobox.cpp

#include "mycombobox.h"
#include <QMouseEvent>
MyComboBox::MyComboBox(QWidget *parent):QComboBox(parent)
{

}

void MyComboBox::mousePressEvent(QMouseEvent *e)
{
    //1.发送信号
    if(e->button()==Qt::LeftButton)
    {
        emit refresh();
    }
    QComboBox::mousePressEvent(e);
}

widget.cpp


 connect(ui->comboBox_serialNum_2,&MyComboBox::refresh,this,&Widget::refreshSerialName);

//串口刷新
void Widget::refreshSerialName()
{
    ui->comboBox_serialNum_2->clear();
    QList<QSerialPortInfo> serialList=QSerialPortInfo::availablePorts(); //检测串口
    for(QSerialPortInfo serialInfo:serialList)
    {
        qDebug()<<serialInfo.portName();  //打印串口号
        ui->comboBox_serialNum_2->addItem(serialInfo.portName());//把检测的串口追加到控件中
    }
    ui->labelSendStaus->setText("Com Refresh!");
}

调试多文本方法

void Widget::on_pushButton_clicked()
{
    ui->lineEditsendcontext->setText(ui->lineEdit->text());
    on_btnSendContext_clicked();
    ui->checkBHexSend->setChecked(ui->checkBox->isChecked());
}
void Widget::on_pushButton_clicked()
{
    ui->lineEditsendcontext->setText(ui->lineEdit->text());
    on_btnSendContext_clicked();
   // ui->checkBHexSend->setChecked(ui->checkBox->isChecked());
    if(ui->checkBox->isChecked())
    {
         ui->checkBHexSend->setChecked(true);
    }
    else
    {
        ui->checkBHexSend->setChecked(false);
    }
}

剩下的同理

方式二


QList<QPushButton*> buttons;
for(int i=1;i<=9;i++)
{
    QString btnname=QString("pushButton_%1").arg(i);
    QPushButton* btn=findChild<QPushButton*>(btnname);
    if(btn)
    {
        btn->setProperty("buttonId",i);
        buttons.append(btn);
        connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));
    }
}


void Widget::on_command_button_clicked()
{
    QPushButton *btn=qobject_cast<QPushButton*>(sender());
    if(btn)
    {
        int num=btn->property("buttonId").toInt();
        //qDebug()<<num;
        QString lineEditname=QString("lineEdit_%1").arg(num);
        QLineEdit* lineEdit=findChild< QLineEdit*>(lineEditname);
        if(lineEdit)
            ui->lineEditsendcontext->setText(lineEdit->text());

        QString checkBoxname=QString("checkBox_%1").arg(num);
        QCheckBox* checkBox=findChild< QCheckBox*>(checkBoxname);
        if(checkBox)
            ui->checkBHexSend->setChecked(checkBox->isChecked());

        on_btnSendContext_clicked();
    }
}

定时器优化循环发送

buttonsContimer=new QTimer(this);
    //循环发送
    connect(buttonsContimer,&QTimer::timeout,this,&Widget::buttons_handler);


void Widget::buttons_handler()
{
    if(buttonsIndex<buttons.size())
    {
        QPushButton* btntmp=buttons[buttonsIndex];
        emit btntmp->clicked();
        buttonsIndex++;
    }
    else
    {
        buttonsIndex=0;
    }

}


void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked)
    {
        ui->spinBox->setEnabled(false);
        buttonsContimer->start(ui->spinBox->text().toUInt());
    }
    else
    {
        ui->spinBox->setEnabled(true);
        buttonsContimer->stop();
    }
}

线程方式优化循环发送

customthread.h

#ifndef CUSTOMTHREAD_H
#define CUSTOMTHREAD_H

#include <QThread>
#include <QWidget>

class CustomThread : public QThread
{
    Q_OBJECT

protected:
      void run() override;
public:
    CustomThread(QWidget *parent);

signals:
    void threadTimeout();
};

#endif // CUSTOMTHREAD_H

customthread.cpp

#include "customthread.h"

void CustomThread::run()
{
        while(true)
        {
            msleep(1000);
            emit threadTimeout();
        }
}

CustomThread::CustomThread(QWidget *parent):QThread(parent)
{

}

widget.cpp


void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked)
    {
        ui->spinBox->setEnabled(false);
        mythread->start();
        //buttonsContimer->start(ui->spinBox->text().toUInt());
    }
    else
    {
        ui->spinBox->setEnabled(true);
        mythread->terminate();
        //buttonsContimer->stop();
    }
}

重置功能实现

for(int i=1;i<=9;i++)
{
    QString btnname=QString("pushButton_%1").arg(i);
    QPushButton* btn=findChild<QPushButton*>(btnname);
    if(btn)
    {
        btn->setProperty("buttonId",i);
        buttons.append(btn);
        connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));
    }

    QString lineEditname=QString("lineEdit_%1").arg(i);
    QLineEdit* lineEdit=findChild<QLineEdit*>(lineEditname);
    lineEdits.append(lineEdit);

    QString checkBoxname=QString("checkBox_%1").arg(i);
    QCheckBox* checkBox=findChild<QCheckBox*>(checkBoxname);
    checkBoxs.append(checkBox);
}



//重置功能
void Widget::on_btnInit_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("提示");
    msgBox.setIcon(QMessageBox::Question);
    msgBox.setText("重置列表不可逆,确定是否重置?");
    QPushButton *yesbutton=msgBox.addButton("是",QMessageBox::YesRole);
    QPushButton *nobutton=msgBox.addButton("否",QMessageBox::NoRole);
    msgBox.exec();
    if(msgBox.clickedButton()==yesbutton)
    {
        qDebug()<<"yesbutton";
        for(int i=0;i<lineEdits.size();i++)
        {
            lineEdits[i]->clear();
            checkBoxs[i]->setChecked(false);
        }
    }
    if(msgBox.clickedButton()==nobutton)
    {
        qDebug()<<"nobutton";
    }
}

保存功能实现

//多文本保存功能
void Widget::on_btnSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "F:/",
                                                    tr("Text(*.txt)"));

    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        for(int i=0;i<lineEdits.size();i++)
        {
             out << checkBoxs[i]->isChecked()<<","<<lineEdits[i]->text()<<"\n";
        }

        file.close();
    }
}

载入功能

//多文本载入功能
void Widget::on_btnLoad_clicked()
{
    int i=0;

    QString fileName = QFileDialog::getOpenFileName(this, tr("Save File"),
                                                    "F:/",
                                                    tr("Text(*.txt)"));

    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;

        QTextStream in(&file);
        while(!in.atEnd())
        {
            QString line=in.readLine();
            QStringList parts=line.split(",");
            if(parts.count()==2)
            {
                 checkBoxs[i]->setChecked(parts[0].toUInt());
                 lineEdits[i]->setText(parts[1]);
            }
            i++;
        }

        file.close();
    }
}

完整代码

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QSerialPort>
#include <QPushButton>
#include <QTimer>
#include <QWidget>
#include <QCheckBox>
#include"mycombobox.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btnCloseOropenSerial_clicked();

    void on_btnSendContext_clicked();

    void on_SerialData_readyToRead();
    void on_btnCloseOropenSerial_clicked(bool checked);

    void on_checkBSendInTime_clicked(bool checked);

    void on_btnrevClear_clicked();

    void on_btnrevSave_clicked();

    void timer_reflash();


    void on_checkBoxHexDisplay_clicked(bool checked);

    void on_btnhideTable_clicked(bool checked);

    void on_btnHidehistory_clicked(bool checked);

    void refreshSerialName();

    void on_command_button_clicked();

    void on_checkBox_send_clicked(bool checked);


    void buttons_handler();

    void on_btnInit_clicked();

    void on_btnSave_clicked();

    void on_btnLoad_clicked();

private:
    Ui::Widget *ui;
    QSerialPort *serialPort;
    int writeCntTotal;
    int readCntTotal;
    QString sendbak;
    QString myTime;
    bool serialstatus;
    QTimer *timer;
    void getSysTime();
    int buttonsIndex;
    QList<QPushButton*> buttons;
    QList<QLineEdit*> lineEdits;
    QList<QCheckBox*> checkBoxs;
    QTimer *buttonsContimer;
};
#endif // WIDGET_H

mycombobox.h

#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H

#include <QWidget>
#include <QComboBox>

class MyComboBox : public QComboBox
{
    Q_OBJECT;

public:
    MyComboBox(QWidget *parent);
protected:
    void mousePressEvent(QMouseEvent *e) override;
signals:
     void refresh();

};

#endif // MYCOMBOBOX_H

mian.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

mycombobox.cpp

#include "mycombobox.h"
#include <QMouseEvent>
MyComboBox::MyComboBox(QWidget *parent):QComboBox(parent)
{

}

void MyComboBox::mousePressEvent(QMouseEvent *e)
{
    //1.发送信号
    if(e->button()==Qt::LeftButton)
    {
        emit refresh();
    }
    QComboBox::mousePressEvent(e);
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <qdatetime.h>
#include <QThread>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        this->setLayout(ui->gridLayoutGlobal);

        buttonsIndex=0;
        writeCntTotal=0;
        readCntTotal=0;
        serialstatus=false;

        serialPort=new QSerialPort(this);
        timer=new QTimer(this);

        ui->btnSendContext->setEnabled(false);
        ui->checkBSendInTime->setEnabled(false);
        ui->checkBSendnewLine->setEnabled(false);
        ui->checkBHexSend->setEnabled(false);
        ui->lineEditTimeeach->setEnabled(false);

        QTimer* getSysTimeTimer=new QTimer(this);



        buttonsContimer=new QTimer(this);
        //循环发送
        connect(buttonsContimer,&QTimer::timeout,this,&Widget::buttons_handler);

        connect(getSysTimeTimer,SIGNAL(timeout()),this,SLOT(timer_reflash()));
        getSysTimeTimer->start(100);

        connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);  //接收数据
        connect(timer,&QTimer::timeout,[=](){
            on_btnSendContext_clicked();  //定时发送
        });

        connect(ui->comboBox_serialNum_2,&MyComboBox::refresh,this,&Widget::refreshSerialName);

        ui->comboBox_boautrate_2->setCurrentIndex(6);//设置默认波特率为115200
        ui->comboBox_datait_2->setCurrentIndex(3);//设置默认数据位为8位

        refreshSerialName();

        ui->labelSendStaus->setText(ui->comboBox_serialNum_2->itemText(0)+"NotOpen!");



        for(int i=1;i<=9;i++)
        {
            QString btnname=QString("pushButton_%1").arg(i);
            QPushButton* btn=findChild<QPushButton*>(btnname);
            if(btn)
            {
                btn->setProperty("buttonId",i);
                buttons.append(btn);
                connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));
            }

            QString lineEditname=QString("lineEdit_%1").arg(i);
            QLineEdit* lineEdit=findChild<QLineEdit*>(lineEditname);
            lineEdits.append(lineEdit);

            QString checkBoxname=QString("checkBox_%1").arg(i);
            QCheckBox* checkBox=findChild<QCheckBox*>(checkBoxname);
            checkBoxs.append(checkBox);
        }

        /*
    //定义一个QList数组
    QList<QPushButton *> button;
    for(int i=1;i<=9;i++)  //有9个按键
    {
        //组出button的名字
        QString btnName=QString("pushButton_%1").arg(i);
        //查找button的子控件
        QPushButton* btn=findChild<QPushButton*>(btnName);
        if(btn) //找到控件
        {
            btn->setProperty("buttonId",i);//借助发送者的属性,设定其他的控件的属性
            //添加
            button.append(btn); //添加到数组
            connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked())); //为当前控件做信号与槽
        }

    }
    */
    }

Widget::~Widget()
{
    delete ui;
}



//打开串口
void Widget::on_btnCloseOropenSerial_clicked()
{
    /*
    if(!serialstatus) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        default:
            serialPort->setParity(QSerialPort::UnknownParity);
            break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
            serialstatus=true; //串口打开
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //串口打开置为没打开
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
        serialstatus=false; //串口失败
    }
    */
}

//发数据
void Widget::on_btnSendContext_clicked()
{
    int writeCnt=0;
    const char* sendData=ui->lineEditsendcontext->text().toLocal8Bit().constData();
    if(ui->checkBHexSend->isChecked()) //按下HEX发送按键
    {

        QString tmp=ui->lineEditsendcontext->text();
        //1.判断是否是偶数位
        QByteArray tmpArray=tmp.toLocal8Bit();
        if(tmpArray.size()%2!=0)
        {
            ui->labelSendStaus->setText("Error Input");
            QMessageBox msgBox;
            msgBox.setWindowTitle("HEX发送");
            msgBox.setText("Error Input!");
            msgBox.exec();
            return;
        }
        //2.判断是否符合16进制的表达
        for(char c:tmpArray)
        {
            if(!std::isxdigit(c))
            {
                ui->labelSendStaus->setText("Error Input");
                QMessageBox msgBox;
                msgBox.setWindowTitle("HEX发送");
                msgBox.setText("Error Input!");
                msgBox.exec();
                return;
            }
        }
        if(ui->checkBSendnewLine->isChecked())
        {
            tmpArray.append("\r\n");
        }
        //3.转换成16进制发送,输入1,变成1
        QByteArray arraySend=QByteArray::fromHex(tmpArray);
        writeCnt=serialPort->write(arraySend);

    }
    else //没按下HEX发送按键
    {

        if(ui->checkBSendnewLine->isChecked()) //发送新行
        {
            qDebug()<<"发送新行";
            QByteArray arrySendData(sendData,strlen(sendData));
            arrySendData.append("\n");
            writeCnt=serialPort->write(arrySendData);
        }
        else
        {
            writeCnt=serialPort->write(sendData);
        }
    }

    if(writeCnt==-1) //发送失败
    {
        ui->labelSendStaus->setText("send Error!");
    }
    else  //发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug()<<"send Ok!"<<sendData<<"sendcnt"<<writeCnt;
        ui->labelSendStaus->setText("send OK!");
        //ui->labelSendcnt->setNum(writeCntTotal);
        ui->labelSendcnt->setText("Sent:"+QString::number(writeCntTotal));
        if(strcmp(sendData,sendbak.toStdString().c_str())!=0)
        {
            ui->textEditRecord->append(sendData);
            sendbak=QString::fromUtf8(sendData) ; //保存上一次记录
        }
    }
}

//收数据
void Widget::on_SerialData_readyToRead()
{
    QString recvMessage=serialPort->readAll();
    if(recvMessage!=NULL)
    {
        qDebug()<<"getMessage:"<<recvMessage<<"getMessage:"<<recvMessage.size();

        if(ui->checkBoxLine->isChecked())
        {
            recvMessage.append("\r\n");

        }


        if(ui->checkBoxHexDisplay->isChecked())
        {
            //新接收的内容
            QByteArray tmpHexString=recvMessage.toUtf8().toHex().toUpper();
            //原来控件的内容
            QString tmpStringHex=ui->textEditRev->toPlainText();
            tmpHexString=tmpStringHex.toUtf8()+tmpHexString;
            ui->textEditRev->setText(tmpHexString);
        }
        else
        {
            if(ui->checkBrevTime->checkState()==Qt::Unchecked)
            {
                ui->textEditRev->insertPlainText(recvMessage);
            }
            else if(ui->checkBrevTime->checkState()==Qt::Checked)
            {
                getSysTime();
                ui->textEditRev->insertPlainText("【"+myTime+"】"+recvMessage);
            }
        }
        readCntTotal+=recvMessage.size();
        //ui->labelRevcnt->setNum(readCntTotal);
        ui->labelRevcnt->setText("Received:"+QString::number(readCntTotal));

        ui->textEditRev->moveCursor(QTextCursor::End);
        ui->textEditRev->ensureCursorVisible();
        //ui->textEditRev->setFocus();
    }
}



//打开串口
void Widget::on_btnCloseOropenSerial_clicked(bool checked)
{
    if(checked) //串口没打开
    {
        //1.选择端口号
        serialPort->setPortName(ui->comboBox_serialNum_2->currentText());
        //2.配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate_2->currentText().toInt());
        //3.配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_datait_2->currentText().toUInt()));
        //4.配置校验位
        switch(ui->comboBox_jiaoyan_2->currentIndex())
        {
            case 0:
                serialPort->setParity(QSerialPort::NoParity);
                break;
            case 1:
                serialPort->setParity(QSerialPort::EvenParity);
                break;
            case 2:
                serialPort->setParity(QSerialPort::OddParity);
                break;
            case 3:
                serialPort->setParity(QSerialPort::SpaceParity);
                break;
            case 4:
                serialPort->setParity(QSerialPort::MarkParity);
                break;
            default:
                serialPort->setParity(QSerialPort::UnknownParity);
                break;
        }
        //5.配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit_2->currentText().toUInt()));
        //6.流控
        if(ui->comboBox_fileCon_2->currentText()=="None")
        {
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        }
        //7.打开串口
        if(serialPort->open(QIODevice::ReadWrite)) //打开成功
        {
            qDebug()<<"serial open  success!";
            ui->comboBox_serialNum_2->setEnabled(false);
            ui->comboBox_boautrate_2->setEnabled(false);
            ui->comboBox_datait_2->setEnabled(false);
            ui->comboBox_stopbit_2->setEnabled(false);
            ui->comboBox_jiaoyan_2->setEnabled(false);
            ui->comboBox_fileCon_2->setEnabled(false);
            ui->btnCloseOropenSerial->setText("关闭串口");
            ui->lineEditTimeeach->setEnabled(true);
            ui->btnSendContext->setEnabled(true);
            ui->checkBSendInTime->setEnabled(true);
            ui->checkBSendnewLine->setEnabled(true);
            ui->checkBHexSend->setEnabled(true);
            ui->btnSave->setEnabled(true);
            ui->btnLoad->setEnabled(true);
            ui->btnInit->setEnabled(true);
            ui->spinBox->setEnabled(true);
            ui->labelSendStaus->setText(ui->comboBox_serialNum_2->itemText(0)+"Open!");
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败,串口可能被占用!");
            msgBox.exec();
        }
    }
    else //关闭串口
    {
        serialPort->close();//关闭串口
        ui->comboBox_serialNum_2->setEnabled(true);
        ui->comboBox_boautrate_2->setEnabled(true);
        ui->comboBox_datait_2->setEnabled(true);
        ui->comboBox_stopbit_2->setEnabled(true);
        ui->comboBox_jiaoyan_2->setEnabled(true);
        ui->comboBox_fileCon_2->setEnabled(true);
        ui->btnCloseOropenSerial->setText("打开串口");
        ui->btnSendContext->setEnabled(false);
        ui->checkBSendInTime->setEnabled(false);
        // ui->checkBSendInTime->setCheckState(Qt::Unchecked);
        ui->lineEditTimeeach->setEnabled(false);
        //        ui->lineEditsendcontext->setEnabled(false);
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditsendcontext->setEnabled(true);
        ui->checkBSendnewLine->setEnabled(false);
        ui->checkBHexSend->setEnabled(false);
        ui->btnSave->setEnabled(false);
        ui->btnLoad->setEnabled(false);
        ui->btnInit->setEnabled(false);
        ui->spinBox->setEnabled(false);
        ui->labelSendStaus->setText(ui->comboBox_serialNum_2->itemText(0)+"NotOpen!");
    }
}

//定时发送
void Widget::on_checkBSendInTime_clicked(bool checked)
{
    //qDebug()<<"checked:"<<checked;
    if(checked)
    {
        timer->start(ui->lineEditTimeeach->text().toInt());
        ui->lineEditTimeeach->setEnabled(false);
        ui->lineEditsendcontext->setEnabled(false);
        //on_btnSendContext_clicked();
    }
    else
    {
        timer->stop();
        ui->lineEditTimeeach->setEnabled(true);
        ui->lineEditsendcontext->setEnabled(true);
    }
}

//清空接收
void Widget::on_btnrevClear_clicked()
{
    ui->textEditRev->setText("");
}


//保存接收
void Widget::on_btnrevSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "F:/Qt/serialData.txt",
                                                    tr("Text(*.txt)"));
    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        out << ui->textEditRev->toPlainText();
        file.close();
    }
}

//刷新时间
void Widget::timer_reflash()
{
    getSysTime();
    ui->labelCurrentTime->setText(myTime);
}

//获得系统时间
void Widget::getSysTime()
{

    QDateTime currentTime=QDateTime::currentDateTime();
    QDate date=currentTime.date();
    int year=date.year();
    int month=date.month();
    int day=date.day();

    QTime time=currentTime.time();
    int hour=time.hour();
    int min=time.minute();
    int sec=time.second();

    myTime=QString("%1-%2-%3 %4:%5:%6")
        .arg(year,2,10,QChar('0'))
        .arg(month,2,10,QChar('0'))
        .arg(day,2,10,QChar('0'))
        .arg(hour,2,10,QChar('0'))
        .arg(min,2,10,QChar('0'))
        .arg(sec,2,10,QChar('0'));

}


//HEX显示
void Widget::on_checkBoxHexDisplay_clicked(bool checked)
{
    if(checked)
    {
        //1.读取TextEdit上的内容
        QString tmp=ui->textEditRev->toPlainText();
        //2.转换成HEX
        QByteArray qtmp=tmp.toUtf8();
        qtmp=qtmp.toHex();
        //3.显示
        QString lastShow;
        tmp=QString::fromUtf8(qtmp);
        for(int i=0;i<tmp.size();i+=2)
        {
            lastShow+=tmp.mid(i,2)+" ";
        }
        ui->textEditRev->setText(lastShow.toUtf8());
    }
    else
    {
        QString tmpHexString=ui->textEditRev->toPlainText();
        QByteArray tmpHexQByteArray=tmpHexString.toUtf8();
        QByteArray tmpQByteString=QByteArray::fromHex(tmpHexQByteArray);
        ui->textEditRev->setText(tmpQByteString);
    }
    ui->textEditRev->moveCursor(QTextCursor::End);
    ui->textEditRev->ensureCursorVisible();
}

//显示或隐藏面板
void Widget::on_btnhideTable_clicked(bool checked)
{
    if(checked)
    {
        ui->btnhideTable->setText("拓展面板");
        ui->groupBoxTexts->hide();
    }
    else
    {
        ui->btnhideTable->setText("显示面板");
        ui->groupBoxTexts->show();
    }
}

//显示或隐藏历史
void Widget::on_btnHidehistory_clicked(bool checked)
{
    if(checked)
    {
        ui->btnHidehistory->setText("显示历史");
        ui->groupBoxRecord->hide();
    }
    else
    {
        ui->btnHidehistory->setText("隐藏历史");
        ui->groupBoxRecord->show();
    }
}

//串口刷新
void Widget::refreshSerialName()
{
    ui->comboBox_serialNum_2->clear();
    QList<QSerialPortInfo> serialList=QSerialPortInfo::availablePorts(); //检测串口
    for(QSerialPortInfo serialInfo:serialList)
    {
        qDebug()<<serialInfo.portName();  //打印串口号
        ui->comboBox_serialNum_2->addItem(serialInfo.portName());//把检测的串口追加到控件中
    }
    ui->labelSendStaus->setText("Com Refresh!");
}


/*
void Widget::on_command_button_clicked()
{
    //获得发送者发送的信号
    QPushButton *btn=qobject_cast<QPushButton*>(sender());
    if(btn)
    {
        //拿到按键编号
        int num=btn->property("buttonId").toInt(); //把属性读出来
        QString lineEditname=QString("lineEdit_%1").arg(num);
        QLineEdit* lineEdit=findChild<QLineEdit*>(lineEditname);
        if(lineEdit)
            ui->lineEditsendcontext->setText(lineEdit->text());

        QString checkBoxname=QString("checkBox_%1").arg(num);
        QCheckBox* checkBox=findChild<QCheckBox*>(checkBoxname);
        if(checkBox)
            ui->checkBHexSend->setChecked(checkBox->isChecked());

        on_btnSendContext_clicked();
    }
}
*/

//多文本
void Widget::on_command_button_clicked()
{
    QPushButton *btn=qobject_cast<QPushButton*>(sender());
    if(btn)
    {
        int num=btn->property("buttonId").toInt();
        //qDebug()<<num;
        QString lineEditname=QString("lineEdit_%1").arg(num);
        QLineEdit* lineEdit=findChild< QLineEdit*>(lineEditname);
        if(lineEdit)
        {
            if(lineEdit->text().size()<=0)
            {
                return;
            }
            ui->lineEditsendcontext->setText(lineEdit->text());
        }


        QString checkBoxname=QString("checkBox_%1").arg(num);
        QCheckBox* checkBox=findChild< QCheckBox*>(checkBoxname);
        if(checkBox)
            ui->checkBHexSend->setChecked(checkBox->isChecked());

        on_btnSendContext_clicked();
    }
}


void Widget::buttons_handler()
{
    if(buttonsIndex<buttons.size())
    {
        QPushButton* btntmp=buttons[buttonsIndex];
        emit btntmp->clicked();
        buttonsIndex++;
    }
    else
    {
        buttonsIndex=0;
    }

}


//循环发送
void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked)
    {
        ui->spinBox->setEnabled(false);
        buttonsContimer->start(ui->spinBox->text().toUInt());
    }
    else
    {
        ui->spinBox->setEnabled(true);
        buttonsContimer->stop();
    }
}

//多文本重置功能
void Widget::on_btnInit_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("提示");
    msgBox.setIcon(QMessageBox::Question);
    msgBox.setText("重置列表不可逆,确定是否重置?");
    QPushButton *yesbutton=msgBox.addButton("是",QMessageBox::YesRole);
    QPushButton *nobutton=msgBox.addButton("否",QMessageBox::NoRole);
    msgBox.exec();
    if(msgBox.clickedButton()==yesbutton)
    {
        qDebug()<<"yesbutton";
        for(int i=0;i<lineEdits.size();i++)
        {
            lineEdits[i]->clear();
            checkBoxs[i]->setChecked(false);
        }
    }
    if(msgBox.clickedButton()==nobutton)
    {
        qDebug()<<"nobutton";
    }
}

//多文本保存功能
void Widget::on_btnSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "F:/",
                                                    tr("Text(*.txt)"));

    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        for(int i=0;i<lineEdits.size();i++)
        {
            out << checkBoxs[i]->isChecked()<<","<<lineEdits[i]->text()<<"\n";
        }

        file.close();
    }
}

//多文本载入功能
void Widget::on_btnLoad_clicked()
{
    int i=0;

    QString fileName = QFileDialog::getOpenFileName(this, tr("Save File"),
                                                    "F:/",
                                                    tr("Text(*.txt)"));

    if(fileName!=NULL)
    {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return;

        QTextStream in(&file);
        while(!in.atEnd())
        {
            QString line=in.readLine();
            QStringList parts=line.split(",");
            if(parts.count()==2)
            {
                checkBoxs[i]->setChecked(parts[0].toUInt());
                lineEdits[i]->setText(parts[1]);
            }
            i++;
        }

        file.close();
    }
}

与硬件通信的程序基本上要用到串口,虽然qt5以后集成了串口通信类,但是个人觉得那个串口通信类有点问题,在linux上表现很好,windows上大数据会有怪怪的问题出现,而且只能在qt5以上的版本才能用,无奈大部分的嵌入式linux上还停留在4.7.1到4.8.5左右的版本,所以本人一直喜欢用第三方的串口通信类做处理。 程序调试中经常需要串口调试,甚至还需要模拟设备数据回复,甚至串口转网络出去,特意将这些常用功能都做到一个串口调试助手中去。 基本功能: 1:支持16进制数据发送与接收。 2:支持windows下COM9以上的串口通信。 3:实时显示收发数据字节大小以及串口状态。 4:支持任意qt版本,亲测4.7.0 4.8.5 4.8.7 5.4.1 5.7.0 5.8.0。 5:支持串口转网络数据收发。 高级功能: 1:可自由管理需要发送的数据,每次只要从下拉框中选择数据即可,无需重新输入数据。 2:可模拟设备回复数据,需要在主界面开启模拟设备回复数据。当接收到设置好的指令时,立即回复设置的回复指令。例如指定收到0x16 0x00 0xFF 0x01需要回复0x16 0x00 0xFE 0x01,则只需要在SendData.txt中添加一条数据16 00 FF 01:16 00 FE 01即可。 3:可定时发送数据和保存数据到文本文件:,默认间隔5秒钟,可更改间隔时间。 4:在不断接收到大量数据时,可以暂停显示数据来查看具体数据,后台依然接收数据但不处理,无需关闭串口来查看已接收到的数据。 5:每次收到的数据都是完整的一条数据,而不是脱节的,做了延时处理。 6:一套源码随处编译,无需更改串口通信类,已在XP/WIN7/UBUNTU/ARMLINUX系统下成功编译并运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值