项目名称:基于Qt的串口调试助手
项目描述 :
开发了一款跨平台的串口通信调试工具,支持多种波特率、数据位、校验位配置,实现数据的收发、十六进制显示与发送、数据清空等核心功能。
技术栈 :
Qt/C++、QSerialPort、QTimer、Qt Designer
主要职责/实现功能 :
设计图形用户界面,实现串口参数(串口号、波特率、数据位等)的动态配置
实现串口数据的异步接收与实时显示,支持文本/十六进制两种显示模式
实现数据发送功能,支持十六进制格式发送
添加系统时间/日期实时显示,提升用户体验
通过定时器实现串口数据的轮询读取,保证数据不丢失
项目成果 :
工具运行稳定,可满足嵌入式开发中的基本串口调试需求。
软件架构图

界面布局:

完整代码:
cpp文件:
cpp
// mainwindow.h 对应的实现文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort>
#include <QSerialPortInfo>
// 构造函数:初始化界面、定时器、串口参数列表
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 1. 创建并启动系统时间刷新定时器
timer = new QTimer(this);
timer->start(); // 启动定时器(默认间隔)
connect(timer, SIGNAL(timeout()), this, SLOT(SetTime()));
// 2. 显示当前日期(格式:2025年01月01日 星期三)
QDate dateNow = QDate::currentDate();
ui->label_date->setText(QString("日期:%1").arg(dateNow.toString("yyyy年MM月dd日 dddd")));
// 3. 初始化串口状态标签
ui->label_serialPortStaut->setText("串口状态:关闭");
// 4. 创建串口读取定时器(每200ms检查一次数据)
ReadTimer = new QTimer(this);
ReadTimer->setInterval(200); // 设置时间间隔200毫秒
connect(ReadTimer, SIGNAL(timeout()), this, SLOT(ReadCom()));
// 5. 初始状态下发送按钮不可用(串口未打开)
ui->pushButton_send->setEnabled(false);
// 6. 默认勾选十六进制显示和发送
ui->checkBox_resieveHex->setCheckState(Qt::Checked);
ui->checkBox_sendHex->setCheckState(Qt::Checked);
// 7. 初始化串口参数下拉框
QStringList portList; // 串口号列表
QStringList baudList; // 波特率列表
QStringList parityList; // 校验位列表
QStringList dataBitsList; // 数据位列表
QStringList stopBitsList; // 停止位列表
// 添加常用串口号(COM1 ~ COM10)
portList << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6"
<< "COM7" << "COM8" << "COM9" << "COM10";
ui->comboBox_portName->addItems(portList);
ui->comboBox_portName->setCurrentIndex(0); // 默认选中COM1
// 添加常用波特率(从50到256000)
baudList << "50" << "75" << "100" << "134" << "150" << "200" << "300"
<< "600" << "1200" << "1800" << "2400" << "4800" << "9600"
<< "14400" << "19200" << "38400" << "56000" << "57600"
<< "76800" << "115200" << "128000" << "256000";
ui->comboBox_baudRate->addItems(baudList);
ui->comboBox_baudRate->setCurrentIndex(12); // 默认选中9600(索引12)
// 校验位:无、奇、偶
parityList << "无" << "奇" << "偶";
ui->comboBox_parity->addItems(parityList);
ui->comboBox_parity->setCurrentIndex(0); // 默认无校验
// 数据位:5、6、7、8
dataBitsList << "5" << "6" << "7" << "8";
ui->comboBox_dataBits->addItems(dataBitsList);
ui->comboBox_dataBits->setCurrentIndex(3); // 默认8位数据
// 停止位:1、1.5、2
stopBitsList << "1" << "1.5" << "2";
ui->comboBox_stopBits->addItems(stopBitsList);
ui->comboBox_stopBits->setCurrentIndex(0); // 默认1位停止位
}
// 析构函数:关闭串口并释放UI资源
MainWindow::~MainWindow()
{
if (serial && serial->isOpen())
serial->close(); // 关闭串口
delete ui; // 释放UI对象
}
// 定时器槽函数:更新时间显示
void MainWindow::SetTime()
{
QTime timeNow = QTime::currentTime();
ui->label_time->setText(QString("时间:%1").arg(timeNow.toString()));
}
// 发送按钮点击槽函数
void MainWindow::on_pushButton_send_clicked()
{
if (!serial->isOpen()) // 串口未打开则直接返回
return;
this->WriteCom(); // 调用实际发送函数
}
// 打开/关闭串口按钮槽函数
void MainWindow::on_pushButton_serialPortOprate_clicked()
{
// 当前状态为"打开串口",准备打开
if (ui->pushButton_serialPortOprate->text() == "打开串口")
{
QString portName = ui->comboBox_portName->currentText(); // 获取选择的串口号
serial = new QSerialPort(portName); // 创建串口对象
// 尝试以读写方式打开串口
if (serial->open(QIODevice::ReadWrite))
{
serial->flush(); // 清空缓冲区
// 设置波特率(从下拉框获取字符串并转为整数)
serial->setBaudRate((QSerialPort::BaudRate)ui->comboBox_baudRate->currentText().toInt());
// 设置数据位
serial->setDataBits((QSerialPort::DataBits)ui->comboBox_dataBits->currentText().toInt());
// 设置校验位(根据索引映射:0->无,1->奇,2->偶)
serial->setParity((QSerialPort::Parity)ui->comboBox_parity->currentIndex());
// 设置停止位(根据索引映射:0->1,1->1.5,2->2)
serial->setStopBits((QSerialPort::StopBits)ui->comboBox_stopBits->currentIndex());
// 关闭流控制(硬件/软件流控都不用)
serial->setFlowControl(QSerialPort::NoFlowControl);
// 更新界面状态
ui->pushButton_serialPortOprate->setText("关闭串口");
ui->label_serialPortStaut->setText("串口状态:打开");
this->ReadTimer->start(); // 启动读取定时器
ui->pushButton_send->setEnabled(true); // 启用发送按钮
}
}
else // 当前状态为"关闭串口",执行关闭操作
{
if (serial && serial->isOpen())
serial->close(); // 关闭串口
ui->pushButton_serialPortOprate->setText("打开串口");
ui->label_serialPortStaut->setText("串口状态:关闭");
this->ReadTimer->stop(); // 停止读取定时器
ui->pushButton_send->setDisabled(true); // 禁用发送按钮
}
}
// 定时读取串口数据(每200ms调用一次)
void MainWindow::ReadCom()
{
// 如果没有数据可读,直接返回
if (serial->bytesAvailable() <= 0)
return;
QByteArray buffer = serial->readAll(); // 读取所有可用数据
// 根据十六进制显示开关决定显示格式
if (IsHexReceive) // 十六进制模式
{
QString hexData = buffer.toHex(); // 将字节数组转为十六进制字符串
ui->textEdit->append(QString("接收:%1 时间:%2")
.arg(hexData)
.arg(QTime::currentTime().toString("HH:mm:ss")));
}
else // 普通文本模式
{
QString normalData = QString(buffer); // 直接按文本解释
ui->textEdit->append(QString("接收:%1 时间:%2")
.arg(normalData)
.arg(QTime::currentTime().toString("HH:mm:ss")));
}
}
// 发送数据函数
void MainWindow::WriteCom()
{
QString str = ui->lineEdit->text(); // 获取发送框内容
qDebug() << str; // 调试输出
if (!serial->isOpen()) // 串口未打开则返回
return;
QByteArray outData = str.toLatin1(); // QString转Latin1编码的字节数组
// 根据十六进制发送开关决定发送格式
if (IsHexSend) // 十六进制模式
{
outData = outData.toHex(); // 转为十六进制字符串
serial->write(outData);
}
else // 普通文本模式
{
serial->write(outData);
}
qDebug() << outData; // 调试输出发送内容
}
// 清空接收区按钮槽函数
void MainWindow::on_pushButton_clearRecieveData_clicked()
{
ui->textEdit->clear(); // 清空接收显示区域
}
// 清空发送区按钮槽函数
void MainWindow::on_pushButton_clearSendData_clicked()
{
ui->lineEdit->clear(); // 清空发送输入框
}
// 接收区十六进制复选框状态改变槽函数
void MainWindow::on_checkBox_resieveHex_stateChanged(int argHex)
{
IsHexReceive = (argHex == 0 ? false : true); // 非0即为true
}
// 发送区十六进制复选框状态改变槽函数
void MainWindow::on_checkBox_sendHex_stateChanged(int argHex)
{
IsHexSend = (argHex == 0 ? false : true);
}
h文件:
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTime>
#include <QTimer>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void initSerialPort();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
QTimer *timer;
QTimer *ReadTimer; //定时读取串口数据
QTimer *SendTimer; //定时发送串口数据
bool IsHexSend = false;//是否16进制数据发送
bool IsHexReceive = false;//是否16进制数据接收
private slots:
void SetTime(); //更新时间
void ReadCom(); //读取串口数据
void WriteCom(); //写串口数据
void on_pushButton_send_clicked();
void on_pushButton_serialPortOprate_clicked();
void on_pushButton_clearRecieveData_clicked();
void on_pushButton_clearSendData_clicked();
void on_checkBox_resieveHex_stateChanged(int arg1);
void on_checkBox_sendHex_stateChanged(int arg1);
};
#endif // MAINWINDOW_H