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) 修改标题:窗口助手
1.2. 背景样式更改
(1) styleSheet:background-color:rgb(232,232,232,232);
(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
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();
}