Qt5实现Windows平台串口通信
一、环境配置
-
开发环境: Qt 5.15.2+ (MSVC 2019编译器) Windows 10/11
-
依赖配置:
# .pro文件配置 QT += serialport widgets LIBS += -lQt5SerialPort
二、界面设计
1. 控件布局
<!-- mainwindow.ui -->
<widget class="QMainWindow" name="MainWindow">
<layout class="QGridLayout">
<!-- 串口配置区 -->
<item row="0" column="0">
<QLabel text="串口号"/>
</item>
<item row="0" column="1">
<QComboBox objectName="cmbPort"/>
</item>
<!-- 波特率设置 -->
<item row="1" column="0">
<QLabel text="波特率"/>
</item>
<item row="1" column="1">
<QComboBox objectName="cmbBaudRate"/>
</item>
<!-- 控制按钮 -->
<item row="2" column="0" colspan="2">
<QPushButton text="打开串口" objectName="btnOpen"/>
</item>
<!-- 数据收发区 -->
<item row="3" column="0">
<QPlainTextEdit objectName="txtSend"/>
</item>
<item row="3" column="1">
<QPlainTextEdit objectName="txtRecv"/>
</item>
<!-- 发送按钮 -->
<item row="4" column="0" colspan="2">
<QPushButton text="发送数据" objectName="btnSend"/>
</item>
</layout>
</widget>
三、核心代码实现
1. 头文件定义
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSerialPort>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_btnOpen_clicked();
void on_btnSend_clicked();
void serialRead();
private:
void initSerialPort();
void populatePorts();
Ui::MainWindow *ui;
QSerialPort *serial;
};
#endif // MAINWINDOW_H
2. 实现文件
// mainwindow.cpp
#include "mainwindow.h"
#include <QSerialPortInfo>
#include <QByteArray>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始化串口
serial = new QSerialPort(this);
initSerialPort();
populatePorts();
// 信号槽连接
connect(ui->btnOpen, &QPushButton::clicked, this, &MainWindow::on_btnOpen_clicked);
connect(ui->btnSend, &QPushButton::clicked, this, &MainWindow::on_btnSend_clicked);
connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialRead);
}
MainWindow::~MainWindow()
{
if(serial->isOpen()) serial->close();
delete ui;
}
void MainWindow::initSerialPort()
{
// 配置默认参数
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
}
void MainWindow::populatePorts()
{
ui->cmbPort->clear();
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cmbPort->addItem(info.portName());
}
}
void MainWindow::on_btnOpen_clicked()
{
if(serial->isOpen()) {
serial->close();
ui->btnOpen->setText("打开串口");
} else {
serial->setPortName(ui->cmbPort->currentText());
if(serial->open(QIODevice::ReadWrite)) {
ui->btnOpen->setText("关闭串口");
} else {
QMessageBox::critical(this, "错误", serial->errorString());
}
}
}
void MainWindow::on_btnSend_clicked()
{
QByteArray data = ui->txtSend->toPlainText().toUtf8();
if(!data.isEmpty()) {
qint64 bytes = serial->write(data);
if(bytes == -1) {
QMessageBox::warning(this, "发送失败", serial->errorString());
}
}
}
void MainWindow::serialRead()
{
QByteArray buffer = serial->readAll();
if(!buffer.isEmpty()) {
ui->txtRecv->appendPlainText(QString::fromUtf8(buffer));
}
}
四、功能扩展
1. 十六进制支持
// 在发送函数中添加HEX转换
void MainWindow::on_btnSend_clicked()
{
QString text = ui->txtSend->toPlainText();
QByteArray data;
if(ui->chkHexSend->isChecked()) {
bool ok;
data = QByteArray::fromHex(text.toUtf8(), &ok);
if(!ok) {
QMessageBox::warning(this, "错误", "无效的HEX格式");
return;
}
} else {
data = text.toUtf8();
}
serial->write(data);
}
2. 数据校验
// 在配置函数中添加校验位设置
void MainWindow::setParity(QSerialPort::Parity parity) {
serial->setParity(parity);
}
// 示例:CRC16校验
quint16 MainWindow::calculateCRC(const QByteArray &data) {
quint16 crc = 0xFFFF;
for(auto byte : data) {
crc ^= (quint16)byte << 8;
for(int i=0; i<8; i++) {
if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
else crc <<= 1;
}
}
return crc;
}
五、调试技巧
-
虚拟串口测试: 使用VSPD创建虚拟串口对(如COM3 <-> COM4) 在程序中选择不同端口测试双向通信
-
数据监控:
// 添加调试输出 qDebug() << "Received:" << buffer.toHex(' ') << "Length:" << buffer.size(); -
流量控制:
// 启用硬件流控制 serial->setFlowControl(QSerialPort::HardwareControl);
六、编译与运行
-
构建配置:
qmake mainwindow.pro make -
运行验证: 确保COM端口未被占用 通过设备管理器确认串口参数匹配
参考代码 Qt5串口通信程序 www.youwenfan.com/contentcnl/69949.html
七、常见问题处理
| 现象 | 解决方案 |
|---|---|
| 无法打开串口 | 检查端口号是否正确,关闭占用程序 |
| 数据丢失 | 增加接收缓冲区,优化读取频率 |
| 显示乱码 | 统一使用UTF-8编码,添加校验逻辑 |
| 高波特率不稳定 | 降低波特率,检查线缆质量 |
八、工程结构
SerialDemo/
├── Src/
│ ├── main.cpp
│ ├── mainwindow.cpp
│ └── mainwindow.h
├── Res/
│ └── mainwindow.ui
└── SerialDemo.pro

浙公网安备 33010602011771号