QT开发--串口通信
第十六章 串口通信
16.1 串口通信基础
串口通信主要通过DB9接口,适用于短距离(<10米)。关键参数包括:
- 波特率:每秒传输bit数,如9600。
- 数据位:信息包中的有效数据位数。
- 停止位:单个包的最后一位,通常为1或2位。
- 奇偶校验位:检错方式,分偶、奇校验。
16.1.1 QtSerialPort模块简介
QtSerialPort是QT5的附加模块,为硬件和虚拟串口提供接口。它简化串口应用开发,提供配置、I/O操作等功能。
使用QtSerialPort,需包含以下头文件:
#include <QSerialPortInfo>
#include <QSerialPort>
并在.pro文件中添加:
QT += serialport
QSerialPort类用于访问串口,
QSerialPortInfo用于获取串口信息。
可通过setPort()或setPortName()设置要访问的串口。
使用open()和close()打开和关闭串口。
串口打开后,可使用setBaudRate()等函数重新配置。
waitForReadyRead()和waitForBytesWritten()用于阻塞操作。
16.1.2 QSerialPort 成员函数
构造函数:
// 构造一个未初始化的QSerialPort对象,可选指定父对象
QSerialPort::QSerialPort(QObject *parent = nullptr) // 构造并初始化QSerialPort对象,指定端口名和可选的父对象
QSerialPort::QSerialPort(const QString &name, QObject *parent = nullptr) // 构造并初始化QSerialPort对象,根据QSerialPortInfo指定端口信息和可选的父对象
QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = nullptr)
关键方法:
bool atEnd() const:检查是否有数据可读。
qint64 bytesAvailable() const:返回可读数据字节数。
qint64 bytesToWrite() const:返回可写数据字节数。
void close():关闭串口。
void setPort(const QSerialPortInfo &serialPortInfo):设置串口信息。
void setPortName(const QString &name):设置串口名。
//波特率改变时触发信号
[signal] void baudRateChanged(qint32 baudRate, //新的波特率
QSerialPort::Directions directions) //波特率用于哪方
/*检查是否有数据可读,无数据可读返回true*/
[virtual] bool QSerialPort::atEnd() const;/*波特率改变后,信号触发*/
[signal] void QSerialPort::baudRateChanged(qint32 baudRate, //新的波特率QSerialPort::Directions directions) //波特率用于哪方
/*
QSerialPort::AllDirections //默认,表示读写方向都应用此波特率
QSerialPort::Input //仅用于输入方向
QSerialPort::Output //仅用于输出方向
*//*返回可读数据的字节数*/
[virtual] qint64 QSerialPort::bytesAvailable() const;/*返回可写数据的字节数*/
[virtual] qint64 QSerialPort::bytesToWrite() const;/*关闭串口*/
[virtual] void QSerialPort::close();/*设置串口端口信息为 serialPortInfo*/
void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo);/*设置串口名为name*/
void QSerialPort::setPortName(const QString &name);
16.2 QSerialPortInfo
16.2.1 QSerialPortInfo 简介
QSerialPortInfo 类用于提供系统中已有串口设备的信息。可通过其静态成员函数获取代表各串口的 QSerialPortInfo 对象链表。每个对象包含端口的详细信息,如端口名、系统位置、描述、制造商等,并可用于配置 QSerialPort 对象。
16.2.2 QSerialPortInfo 成员函数
构造函数
QSerialPortInfo(const QSerialPort &port);
QSerialPortInfo(const QString &name);
QSerialPortInfo(const QSerialPortInfo &other);
静态成员函数
static QList<QSerialPortInfo> availablePorts(); // 返回可用串口链表
static QList<qint32> standardBaudRates(); // 返回标准波特率链表
成员函数
QString description() const; // 返回串口描述
bool hasProductIdentifier() const; // 是否有生产编码
bool hasVendorIdentifier() const; // 是否有制造商编码
bool isBusy() const; // 串口是否正忙
QString manufacturer() const; // 返回制造商名称
QString portName() const; // 返回串口名称
quint16 productIdentifier() const; // 返回生产编码
QString serialNumber() const; // 返回序列号
QString systemLocation() const; // 返回系统位置
quint16 vendorIdentifier() const; // 返回制造商编码
void swap(QSerialPortInfo &other); // 交换两个对象
16.3 实现简易串口
打开/关闭串口:
当点击“打开串口”按钮时,配置串口参数并尝试打开串口。如果成功,禁用串口配置ComboBox,启用发送按钮,并更改按钮文本为“关闭串口”。
同时连接串口的 readyRead信号到 readData槽函数。
当点击“关闭串口”按钮时(即串口已打开状态),关闭串口,重新启用串口配置ComboBox,更改按钮文本为“打开串口”,并禁用发送按钮。
数据发送与接收:
点击发送按钮时,将发送文本框中的内容以Latin1编码写入串口。
点击清空接收/发送数据按钮时,清空相应的文本框内容。
当串口有数据可读时,readData槽函数被调用,读取所有可用数据,并将其追加到接收文本框中。
#ifndef MAINWINDOW_H // 防止头文件重复包含,如果已定义MAINWINDOW_H则不再次包含
#define MAINWINDOW_H // 包含必要的Qt库头文件
#include <QMainWindow> // 主窗口类
#include <QSerialPort> // 串口通信类
#include <QSerialPortInfo> // 串口信息类,用于获取系统中可用的串口信息
#include <QList> // 用于存储串口信息列表
#include <QDebug> // 用于调试输出 // Ui命名空间,包含UI类的声明(通常由Qt Designer生成)
namespace Ui {
class MainWindow;
} // MainWindow类,继承自QMainWindow
class MainWindow : public QMainWindow { Q_OBJECT // 使用Qt的宏,允许该类使用信号和槽机制 public: // 构造函数,explicit关键字防止隐式转换 explicit MainWindow(QWidget *parent = 0); // 析构函数 ~MainWindow(); private slots: // 私有槽函数,用于处理UI按钮点击事件 void on_btn_openConsole_clicked(); // 打开控制台按钮点击事件处理 void on_btn_send_clicked(); // 发送按钮点击事件处理 void on_btn_clearRecv_clicked(); // 清空接收区按钮点击事件处理 void on_btn_clearSend_clicked(); // 清空发送区按钮点击事件处理 void readData(); // 读取串口数据 private: // Ui类的指针,用于访问UI元素 Ui::MainWindow *ui; // QSerialPort类的指针,用于串口通信 QSerialPort *serial;
}; #endif // MAINWINDOW_H // 结束头文件保护
#include "mainwindow.h"
#include "ui_mainwindow.h" // 定义一个静态常量字符串,用于表示“不可用”或“无数据”的情况
static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A"); // MainWindow类的构造函数实现
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), // 调用基类的构造函数 ui(new Ui::MainWindow) { // 初始化UI类的指针 ui->setupUi(this); // 设置UI界面 // 初始化串口类的指针 serial = new QSerialPort; // 用于存储串口描述、制造商、序列号等信息的字符串 QString description; QString manufacturer; QString serialNumber; // 获取系统中可用的串口信息列表 QList<QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts(); // 输出当前系统可以使用的串口个数 qDebug() << "Total numbers of ports: " << serialPortInfos.count(); // 遍历所有可用的串口信息,并将其添加到ComboBox中 for (const QSerialPortInfo &serialPortInfo : serialPortInfos) { QStringList list; // 用于存储串口信息的字符串列表 description = serialPortInfo.description(); // 获取串口描述 manufacturer = serialPortInfo.manufacturer(); // 获取制造商信息 serialNumber = serialPortInfo.serialNumber(); // 获取序列号 // 将串口的相关信息添加到列表中,如果信息为空则使用blankString代替 list << serialPortInfo.portName() << (!description.isEmpty() ? description : blankString) << (!manufacturer.isEmpty() ? manufacturer : blankString) << (!serialNumber.isEmpty() ? serialNumber : blankString) << serialPortInfo.systemLocation() << (serialPortInfo.vendorIdentifier() ? QString::number(serialPortInfo.vendorIdentifier(), 16) : blankString) << (serialPortInfo.productIdentifier() ? QString::number(serialPortInfo.productIdentifier(), 16) : blankString); // 将串口名称作为第一项,其余信息作为关联数据添加到ComboBox中 ui->comboBox_serialPort->addItem(list.first(), list); } // 添加一个自定义选项到串口ComboBox中 ui->comboBox_serialPort->addItem(tr("custom")); // 设置波特率的ComboBox选项 ui->comboBox_baudRate->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); ui->comboBox_baudRate->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); ui->comboBox_baudRate->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); ui->comboBox_baudRate->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); ui->comboBox_baudRate->addItem(tr("Custom")); // 设置数据位的ComboBox选项 ui->comboBox_dataBits->addItem(QStringLiteral("5"), QSerialPort::Data5); ui->comboBox_dataBits->addItem(QStringLiteral("6"), QSerialPort::Data6); ui->comboBox_dataBits->addItem(QStringLiteral("7"), QSerialPort::Data7); ui->comboBox_dataBits->addItem(QStringLiteral("8"), QSerialPort::Data8); ui->comboBox_dataBits->setCurrentIndex(3); // 默认选择8数据位 // 设置奇偶校验位的ComboBox选项 ui->comboBox_parity->addItem(tr("None"), QSerialPort::NoParity); ui->comboBox_parity->addItem(tr("Even"), QSerialPort::EvenParity); ui->comboBox_parity->addItem(tr("Odd"), QSerialPort::OddParity); ui->comboBox_parity->addItem(tr("Mark"), QSerialPort::MarkParity); ui->comboBox_parity->addItem(tr("Space"), QSerialPort::SpaceParity); // 设置停止位的ComboBox选项 ui->comboBox_stopBit->addItem(QStringLiteral("1"), QSerialPort::OneStop); ui->comboBox_stopBit->addItem(QStringLiteral("2"), QSerialPort::TwoStop); // 设置流控的ComboBox选项 ui->comboBox_flowBit->addItem(tr("None"), QSerialPort::NoFlowControl); ui->comboBox_flowBit->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl); ui->comboBox_flowBit->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl); // 初始禁用发送按钮 ui->btn_send->setEnabled(false);
} // MainWindow类的析构函数实现
MainWindow::~MainWindow() { delete ui; // 释放UI类的指针所指向的内存
} // 打开串口按钮的槽函数实现
void MainWindow::on_btn_openConsole_clicked() { qDebug() << ui->btn_openConsole->text(); // 输出按钮的当前文本 if (ui->btn_openConsole->text() == tr("打开串口")) { // 配置串口参数 serial->setPortName(ui->comboBox_serialPort->currentText()); // 设置串口名称 serial->setBaudRate(ui->comboBox_baudRate->currentText().toInt()); // 设置波特率 serial->setDataBits(QSerialPort::Data8); // 设置数据位 serial->setParity(QSerialPort::NoParity); // 设置奇偶校验位 serial->setStopBits(QSerialPort::OneStop); // 设置停止位 serial->setFlowControl(QSerialPort::NoFlowControl); // 设置流控 // 尝试打开串口 if (serial->open(QIODevice::ReadWrite)) { // 禁用串口配置相关的ComboBox ui->comboBox_baudRate->setEnabled(false); ui->comboBox_dataBits->setEnabled(false); ui->comboBox_flowBit->setEnabled(false); ui->comboBox_parity->setEnabled(false); ui->comboBox_serialPort->setEnabled(false); ui->comboBox_stopBit->setEnabled(false); // 启用发送按钮 ui->btn_send->setEnabled(true); // 更改按钮文本 ui->btn_openConsole->setText(tr("关闭串口")); // 连接串口的readyRead信号到readData槽函数 connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); } } else { // 关闭串口 serial->close(); // 关闭串口连接 // 重新启用串口配置相关的ComboBox ui->comboBox_baudRate->setEnabled(true); ui->comboBox_dataBits->setEnabled(true); ui->comboBox_flowBit->setEnabled(true); ui->comboBox_parity->setEnabled(true); ui->comboBox_serialPort->setEnabled(true); ui->comboBox_stopBit->setEnabled(true); // 更改按钮文本 ui->btn_openConsole->setText(tr("打开串口")); // 禁用发送按钮 ui->btn_send->setEnabled(false); }
} // 发送数据按钮的槽函数实现
void MainWindow::on_btn_send_clicked() { // 将发送文本框中的内容以Latin1编码写入串口 serial->write(ui->textEdit_send->toPlainText().toLatin1());
} // 清空接收数据按钮的槽函数实现
void MainWindow::on_btn_clearRecv_clicked() { ui->textEdit_recv->clear(); // 清空接收文本框的内容
} // 清空发送数据按钮的槽函数实现
void MainWindow::on_btn_clearSend_clicked() { ui->textEdit_send->clear(); // 清空发送文本框的内容
} // 读取串口数据的槽函数实现
void MainWindow::readData() { QByteArray buf; // 定义一个字节数组用于存储读取到的数据 qDebug() << "readData: " << endl; // 输出调试信息 buf = serial->readAll(); // 从串口读取所有可用数据 if (!buf.isEmpty()) { // 如果读取到的数据不为空 QString str = ui->textEdit_recv->toPlainText(); // 获取接收文本框的当前内容 str += tr(buf); // 将读取到的数据追加到字符串中(注意:这里tr的使用可能是不必要的,除非需要翻译字节数组的内容) ui->textEdit_recv->clear(); // 清空接收文本框的内容 ui->textEdit_recv->append(str); // 将更新后的字符串添加到接收文本框中 }
}



相关文章:
QT开发--串口通信
第十六章 串口通信 16.1 串口通信基础 串口通信主要通过DB9接口,适用于短距离(<10米)。关键参数包括: 波特率:每秒传输bit数,如9600。数据位:信息包中的有效数据位数。停止位:…...
数据库(至少还的再花两天 )
1 连接查询 左连接 右连接 2 聚合函数 SQL 统计求和 求最值 count sum avg max min 3 SQL关键字 limit 分页 group by 分组 distinct 去重 4 Select执行顺序 from where group by order by 5 数据库三范式 原子性 唯一性 直接性 6 存储引擎 MyISAM InnoDB 7 …...
网络安全公司及其主要产品介绍
以下是一些全球领先的网络安全公司及其主要产品介绍: 一、思科(Cisco) 思科是全球最大的网络设备供应商之一,其网络安全产品以企业级解决方案为主,覆盖多种安全需求。 Cisco ASA(Adaptive Security Appli…...
orjson:高性能的Python JSON库
在Python中处理JSON数据是一项常见任务,标准库的json模块虽然功能齐全,但在性能方面还有提升空间。今天我要向大家介绍一个出色的第三方JSON库 - orjson。 orjson简介 orjson是一个快速、正确的Python JSON库。它具有以下主要特点: 性能卓越 - 在序列化和反序列化方面都比标准…...
常见几大排序算法
排序算法是计算机科学中的基本算法,它们将一个无序的数组或列表按特定顺序进行排列(如升序或降序)。常见的排序算法可以根据其时间复杂度、空间复杂度和适用场景分类。以下是几种常见的排序算法: 1. 冒泡排序(Bubble …...
Linux下CMake入门
CMake的基础知识 什么是 CMake CMake 是一个跨平台的构建工具,主要用于管理构建过程。CMake 不直接构建项目,而是生成特定平台上的构建系统(如 Unix 下的 Makefile,Windows 下的 Visual Studio 工程),然后…...
网络资源模板--Android Studio 实现简易记事本App
目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易记事本App 二、项目测试环境 三、项目详情 首页 创建一个空的笔记本列表 mNotebookList。使用该列表和指定的布局资源 item_notebook 创建…...
根据Vue对比来深入学习React 下 props 组件传值 插槽 样式操作 hooks 高阶组件 性能优化
文章目录 函数组件的特点props组件间的传值父传子看上例子传父兄弟组件传值祖先组件传值 插槽基础插槽具名插槽作用域插槽 样式操作**CSS Modules** 生命周期useRef常用hookuseStateuseEffectuseContextuseReduceruseMemouseCallback 高阶组件什么时候使用 react性能问题和优化…...
HTML(六)超链接
HTML讲解(一)body部分_html body-CSDN博客 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>title</title> </head><body><a href"https://blog.csdn.net/2301_8034953…...
【Coroutines】Implement Lua Coroutine by Kotlin - 2
Last Chapter Link 文章目录 Symmetric CoroutinesNon-Symmetric Coroutine SampleSymmetric Coroutine SampleHow to Implement Symmetric CoroutinesWonderful TricksCode DesignTail Recursion OptimizationFull Sources Symmetric Coroutines in last blog, we have talk…...
java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频)
这是什么系统? 资源获取方式再最下方(本次10月份活动福利,免费提供下载,自行到对应的方式1下载,csdn的0积分下载) java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频) 基于Java的扫雷游戏…...
AndroidLogger 使用问题
Q1:解压zip后,启动Notepad未看到AndroidLogger工具栏 请检查plugins下安装位置是否正确,必须与下图一致,再确认Notepad 是否为 x64 ? Q2:使用 adb 可以显示已连接,但是获取不到日志 暂时不确定问…...
数据库常见面试
8道面试题 目录 目录 7道面试题 1.怎样进行sql优化 4、group by优化 5、limit优化 6、count优化 7、update优化 2.。怎样查看sql执行情况呢(哪个关键字),说说你对这个关键字的认识 4) possible_key: 5) key 3.说说你对innodb和 myisam的理解 …...
boxplot 绘制箱线图,添加数据点
先看效果图 import matplotlib.pyplot as plt #! 解决不显示的问题:中文设置为宋体格式 plt.rcParams[font.family] ["Times New Roman", SimSun]def plot_boxplot(data_list, out_file, x_custom_labels):# 画图fig, ax plt.subplots(figsize(90, 6…...
用sdkman管理多个jdk切换
前言 最近项目前后端进行升级,需要在jdk8和jdk17两个版本切换。最简单的是通过手动切换,但切换过程太繁琐,修改环境变量,达到切换目的。于是尝试其它解决方案,最终确实使用sdkman工具。 sdkman 是一款面向Java开发者的…...
【AIGC】ChatGPT提示词Prompt高效编写模式:结构化Prompt、提示词生成器与单样本/少样本提示
💯前言 在如今AI技术迅猛发展的背景下,尽管像ChatGPT这样的大型语言模型具备强大的生成能力,但它们的输出质量有时仍难以完全满足我们的预期。为了让ChatGPT生成更加准确、可靠的内容,掌握高效的Prompt编写技巧变得尤为重要。本文…...
反调式实战(有道翻译窗口弹出)
1.添加脚本断点实现源码获取 2.Function构造器构造debugger 因为是窗口被弹出的情况,所以window.closefunction()构造debugger。 3.定位到影响弹出的JavaScript代码片段 反调试思想:置空和替换,所以将其JavaScript进行注释或者删除。 这里主…...
verilog端口使用注意事项
下图存在组合逻辑反馈环,即组合逻辑的输出反馈到输入(赋值的左右2边存在相同的信号),此种情况会造成系统不稳定。比如在data_in20的情况下,在data_out0 时候,输出的数据会反馈到输入,输入再输出,从而造成不…...
Docker常用命令大全汇总
Docker是一种流行的容器化平台,可以在一个独立的、隔离的环境中构建、部署和运行应用程序。了解Docker常用命令可以帮助我们更高效地管理容器,快速开发和部署应用。本文将整理一系列Docker的常用命令,便于日常使用和学习。 1 Docker基础命令 1.1 启动/停止/重启docker # …...
LVS-DR+Keepalived 高可用群集部署
LVS-DRKeepalived 高可用群集部署 Keepalived 的工作原理LVSKeepalived 高可用群集部署配置负载调度器(主、备相同)关闭防火墙和核心防护及准备IPVS模块配置keeplived(主、备DR 服务器上都要设置)启动 ipvsadm 服务调整 proc 响应…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
