0
点赞
收藏
分享

微信扫一扫

QT实现串口通信

三分梦_0bc3 2022-03-12 阅读 145

要实现串口通信,需要知道串口通信需要的信息

主要参数有:波特率、校验位、数据位、停止位、控制流

主要操作有:串口的打开和关闭、刷新设备串口、接发数据、开关显示灯等。

实现效果如图:

最后附赠完整源码。

第一步:在头文件中引入 QtSerialPort 类的两个头文件(必须引入)

// 引入串口通信的两个头文件(第一步)
#include <QtSerialPort/QSerialPort> // 提供访问串口的功能
#include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口信息

第二步:在工程文件中添加以下代码

# 引入串口工程类型(第二步)
QT += serialport

第三步:在头文件中定义全局的串口对象

QSerialPort     *serial;                            // 定义全局的串口对象(第三步)

第四步:参数设置,在头文件中定义初始化参数的函数和参数变量名,在.cpp文件中实现函数

public:
void SerialPortInit(); // 串口初始化(参数配置)

private:
// 参数配置
QStringList baudList; //波特率
QStringList parityList; //校验位
QStringList dataBitsList; //数据位
QStringList stopBitsList; //停止位
QStringList flowControlList; //控制流
// 串口初始化(参数配置)
void MainWindow::SerialPortInit()
{
serial = new QSerialPort; //申请内存,并设置父对象

// 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
serial->setPort(info); // 在对象中设置串口
if(serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口
{
ui->PortBox->addItem(info.portName()); // 添加计算机中的端口
serial->close(); // 关闭
} else
{
qDebug() << "串口打开失败,请重试";
}
}

// 参数配置
// 波特率,波特率默认选择57600 ,禁止用户点击
ui->BaudBox->addItem("57600");
serial->setBaudRate(QSerialPort::Baud57600);
ui->BaudBox->setDisabled(true);

// 校验,校验默认选择无
ui->ParityBox->addItem("无");
serial->setParity(QSerialPort::NoParity);

// 数据位,数据位默认选择8位
ui->BitBox->addItem("8");
serial->setDataBits(QSerialPort::Data8);

// 停止位,停止位默认选择1位
ui->StopBox->addItem("1");
serial->setStopBits(QSerialPort::OneStop);

// 控制流,默认选择无
ui->ControlBox->addItem("无");
serial->setFlowControl(QSerialPort::NoFlowControl);

// 刷新串口
RefreshSerialPort(0);

// 信号
connect(serial,&QSerialPort::readyRead,this,&MainWindow::DataReceived); // 接收数据
connect(ui->SendWordOrder,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendButton,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn1,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn2,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn3,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
}

第五步:刷新串口,及时更新可用的串口

// 刷新串口
void MainWindow::RefreshSerialPort(int index)
{
QStringList portNameList; // 存储所有串口名
if(index != 0)
{
serial->setPortName(ui->PortBox->currentText()); //设置串口号
}
else
{
ui->PortBox->clear(); //关闭串口号
ui->PortBox->addItem("刷新"); //添加刷新
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //添加新串口
{
portNameList.append(info.portName());
}
// 将串口号按着COM1,COM2,COM3....排序
std::sort(portNameList.begin(), portNameList.end(),
[=](const QString &s1, const QString &s2)
{
int a = 0;
int b = 0;
sscanf(s1.toUtf8().data(),"COM%d",
sscanf(s2.toUtf8().data(),"COM%d",
return a < b;
});
ui->PortBox->addItems(portNameList);
ui->PortBox->setCurrentIndex(1); // 当前串口号为COM1
serial->setPortName(ui->PortBox->currentText()); //设置串口号
}
}

第六步:发送数据和接收数据

// 接收数据,使用read () / readLine () / readAll ()
void MainWindow::DataReceived()
{
char BUF[512] = {0}; // 存储转换类型后的数据
QByteArray data = serial->readAll(); // 读取数据

if(!data.isEmpty()) // 接收到数据
{
QString str = ui->DataReceived->toPlainText(); // 返回纯文本
str += tr(data); // 数据是一行一行传送的,要保存所有数据
ui->DataReceived->clear(); // 清空之前的数据
ui->DataReceived->append(str); // 将数据放入控件中
qDebug() << "str info: " << ui->DataReceived->toPlainText();

// 清除之前的数据,防止追加,因为每次获取的数据不一样
int index = str.indexOf("\r\n"); // 找到,返回索引值,找不到,返回-1
if(index != -1)
{
snprintf(BUF,500,"%s", str.left(index + 2).toUtf8().data()); // QString转为char * 类型
qDebug() << "BUF info: " << BUF; // 数据类型转换成功
str.remove(0,index + 2);

// 处理获取到的数据,将其放入对应的控件中
// .....

}
}
}

// 发送数据,write ()
void MainWindow::DataSend()
{
serial->write(ui->DataSend->toPlainText().toLatin1()); // 串口发送数据
}

第七步:打开串口和关闭串口,当打开串口后,显示绿灯;关闭串口后,显示红灯

// 串口开关
void MainWindow::on_OpenSerialButton_clicked()
{
if(serial->isOpen()) // 如果串口打开了,先给他关闭
{
serial->clear();
serial->close();
// 关闭状态,按钮显示“打开串口”
ui->OpenSerialButton->setText("打开串口");
// 关闭状态,允许用户操作
ui->BaudBox->setDisabled(false);
ui->ParityBox->setDisabled(false);
ui->BitBox->setDisabled(false);
ui->StopBox->setDisabled(false);
ui->ControlBox->setDisabled(false);
// 禁止操作“发送字符操作”
ui->SendWordOrder->setDisabled(true);
ui->SendButton->setDisabled(true);
// 关闭状态,颜色为绿色
ui->OpenSerialButton->setStyleSheet("color: green;");
// 关闭,显示灯为红色
LED(true);
// 清空数据
ui->DataReceived->clear();
ui->DataSend->clear();
}
else // 如果串口关闭了,先给他打开
{
//当前选择的串口名字
serial->setPortName(ui->PortBox->currentText());
//用ReadWrite 的模式尝试打开串口,无法收发数据时,发出警告
if(!serial->open(QIODevice::ReadWrite))
{
QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);
return;
}
// 打开状态,按钮显示“关闭串口”
ui->OpenSerialButton->setText("关闭串口");
// 打开状态,禁止用户操作
ui->BaudBox->setDisabled(true);
ui->ParityBox->setDisabled(true);
ui->BitBox->setDisabled(true);
ui->StopBox->setDisabled(true);
ui->ControlBox->setDisabled(true);
// 允许操作“发送字符操作”
ui->SendWordOrder->setDisabled(false);
ui->SendButton->setDisabled(false);
// 打开状态,颜色为红色
ui->OpenSerialButton->setStyleSheet("color: red;");
// 打开,显示灯为绿色
LED(false);
}
}

// 开关显示灯
void MainWindow::LED(bool changeColor)
{
if(changeColor == false)
{
// 显示绿色
ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 229, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
}
else
{
// 显示红色
ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
}
}

第八步:相关槽函数

// 控件中添加 #
void MainWindow::on_SendButton_clicked()
{
on_ClearButton_clicked();
ui->DataSend->append("#");
}
// 清空控件
void MainWindow::on_ClearButton_clicked()
{
ui->DataSend->setText("");
}
// 清空接收到的数据
void MainWindow::on_ClearShowButton_clicked()
{
ui->DataReceived->setText("");
}
// 点击发送后,获取串口信息并展示在接受控件中
void MainWindow::on_SendEditBtn1_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit1->text(); //获取发送框内容
ui->DataSend->setText(EditText); //将文本内容放在发送栏中
}

void MainWindow::on_SendEditBtn2_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit2->text(); //获取发送框内容

// qDebug() << "Edit1 text: " << EditText;

ui->DataSend->append(EditText); //将文本内容放在发送栏中
}

void MainWindow::on_SendEditBtn3_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit3->text(); //获取发送框内容

// qDebug() << "Edit1 text: " << EditText;

ui->DataSend->append(EditText); //将文本内容放在发送栏中
}



void MainWindow::on_SendWordOrder_clicked()
{
on_SendButton_clicked();
}

源码:

工程文件.pro文件源码:

QT       += core gui
# 引入串口工程类型(第二步)
QT += serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

FORMS += \
mainwindow.ui

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

头文件源码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
// 引入串口通信的两个头文件(第一步)
#include <QtSerialPort/QSerialPort> // 提供访问串口的功能
#include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口信息

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

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

// 串口功能
void SerialPortInit(); // 串口初始化(参数配置)
void RefreshSerialPort(int index); // 刷新串口

public slots:
// 串口槽函数
void DataReceived(); // 接收数据
private slots:
// 串口槽函数
void DataSend(); // 发送数据

void on_OpenSerialButton_clicked(); // 串口开关

void on_SendButton_clicked(); // 控件中添加 #

void on_ClearButton_clicked(); // 清空控件中的所有 #

void on_ClearShowButton_clicked(); // 清空接收到的数据

void LED(bool changeColor); // 开关显示灯

// 点击发送,接收数据
void on_SendEditBtn1_clicked();

void on_SendEditBtn2_clicked();

void on_SendEditBtn3_clicked();


void on_SendWordOrder_clicked();

private:
Ui::MainWindow *ui;

// 串口变量
QSerialPort *serial; // 定义全局的串口对象(第三步)
// 参数配置
QStringList baudList; //波特率
QStringList parityList; //校验位
QStringList dataBitsList; //数据位
QStringList stopBitsList; //停止位
QStringList flowControlList; //控制流
};
#endif // MAINWINDOW_H

.cpp文件源码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>

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

SerialPortInit();
}

// 串口初始化(参数配置)
void MainWindow::SerialPortInit()
{
serial = new QSerialPort; //申请内存,并设置父对象

// 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
serial->setPort(info); // 在对象中设置串口
if(serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口
{
ui->PortBox->addItem(info.portName()); // 添加计算机中的端口
serial->close(); // 关闭
} else
{
qDebug() << "串口打开失败,请重试";
}
}

// 参数配置
// 波特率,波特率默认选择57600 ,禁止用户点击
ui->BaudBox->addItem("57600");
serial->setBaudRate(QSerialPort::Baud57600);
ui->BaudBox->setDisabled(true);

// 校验,校验默认选择无
ui->ParityBox->addItem("无");
serial->setParity(QSerialPort::NoParity);

// 数据位,数据位默认选择8位
ui->BitBox->addItem("8");
serial->setDataBits(QSerialPort::Data8);

// 停止位,停止位默认选择1位
ui->StopBox->addItem("1");
serial->setStopBits(QSerialPort::OneStop);

// 控制流,默认选择无
ui->ControlBox->addItem("无");
serial->setFlowControl(QSerialPort::NoFlowControl);

// 刷新串口
RefreshSerialPort(0);

// 信号
connect(serial,&QSerialPort::readyRead,this,&MainWindow::DataReceived); // 接收数据
connect(ui->SendWordOrder,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendButton,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn1,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn2,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
connect(ui->SendEditBtn3,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据

}
// 刷新串口
void MainWindow::RefreshSerialPort(int index)
{
QStringList portNameList; // 存储所有串口名
if(index != 0)
{
serial->setPortName(ui->PortBox->currentText()); //设置串口号
}
else
{
ui->PortBox->clear(); //关闭串口号
ui->PortBox->addItem("刷新"); //添加刷新
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //添加新串口
{
portNameList.append(info.portName());
}
// 将串口号按着COM1,COM2,COM3....排序
std::sort(portNameList.begin(), portNameList.end(),
[=](const QString &s1, const QString &s2)
{
int a = 0;
int b = 0;
sscanf(s1.toUtf8().data(),"COM%d",
sscanf(s2.toUtf8().data(),"COM%d",
return a < b;
});
ui->PortBox->addItems(portNameList);
ui->PortBox->setCurrentIndex(1); // 当前串口号为COM1
serial->setPortName(ui->PortBox->currentText()); //设置串口号
}
}

// 接收数据,使用read () / readLine () / readAll ()
void MainWindow::DataReceived()
{
char BUF[512] = {0}; // 存储转换类型后的数据
QByteArray data = serial->readAll(); // 读取数据

if(!data.isEmpty()) // 接收到数据
{
QString str = ui->DataReceived->toPlainText(); // 返回纯文本
str += tr(data); // 数据是一行一行传送的,要保存所有数据
ui->DataReceived->clear(); // 清空之前的数据
ui->DataReceived->append(str); // 将数据放入控件中
qDebug() << "str info: " << ui->DataReceived->toPlainText();

// 清除之前的数据,防止追加,因为每次获取的数据不一样
int index = str.indexOf("\r\n"); // 找到,返回索引值,找不到,返回-1
if(index != -1)
{
snprintf(BUF,500,"%s", str.left(index + 2).toUtf8().data()); // QString转为char * 类型
qDebug() << "BUF info: " << BUF;
str.remove(0,index + 2);

// 处理获取到的数据,将其放入对应的控件中
// ....
}
}
}
// 发送数据,write ()
void MainWindow::DataSend()
{
serial->write(ui->DataSend->toPlainText().toLatin1()); // 串口发送数据
}

// 开关显示灯
void MainWindow::LED(bool changeColor)
{
if(changeColor == false)
{
// 显示绿色
ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 229, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
}
else
{
// 显示红色
ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
}
}

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

// 串口开关
void MainWindow::on_OpenSerialButton_clicked()
{
if(serial->isOpen()) // 如果串口打开了,先给他关闭
{
serial->clear();
serial->close();
// 关闭状态,按钮显示“打开串口”
ui->OpenSerialButton->setText("打开串口");
// 关闭状态,允许用户操作
ui->BaudBox->setDisabled(false);
ui->ParityBox->setDisabled(false);
ui->BitBox->setDisabled(false);
ui->StopBox->setDisabled(false);
ui->ControlBox->setDisabled(false);
// 禁止操作“发送字符操作”
ui->SendWordOrder->setDisabled(true);
ui->SendButton->setDisabled(true);
// 关闭状态,颜色为绿色
ui->OpenSerialButton->setStyleSheet("color: green;");
// 关闭,显示灯为红色
LED(true);
// 清空数据
ui->DataReceived->clear();
ui->DataSend->clear();
}
else // 如果串口关闭了,先给他打开
{
//当前选择的串口名字
serial->setPortName(ui->PortBox->currentText());
//用ReadWrite 的模式尝试打开串口,无法收发数据时,发出警告
if(!serial->open(QIODevice::ReadWrite))
{
QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);
return;
}
// 打开状态,按钮显示“关闭串口”
ui->OpenSerialButton->setText("关闭串口");
// 打开状态,禁止用户操作
ui->BaudBox->setDisabled(true);
ui->ParityBox->setDisabled(true);
ui->BitBox->setDisabled(true);
ui->StopBox->setDisabled(true);
ui->ControlBox->setDisabled(true);
// 允许操作“发送字符操作”
ui->SendWordOrder->setDisabled(false);
ui->SendButton->setDisabled(false);
// 打开状态,颜色为红色
ui->OpenSerialButton->setStyleSheet("color: red;");
// 打开,显示灯为绿色
LED(false);
}
}
// 控件中添加 #
void MainWindow::on_SendButton_clicked()
{
on_ClearButton_clicked();
ui->DataSend->append("#");
}
// 清空控件
void MainWindow::on_ClearButton_clicked()
{
ui->DataSend->setText("");
}
// 清空接收到的数据
void MainWindow::on_ClearShowButton_clicked()
{
ui->DataReceived->setText("");
}
// 点击发送后,获取串口信息并展示在接受控件中
void MainWindow::on_SendEditBtn1_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit1->text(); //获取发送框内容
ui->DataSend->setText(EditText); //将文本内容放在发送栏中
}

void MainWindow::on_SendEditBtn2_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit2->text(); //获取发送框内容

// qDebug() << "Edit1 text: " << EditText;

ui->DataSend->append(EditText); //将文本内容放在发送栏中
}

void MainWindow::on_SendEditBtn3_clicked()
{
on_ClearButton_clicked();
QString EditText = ui->Edit3->text(); //获取发送框内容

// qDebug() << "Edit1 text: " << EditText;

ui->DataSend->append(EditText); //将文本内容放在发送栏中
}


void MainWindow::on_SendWordOrder_clicked()
{
on_SendButton_clicked();
}

运行后效果:

 

举报

相关推荐

0 条评论