当前位置: 首页 > news >正文

QT-串口,完结!

Qt串口

Qt串口编程是使用Qt框架进行串口通信的一种技术,它的主要作用在于实现应用程序与外部设备之间的数据交换,特别是那些通过串口进行通信的设备。串口通信广泛用于连接嵌入式系统、嵌入式设备和传感器、单片机、无线模块等外部硬件设备。它在很多嵌入式系统、嵌入式设备和传感器等应用中被广泛使用。

一、串口编程基础
1.1 串口通信基础

目前使用最广泛的串口为 DB9 接口,适用于较近距离的通信。一般小于10米,DB9接口有9个针脚。

串口通信的主要参数如下:

  1. 波特率:衡量通信速度的参数,表示每秒钟传送的bit的个数。例如9600波特表示每秒钟发送9600个bit。
  2. 数据位:衡量通信中实际数据位的参数,当计算机发送一个信息包,实际包含的有效数据位个数。
  3. 停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。
  4. 奇偶校验位:串口通信中一种检错方式。常用的检错方式有:偶、奇校验。

在这里插入图片描述

1.2 QtSerialPort模块简介

QtSerialPort模块是QT5中附加模块的一个模块,为硬件和虚拟的串口提供统一的接口。

串口由于其简单和可靠,目前在像嵌入式系统、机器人等工业中依旧用得很多。使用QtSerialPort模块,开发者可以大大缩短开发串口相关的应用程序的周期。

Qt SerialPort 提供了基本的功能,包括配置、I/O操作、获取和设置RS-232引脚的信号。

要在应用程序中使用QtSerialPort,需要包括如下的声明:

#include <QSerialPortInfo>
#include <QSerialPort>

要链接 QtSerialPort 模块,需要在.pro文件中添加如下内容:

QT += serialport

QSerialPort 提供了访问串口的接口函数。使用辅助类QSerialPortInfo可以获取可用的串口信息。将 QSerialPortInfo 辅助类对象做为参数,使用setPort()setPortName()函数可以设置要访问的串口设备。
设置好端口后,可以使用open()函数以只读、只写或读写的模式打开使用。使用close()函数关闭串口并且取消IO操作。

注意:串口使用独占方式打开

串口成功打开后,QSerialPort会尝试确定串口的当前配置并初始化。可以使用setBaudRate()setDataBits()setParity()

setStopBits()setFlowControl()函数重新配置端口设置。

有一对名为QSerialPort::dataTerminalReadyQSerialPort::requestToSend的属性QSerialPort提供了中止正在调用线程直到

信号触发的一系列函数。这些函数用于阻塞串口。

waitForReadyRead():阻塞调用,直到有新的数据可读

waitForBytesWritten():阻塞调用,直到数据以及写入串口

阻塞串口编程与非阻塞串口编程完全不同。阻塞串口不会要求时间循环并且通常会简化代码。然而,在GUI程序中,为了避免冻结用户界面,阻塞串口编程只能用于非GUI线程。

QSerialPort也能使用 QTextStreamQDataStream 的流操作符。在试图使用流操作符 >> 读时,需要确保有足够可用的数据。

1.3 QSerialPort 成员函数

构造函数

QSerialPort::QSerialPort(QObject *parent = Q_NULLPTR)
QSerialPort::QSerialPort(const QString &name, QObject *parent = Q_NULLPTR)
QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = Q_NULLPTR)

如果当前没有数据可读,返回 true

[virtual] bool QSerialPort::atEnd() const

波特率改变后,信号触发

[signal] void QSerialPort::baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)

返回可读数据的字节数

[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)
#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建串口对象(无父对象)QSerialPort serial;// 设置串口名serial.setPortName("COM3");  // 右侧注释:指定要操作的串口设备名// 打开串口(读写模式)if (!serial.open(QSerialPort::ReadWrite)) {qDebug() << "串口打开失败";return -1;}// 设置波特率serial.setBaudRate(QSerialPort::Baud9600); // 右侧注释:设置通信速率为9600// 设置数据位、校验位、停止位serial.setDataBits(QSerialPort::Data8);    // 数据位8serial.setParity(QSerialPort::NoParity);   // 无校验serial.setStopBits(QSerialPort::OneStop);  // 1个停止位serial.setFlowControl(QSerialPort::NoFlowControl); // 无流控// 检查是否有可读数据if (serial.atEnd()) { // 右侧注释:如果当前没有数据可读,则返回trueqDebug() << "没有可读数据";}// 获取可读数据字节数qint64 bytesAvailable = serial.bytesAvailable(); // 右侧注释:返回当前可读数据字节数qDebug() << "可读字节数:" << bytesAvailable;// 写入数据QByteArray data = "Hello Serial";qint64 bytesWritten = serial.write(data); // 右侧注释:写入数据到串口,返回写入字节数qDebug() << "写入字节数:" << bytesWritten;// 获取等待写入的字节数qint64 toWrite = serial.bytesToWrite(); // 右侧注释:返回仍然在缓冲区等待写入的数据字节数qDebug() << "待写字节数:" << toWrite;// 关闭串口serial.close(); // 右侧注释:关闭串口设备return a.exec();
}
二、QSerialPortInfo
2.1 QSerialPortInfo简介

QSerialPortInfo 类提供已有串口设备的信息。使用 QSerialPortInfo 类的静态成员函数生成 QSerialPortInfo 对象的链表。

链表中的每个QSerialPortInfo对象代表一个串口,每个串口可以使用端口名、系统定位、描述、制造商查询。QSerialPortInfo

对象也可以用做QSerialPort类的setPort()成员函数的参数。

2.2 QSerialPortInfo成员函数

构造函数

QSerialPortInfo::QSerialPortInfo(const QSerialPort &port)
QSerialPortInfo::QSerialPortInfo(const QString &name)
QSerialPortInfo::QSerialPortInfo(const QSerialPortInfo &other)

返回当前系统可用串口的链表

[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()

如果串口可用,返回串口的描述信息

QString QSerialPortInfo::description() const

如果有一个合法的16位生产码,返回true

bool QSerialPortInfo::hasProductIdentifier() const

如果有一个合法的16位制造商编码,返回true

bool QSerialPortInfo::hasVendorIdentifier() const

如果串口当前正忙,返回true

bool QSerialPortInfo::isBusy() const

如果串口可用,返回串口的制造商的名字

QString QSerialPortInfo::manufacturer() const

返回串口的名字

QString QSerialPortInfo::portName() const

如果串口可用,返回串口的16位的生产编码

quint16 QSerialPortInfo::productIdentifier() const

如果串口可用,返回串口的序列号

QString QSerialPortInfo::serialNumber() const

返回目标平台支持的可用的标准波特率的链表

[static] QList<qint32> QSerialPortInfo::standardBaudRates()

使用other交换QSerialPortInfo对象

void QSerialPortInfo::swap(QSerialPortInfo &other)

返回串口的系统位置

QString QSerialPortInfo::systemLocation() const

如果串口可用,返回16位的制造商编码

quint16 QSerialPortInfo::vendorIdentifier() const
#include <QCoreApplication>
#include <QSerialPortInfo>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 获取系统当前可用串口的链表QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();  // 静态函数,返回所有可用串口信息// 遍历每一个串口foreach (const QSerialPortInfo &info, ports) {qDebug() << "--------------------------------------";qDebug() << "端口名:" << info.portName();                 // 返回串口的名字,例如 "COM3"qDebug() << "系统位置:" << info.systemLocation();         // 串口在系统中的路径,例如 "/dev/ttyS0" 或 "COM3"qDebug() << "描述信息:" << info.description();            // 返回串口的描述,例如 "USB-SERIAL CH340"qDebug() << "制造商:" << info.manufacturer();             // 返回串口制造商,例如 "wch.cn"qDebug() << "序列号:" << info.serialNumber();             // 返回串口序列号(若有)if (info.hasVendorIdentifier()) {                         // 判断是否有合法的16位制造商编码qDebug() << "厂商ID:" << info.vendorIdentifier();     // 返回厂商ID,例如 6790}if (info.hasProductIdentifier()) {                        // 判断是否有合法的16位产品编码qDebug() << "产品ID:" << info.productIdentifier();    // 返回产品ID,例如 29987}qDebug() << "是否忙:" << (info.isBusy() ? "是" : "否");   // 串口当前是否被占用}// 获取支持的标准波特率列表QList<qint32> baudRates = QSerialPortInfo::standardBaudRates(); // 返回可用的标准波特率链表qDebug() << "支持的标准波特率:" << baudRates;return a.exec();
}
2.3 QSerialPortInfo显示串口信息实例
#include <QCoreApplication>
#include <QSerialPortInfo>
#include <QSerialPort>
#include <QList>
#include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();   // 获取系统中可用串口列表qDebug() << "Total number of availiable ports:" << list.count();   // 输出可用串口的总数foreach(const QSerialPortInfo &serialportinfo, list) {qDebug() << "Port: " << serialportinfo.portName();             // 串口名称,例如 "COM3"qDebug() << "Location: " << serialportinfo.systemLocation();   // 串口系统位置,例如 "COM3" 或 "/dev/ttyUSB0"qDebug() << "Description: " << serialportinfo.description();   // 串口描述信息,例如 "USB-SERIAL CH340"qDebug() << "Manufactutor: " << serialportinfo.manufacturer(); // 制造商名称,例如 "wch.cn"qDebug() << "Vendor Indentifier: " << serialportinfo.vendorIdentifier(); // 厂商ID,16位十六进制数qDebug() << "Busy: " << serialportinfo.isBusy();               // 串口是否被占用,true/false}return a.exec();   // 进入事件循环(QCoreApplication要求)
}

实现简易串口

mainwindow.h

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>
#include <QSerialPort>   // 串口类
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }  // 前向声明 UI 界面类
QT_END_NAMESPACEclass MyWidget : public QWidget
{Q_OBJECT   // Qt 宏,启用信号槽机制public:MyWidget(QWidget *parent = nullptr);   // 构造函数,初始化窗口~MyWidget();                           // 析构函数,释放资源public slots:void onOpenPort();        // 打开串口的槽函数void reviceData();        // 接收串口消息的槽函数void on_pushButton_clicked(); // 发送消息的槽函数(按钮点击)private:Ui::MyWidget *ui;     // 界面指针,管理 UI 控件QSerialPort *serial;  // 串口对象,用于收发数据
};
#endif // MYWIDGET_H

mainwindow.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QSerialPortInfo>
#include <QDebug>
#include <QSerialPort>MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);serial = new QSerialPort;   // 创建串口对象//// 设置端口    QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();  // 获取可用串口列表for(auto info: list){ui->comboBox_port->addItem(info.portName());  // 将串口名添加到下拉框}// 设置波特率ui->comboBox_baudRate->addItem("9600", QSerialPort::Baud9600);ui->comboBox_baudRate->addItem("19200", QSerialPort::Baud19200);ui->comboBox_baudRate->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);ui->comboBox_baudRate->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);// 设置数据位ui->comboBox_dataBit->addItem(QStringLiteral("5"), QSerialPort::Data5);ui->comboBox_dataBit->addItem(QStringLiteral("6"), QSerialPort::Data6);ui->comboBox_dataBit->addItem(QStringLiteral("7"), QSerialPort::Data7);ui->comboBox_dataBit->addItem(QStringLiteral("8"), QSerialPort::Data8);// 设置奇偶校验位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);// 设置停止位ui->comboBox_stopBit->addItem(QStringLiteral("1"), QSerialPort::OneStop);ui->comboBox_stopBit->addItem(QStringLiteral("2"), QSerialPort::TwoStop);// 添加流控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);// 打开串口按钮点击信号连接到槽函数connect(ui->pushButton_3,&QPushButton::clicked,this,&MyWidget::onOpenPort);
}MyWidget::~MyWidget()
{delete ui;  // 释放 UI 内存
}void MyWidget::onOpenPort()
{if(ui->pushButton_3->text() == "打开串口"){  // 如果按钮显示“打开串口”,说明串口未打开// 获取串口信息并设置serial->setPortName(ui->comboBox_port->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)){  // 打开串口ui->pushButton_3->setText("关闭串口"); // 按钮改为关闭串口qDebug() << "打开串口" << serial->portName() << "成功";// 串口有新数据可读时触发 reviceData() 槽connect(serial,&QSerialPort::readyRead,this,&MyWidget::reviceData);}} else {// 关闭串口if(serial->isOpen()){serial->close();   // 关闭串口}ui->pushButton_3->setText("打开串口");  // 按钮改为打开串口}
}void MyWidget::reviceData()
{QByteArray buf;buf += serial->readAll();  // 读取串口缓冲区所有数据if(!buf.isEmpty()){ui->plainTextEdit->appendPlainText(buf);  // 显示到文本框}
}void MyWidget::on_pushButton_clicked()
{serial->write(ui->plainTextEdit_2->toPlainText().toUtf8()); // 将输入框数据写入串口
}
三、图形界面设计
3.1 图形界面设计如图所示

在这里插入图片描述

3.2 图形界面相关属性设置

在这里插入图片描述

3.3 测试结果

在这里插入图片描述

http://www.dtcms.com/a/394530.html

相关文章:

  • Git常用命令合集
  • Qt(模态对话框的切换)
  • QT-模型视图结构
  • C语言 C语句
  • 《理解Reactor网络编程模型》
  • Mirror Maze 镜面反射
  • 一个案例弄懂nfs
  • 在飞牛NAS使用Lucky做动态解析到域名?
  • 多实例 MySQL 部署
  • 使用批处理脚本快速切换 Claude API 实现多平台环境配置
  • SkyDiffusion:用 BEV 视角打开街景→航拍图像合成新范式
  • 免费下载适用于 Windows PC 的 Pixologic Zbrush 2026
  • 10.eNSP下载及安装教程(2025年9月21日)
  • Qt 实战 之 打包部署
  • QT-文件
  • 2001-2022年全国地级市高铁开通数据
  • TenstoRT加速YOLOv11——C++端加速
  • 面试技巧第三篇:嵌入式操作系统基础考点:任务、调度和中断
  • 简单使用Vanna
  • 【面板数据】各省环境保护支出统计数据集(2007-2023年)
  • 无需格式转换!FileOptimizer将文件体积压至极致的软件
  • 【论文速递】2025年第17周(Apr-20-26)(Robotics/Embodied AI/LLM)
  • Spring Framework 入门:传统 XML 配置启动方式详解
  • 构建AI智能体:四十、K-Means++与RAG的融合创新:智能聚类与检索增强生成的深度应用
  • Python 中,判断元素是否存在于列表(list)和判断键是否存在于字典(dict)
  • 如何在 Windows 上恢复已删除/未保存的 PowerPoint 文件 - 4 种快速方法
  • 【含文档+PPT+源码】基于过滤协同算法的城市旅游网站的设计与实现
  • week 2
  • Core Animation基础
  • OpenVLC解析