Qt串口通信开发教程:Linux下的串口调试工具实现
文章前言:
源码地址:https://github.com/haoxiliangluo/robot_control
不用做ros开发的可以将串口部分复制到新的项目中,也可以直接cmake使用,如果直接使用的话,请不要连接rosmaster,这可能会导致程序崩溃。
本项目是我大一下学期时候在Linux为调试串口方便写的,当时用的都是很简单的语法,也没有开多线程,所以在一些方面可能为有一些问题,等我抽出来空再将他分离出来,并进行优化。
1. 项目概述
本文介绍一个基于Qt5和ROS的串口通信工具,该工具提供了一套完整的串口通信解决方案,可用于各种串口设备的调试和数据传输。工具具有以下特点:
- 自动检测和显示系统可用串口设备
- 完整的串口参数配置(波特率、数据位、停止位、校验位)
- 支持ASCII和十六进制数据的收发与显示
- 大数据量自动清屏功能
- 串口数据保存功能
- 自动重连断开的串口
- 添加时间戳功能
项目效果:

2. 开发环境配置
2.1 开发环境
- 操作系统:Ubuntu 20.04
- ROS版本:ROS Noetic
- Qt版本:Qt 5.14.2(也可使用Qt 5.12或更高版本)
- 编译器:GCC 9.3.0
- 构建工具:CMake 3.16.3
2.2 依赖库
- QtSerialPort:Qt提供的串口通信模块
- QtWidgets:Qt图形界面库
- ROS相关库(可选,用于ROS集成)
2.3 环境配置
-
安装Qt开发环境:
bashsudo apt-get install qt5-default qtcreator
-
安装Qt串口模块:
bashsudo apt-get install libqt5serialport5-dev
-
安装ROS(如果需要ROS集成):
bash# 按ROS官方指南安装ROS Noetic
3. 项目结构
serial/
├── CMakeLists.txt # CMake构建脚本
├── package.xml # ROS包配置文件
├── mainpage.dox # 文档配置
├── resources/ # 资源文件目录
│ └── images.qrc # Qt资源配置文件
├── ui/ # UI文件目录
│ └── main_window.ui # 主窗口UI设计文件
├── include/ # 头文件目录
│ └── serailDemo/ # 项目头文件
│ ├── main_window.hpp # 主窗口类定义
│ └── qnode.hpp # ROS节点类定义
└── src/ # 源代码目录
├── main.cpp # 主函数
├── main_window.cpp # 主窗口类实现
└── qnode.cpp # ROS节点类实现
4. 核心功能实现
4.1 串口设备检测
使用QSerialPortInfo
类获取系统可用串口设备列表:
cpp
void MainWindow::report()
{
ui.serial_port_2->clear(); //清空下拉菜单
portList = QSerialPortInfo::availablePorts(); //获取端口列表
//添加下拉菜单
for (QSerialPortInfo &i : portList)
{
ui.serial_port_2->addItem(i.portName());
}
}
4.2 串口参数配置
设置串口参数,包括波特率、数据位、停止位和校验位:
cpp
void MainWindow::slot_open_serial()
{
//相当于sudo,pkexec一般用于图形化编程
QString command = "pkexec chmod 666 /dev/" + portList.at(ui.serial_port_2->currentIndex()).portName();
system(command.toUtf8());
update_serial_date();
serial.setParity(parity);
serial.setBaudRate(baudRate);
serial.setDataBits(dataBits);
serial.setStopBits(stopBits);
if (serial.open(QIODevice::ReadWrite)) {
logMessage("串口打开成功!");
} else {
logMessage("串口打开失败!");
qDebug() << serial.error();
}
}
4.3 数据发送功能
实现数据发送,支持ASCII和十六进制格式:
cpp
void MainWindow::sendMessge() {
if (serial.isOpen()) {
QString message = ui.textEdit->toPlainText();
QByteArray data = message.toUtf8();
if(ui.checkBox_3->isChecked())
{
message = data.toHex(' ').toUpper(); // 将数据转换为十六进制字符串,并用空格分隔
serial.write(data);
}
else
{
serial.write(data);
}
receivedDataSize += data.size();
// 检查是否需要200k清屏
if(ui.checkBox_5->isChecked() && receivedDataSize >= 200 * 1024)
{
cleanAccept();
receivedDataSize = 0;
}
logMessage("发送: " + message);
} else {
logMessage("串口并没有被打开.");
QMessageBox::warning(this, "warning!", "串口并没有被打开,脑子不要可以捐了.");
}
}
4.4 数据接收功能
使用QSerialPort::read
方法读取串口数据,支持ASCII和十六进制显示:
cpp
void MainWindow::readSerialData()
{
while (serial.canReadLine()) {
QByteArray data = serial.read(serial.bytesAvailable());
receivedDataSize += data.size();
if (ui.checkBox_5->isChecked() && receivedDataSize >= 200 * 1024) {
cleanAccept();
receivedDataSize = 0;
}
QString message;
if (ui.checkBox_2->isChecked()) {
message = toHex(data);
} else {
message = QString::fromUtf8(data);
}
logMessage("接收: "+message);
}
}
4.5 十六进制转换
实现数据与十六进制字符串之间的转换:
cpp
QString MainWindow::toHex(const QByteArray &data)
{
QString hexString;
for (char byte : data) {
hexString.append(QString("%1 ").arg(static_cast<unsigned char>(byte), 2, 16, QChar('0')).toUpper());
}
return hexString.trimmed();
}
4.6 自动重连功能
检测串口错误并自动尝试重新连接:
cpp
void MainWindow::handleSerialError(QSerialPort::SerialPortError error) {
if (error == QSerialPort::ResourceError) {
logMessage("串口连接断开,尝试重新连接...");
serial.close();
QTimer::singleShot(1000, this, &MainWindow::slot_open_serial);
}
}
4.7 保存数据功能
将接收的数据保存到文件:
cpp
void MainWindow::save_data()
{
QString filename = QFileDialog::getSaveFileName(this, tr("选择保存路径"), "");
QFile file(filename);
file.open(QIODevice::ReadWrite | QIODevice::Text);
//获取日志信息
QStringList saveData;
for(int i=0; i<ui.listWidget->count(); i++)
{
QListWidgetItem* item = ui.listWidget->item(i);
saveData << item->text();
}
// 将 QStringList 转换为单个 QString
QString saveDataString = saveData.join("\n");
// 写入日志信息
if (file.write(saveDataString.toUtf8()) > 0) {
// 弹出成功对话框
QMessageBox::information(this, tr("保存数据"), tr("保存成功!"));
} else {
QMessageBox::warning(this, tr("保存数据"), tr("保存失败!"));
}
}
5. CMake配置
项目使用CMake构建,以下是CMakeLists.txt
的核心部分:
cmake
cmake_minimum_required(VERSION 2.8.0)
project(serailDemo)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_PREFIX_PATH "/usr/lib/x86_64-linux-gnu/cmake/Qt5")
find_package(catkin REQUIRED COMPONENTS roscpp)
include_directories(${catkin_INCLUDE_DIRS})
find_package(Qt5 REQUIRED Core Widgets SerialPort)
set(QT_LIBRARIES Qt5::Widgets Qt5::SerialPort)
catkin_package()
file(GLOB QT_FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ui/*.ui)
file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/serailDemo/*.hpp *.h)
QT5_ADD_RESOURCES(QT_RESOURCES_CPP ${QT_RESOURCES})
QT5_WRAP_UI(QT_FORMS_HPP ${QT_FORMS})
QT5_WRAP_CPP(QT_MOC_HPP ${QT_MOC})
file(GLOB_RECURSE QT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)
add_executable(serailDemo ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_FORMS_HPP} ${QT_MOC_HPP})
target_link_libraries(serailDemo ${QT_LIBRARIES} ${catkin_LIBRARIES})
install(TARGETS serailDemo RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
6. UI设计
通过Qt Designer创建界面,主要包含:
- 串口配置区域:用于选择串口设备和设置串口参数
- 接收区域:显示接收到的数据
- 发送区域:用于编辑和发送数据
- 控制按钮:打开/关闭串口、清空接收/发送区、保存数据等
- 选项设置:十六进制显示/发送、添加时间戳、自动清屏等
UI文件通过QT5_WRAP_UI
命令转换为C++头文件,并在主窗口类中使用。
7. 编译与运行
7.1 使用catkin编译
bash
# 在工作空间根目录下
catkin_make
7.2 运行程序
bash
# 在工作空间根目录下
source devel/setup.bash
rosrun serailDemo serailDemo#用ros开发的
./build/devel/lib/serailDemo #原生linux开发的
8. 使用指南
- 选择串口设备:从下拉菜单中选择要使用的串口设备
- 配置串口参数:设置波特率、数据位、停止位和校验位
- 打开串口:点击"打开串口"按钮
- 发送数据:在发送区输入要发送的数据,点击"发送消息"按钮
- 接收数据:接收到的数据将显示在接收区
- 特殊功能 :
- 勾选"16进制显示"可将接收到的数据以十六进制显示
- 勾选"16进制发送"可将发送的数据以十六进制发送
- 勾选"200k清屏"当接收数据量超过200KB时自动清空接收区
- 勾选"添加时间头"在日志前添加时间戳
- 保存数据:点击"保存串口数据"按钮将接收到的数据保存到文件
9. 常见问题与解决方案
-
无法打开串口
- 检查串口权限:确保当前用户有访问串口设备的权限
- 检查串口是否被其他程序占用
- 检查串口设备是否正确连接
-
数据接收显示乱码
- 检查波特率设置是否正确
- 检查数据位、停止位、校验位是否与设备匹配
- 尝试以十六进制模式查看数据
-
程序闪退或卡死
- 检查串口连接是否稳定
- 减少高频率大数据量的传输
- 启用自动清屏功能
10. 拓展与改进
本项目还可以进行以下改进:
- 添加数据绘图功能,实时显示串口数据
- 增加数据协议解析功能
- 支持多串口同时操作
11. 总结
本文介绍了一个基于Qt和ROS的串口通信工具的实现过程,包括环境配置、核心功能实现、UI设计和使用说明。该工具功能完善,界面友好,适用于各种串口设备的调试和开发工作。通过这个项目,我们可以了解Qt串口通信的基本原理和实现方法,为进一步的串口应用开发打下基础。
希望这篇教程对大家学习Qt串口通信开发有所帮助!如有问题欢迎在评论区留言讨论。
欢迎分享、点赞、收藏!如果您对这个项目有兴趣,可以到我的GitHub仓库查看完整代码。