上位机项目1

141 阅读6分钟

1.界面布局

1.设计总体框架

(1) 主窗口大小:550*400

(2) 接收窗口:350*200

(3) 发送窗口:350*70

(4) 按键:刷新,状态灯,打开串口,两种显示,两种清除,三种发送

(5) 标签:TX,RX,提示信息message,TX的值,RX的值

(6) 下拉框:COM口,波特率值

(7) 波特率下拉框,默认为4800,9600和115200

(8) 修改标题:窗口助手

image.png

image.png

1.2. 背景样式更改

(1) styleSheet:background-color:rgb(232,232,232,232);

image.png

image.png

(2) 右下角标签styleSheet:color:red

(3) LED显示styleSheet:background-color:green

2.后端代码编写

2.1.pro文件

QT += serialport

2.2.头文件

(1) 添加两个头文件

#include <QSerialPort>
#include <QSerialPortInfo>

(2) 添加一个QSerialPort串口连接对象,用于后续串口连接操作

private:
    QSerialPort m_serial;

2.3.刷新按钮cpp文件

刷新按钮,先清空comboBox串口列表,再查询新的串口列表,将列表添加到comboBox中显示

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

    on_FreshCompushButton_clicked();//初始化
}

void Widget::on_FreshCompushButton_clicked()
{
    ui->ComcomboBox->clear();//清空端口
    QList<QSerialPortInfo> infoList = QSerialPortInfo::availablePorts();
    foreach (QSerialPortInfo info, infoList) {
        ui->ComcomboBox->addItem(info.portName());
    }
}

2.4.打开串口按钮cpp文件

(1) 打开串口按钮,先设置串口的参数,再打开串口,最后判断串口是否已经成功打开。若打开,LED->绿色,message标签->"串口已打开!",打开串口按键改成"关闭串口"

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

    on_OpenSerialpushButton_clicked();//初始化
}

void Widget::on_OpenSerialpushButton_clicked()
{
    if(ui->OpenSerialpushButton->text() == "打开串口")
    {
        // 串口端口设置
        m_serial.setPortName(ui->ComcomboBox->currentText());
        m_serial.setBaudRate(ui->BaudecomboBox->currentText().toInt());

        //打开串口
        m_serial.open(QIODevice::ReadWrite);

        //判断是否打开
        if(m_serial.isOpen()){//打开成功

            connect(&m_serial,&QSerialPort::readyRead,this,&Widget::stringReceived);
            ui->LEDpushButton->setStyleSheet("background-color: green;");
            ui->Messagelabel->setText("串口已打开!");
            ui->OpenSerialpushButton->setText("关闭串口");
        }
    }
    else{//关闭串口
        m_serial.close();
        if(m_serial.isOpen()){//关闭失败
            ui->Messagelabel->setText("串口关闭失败");
        }else{//关闭成功
            ui->LEDpushButton->setStyleSheet("background-color: rgb(232,232,232,232);");
            ui->Messagelabel->setText("串口已关闭!");
            ui->OpenSerialpushButton->setText("打开串口");
        }
    }
}

(2) 最终效果,这里我们用到了虚拟串口软件VSPD image.png

image.png

2.5.串口接收字符

需要手动添加槽函数,没有对应的按键;读取串口中所有的二进制字符串,按字符串或HEX格式在文本浏览框末尾显示,然后将光标移动到文本最后

(1) 头文件

private slots:
    void stringReceived
    
private:
    int rxCount = 0;
    int txCount = 0;
    char rxMode = 0;//默认是0,字符显示格式,1,HEX显示格式
    char txMode = 0;//默认是0,字符发送格式,1,HEX发送格式

(2) 头文件

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

    stringReceived();//初始化//初始化
}

void Widget::stringReceived()
{
    ui->ComcomboBox->clear();//清空端口
    QList<QSerialPortInfo> infoList = QSerialPortInfo::availablePorts();
    foreach (QSerialPortInfo info, infoList) {
        ui->ComcomboBox->addItem(info.portName());
    }
}

(3) cpp文件

void Widget::stringReceived(){
    QByteArray buf = m_serial.readAll();//接收到二进制字符数组
    rxCount += buf.size();
    if(rxMode == 0){//字符显示格式
        QString str = QString::fromUtf8(buf);// UTF-8
        ui->RxtextBrowser->insertPlainText(str);
    }else{//HEX显示格式
        QString str = "";
        for(int i = 0;i < buf.size(); i++){
            str += QString("%1 ").arg(buf[i]&0xff, 2, 16, QLatin1Char('0'));
        }
        ui->RxtextBrowser->moveCursor(QTextCursor::End); //光标始终放最后

        ui->Rxlabel->setText(QString::number(rxCount));
    }
}

2.6.发送按钮cpp文件

先判断串口是否已经打开,再按字符串或HEX格式将文本编辑中的字符发送出去,最后统计发送字符的总数。其中,在打开串口按键的槽函数中添加一行,为串口接收字符的槽函数设置一个触发信号

void Widget::on_TxpushButton_clicked()
{
    if(m_serial.isOpen()){  //串口已打开
        if(txMode == 0){    //字符格式发送
            txCount += m_serial.write(ui->TxtextEdit->toPlainText().toLatin1());
        }else{ //Hex格式发送
            txCount += m_serial.write(QByteArray::fromHex(ui->TxtextEdit->toPlainText().toLatin1()));
        }
        ui->labelTX->setText(QString::number(txCount));
    }else{//串口已关闭

    }
}

2.7.HEX显示按钮CPP文件

void Widget::on_HexRxpushButton_clicked()
{
    ui->HexRxpushButton->setStyleSheet("background-color:green;");
    rxMode = 1;
    ui->CharRxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
}

2.8.字符显示按钮CPP文件

void Widget::on_CharRxpushButton_clicked()
{
    ui->HexRxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
    rxMode = 0;
    ui->CharRxpushButton->setStyleSheet("background-color:green;");
}

2.9.HEX发送按钮CPP文件

void Widget::on_HexTxpushButton_clicked()
{
    ui->HexTxpushButton->setStyleSheet("background-color:green;");
    rxMode = 1;
    ui->CharTxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
}

2.10.字符发送按钮CPP文件

void Widget::on_CharTxpushButton_clicked()
{
    ui->HexTxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
    rxMode = 0;
    ui->CharTxpushButton->setStyleSheet("background-color:green;");
}

2.11.清空接收区按钮CPP文件

void Widget::on_ClearRxpushButton_clicked()
{
    ui->RxtextBrowser->clear();
    rxCount = 0;
    ui->labelRX->setText("0");
}

2.12.清空发送区按钮CPP文件

void Widget::on_ClearTxpushButton_clicked()
{
    ui->TxtextEdit->clear();
    txCount = 0;
    ui->labelTX->setText("0");
}

3.完整代码

3.1pro文件

QT       += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# 在.pro文件中添加
QMAKE_CXXFLAGS += /utf-8

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

3.2头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSerialPort>
#include <QSerialPortInfo>

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_FreshCompushButton_clicked();

    void on_OpenSerialpushButton_clicked();

    void stringReceived();

    void on_TxpushButton_clicked();

    void on_HexRxpushButton_clicked();

    void on_CharRxpushButton_clicked();

    void on_HexTxpushButton_clicked();

    void on_CharTxpushButton_clicked();

    void on_ClearRxpushButton_clicked();

    void on_ClearTxpushButton_clicked();

private:
    Ui::Widget *ui;
    QSerialPort m_serial;

    int rxCount = 0;
    int txCount = 0;
    char rxMode = 0;//默认是0,字符显示格式,1,HEX显示格式
    char txMode = 0;//默认是0,字符发送格式,1,HEX发送格式
};
#endif // WIDGET_H

3.3widget源文件

#include "widget.h"
#include "ui_widget.h"

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

    on_FreshCompushButton_clicked();//初始化

    on_OpenSerialpushButton_clicked();//初始化

    stringReceived();//初始化

}

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

void Widget::on_FreshCompushButton_clicked()
{
    ui->ComcomboBox->clear();//清空端口
    QList<QSerialPortInfo> infoList = QSerialPortInfo::availablePorts();
    foreach (QSerialPortInfo info, infoList) {
        ui->ComcomboBox->addItem(info.portName());
    }
}


void Widget::on_OpenSerialpushButton_clicked()
{
    if(ui->OpenSerialpushButton->text() == "打开串口")
    {
        // 串口端口设置
        m_serial.setPortName(ui->ComcomboBox->currentText());
        m_serial.setBaudRate(ui->BaudecomboBox->currentText().toInt());

        //打开串口
        m_serial.open(QIODevice::ReadWrite);

        //判断是否打开
        if(m_serial.isOpen()){//打开成功

            connect(&m_serial,&QSerialPort::readyRead,this,&Widget::stringReceived);
            ui->LEDpushButton->setStyleSheet("background-color: green;");
            ui->Messagelabel->setText("串口已打开!");
            ui->OpenSerialpushButton->setText("关闭串口");
        }
    }
    else{//关闭串口
        m_serial.close();
        if(m_serial.isOpen()){//关闭失败
            ui->Messagelabel->setText("串口关闭失败");
        }else{//关闭成功
            ui->LEDpushButton->setStyleSheet("background-color: rgb(232,232,232,232);");
            ui->Messagelabel->setText("串口已关闭!");
            ui->OpenSerialpushButton->setText("打开串口");
        }
    }
}


void Widget::stringReceived(){
    QByteArray buf = m_serial.readAll();//接收到二进制字符数组
    rxCount += buf.size();
    if(rxMode == 0){//字符显示格式
        QString str = QString::fromUtf8(buf);// UTF-8
        ui->RxtextBrowser->insertPlainText(str);
    }else{//HEX显示格式
        QString str = "";
        for(int i = 0;i < buf.size(); i++){
            str += QString("%1 ").arg(buf[i]&0xff, 2, 16, QLatin1Char('0'));
        }
        ui->RxtextBrowser->moveCursor(QTextCursor::End); //光标始终放最后

        ui->Rxlabel->setText(QString::number(rxCount));
    }
}


void Widget::on_TxpushButton_clicked()
{
    if(m_serial.isOpen()){  //串口已打开
        if(txMode == 0){    //字符格式发送
            txCount += m_serial.write(ui->TxtextEdit->toPlainText().toLatin1());
        }else{ //Hex格式发送
            txCount += m_serial.write(QByteArray::fromHex(ui->TxtextEdit->toPlainText().toLatin1()));
        }
        ui->labelTX->setText(QString::number(txCount));
    }else{//串口已关闭

    }
}


void Widget::on_HexRxpushButton_clicked()
{
    ui->HexRxpushButton->setStyleSheet("background-color:green;");
    rxMode = 1;
    ui->CharRxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
}


void Widget::on_CharRxpushButton_clicked()
{
    ui->HexRxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
    rxMode = 0;
    ui->CharRxpushButton->setStyleSheet("background-color:green;");
}


void Widget::on_HexTxpushButton_clicked()
{
    ui->HexTxpushButton->setStyleSheet("background-color:green;");
    rxMode = 1;
    ui->CharTxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
}


void Widget::on_CharTxpushButton_clicked()
{
    ui->HexTxpushButton->setStyleSheet("background-color:rgb(232,232,232,232);");
    rxMode = 0;
    ui->CharTxpushButton->setStyleSheet("background-color:green;");
}


void Widget::on_ClearRxpushButton_clicked()
{
    ui->RxtextBrowser->clear();
    rxCount = 0;
    ui->labelRX->setText("0");
}


void Widget::on_ClearTxpushButton_clicked()
{
    ui->TxtextEdit->clear();
    txCount = 0;
    ui->labelTX->setText("0");
}



3.4main源文件

#include "widget.h"

#include <QApplication>

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