Qt的QSerialPort 使用注意事项

本文详细阐述了Qt库中QSerialPort组件的使用时需要注意的两个关键点:避免跨线程操作和正确区分同步与异步方法。同步方法如waitForReadyRead和waitForByteWritten,异步信号如dataReady和byteWritten,两者搭配需谨慎。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本用法就不说了,说一下注意点:

1、不可以跨线程使用,比如GUI构造,传指针给子线程,NO!

2、同步和异步方法不可以混用,同步包括waitForReadyRead, waitForByteWritten这2个函数;异步方法包括dataReady, byteWritten等信号

继续:Qt的QSerialPort 使用注意事项-3YL的博客 (labisart.com)

#include "qserial.h" #include<QDebug> qserial::qserial(Ui::MainWindow *ui, QObject *parent):QObject(parent), ui(ui), serialPort(new QSerialPort(this)) { QObject::connect(serialPort, &QSerialPort::readyRead, this, &qserial::onReadyRead); QList<QSerialPortInfo> PORT=QSerialPortInfo::availablePorts(); //获取可用串口 QList<qint32> bands=QSerialPortInfo::standardBaudRates(); //获取波特率 foreach (const QSerialPortInfo &port, PORT) { ui->port_chose->addItem(port.portName()); //将可用串口传入控件 } foreach ( qint32 band, bands) { ui->band_rate->addItem(QString::number(band)); //将可用波特率传入控件 } ui->band_rate->setCurrentText("115200"); } qserial::~qserial() { delete serialPort; delete ui; } bool qserial::connect() { // 设置串口名称(根据你的系统,可能需要使用具体的端口名称) serialPort->setPortName(ui->port_chose->currentText()); // 设置波特率 serialPort->setBaudRate(ui->band_rate->currentText().toInt()); // 设置数据位 serialPort->setDataBits(QSerialPort::Data8); // 设置停止位 serialPort->setParity(QSerialPort::NoParity); // 设置停止位长度 serialPort->setStopBits(QSerialPort::OneStop); // 设置流控制 serialPort->setFlowControl(QSerialPort::NoFlowControl); if (!serialPort->open(QIODevice::ReadWrite)) { return false; //返回打开失败 } else { return true; //返回打开成功 } } void qserial::dis_connect() { serialPort->close(); //关闭串口 } void qserial::onReadyRead() { // 读取所有可用数据 m_buffer += serialPort->readAll(); // 持续处理完整数据帧 while(true) { // 查找换行符位置 int endIndex = m_buffer.indexOf('\n'); if(endIndex == -1) break; // 没有完整帧则退出 // 提取完整数据(包含换行符) QByteArray frame = m_buffer.left(endIndex + 1); m_buffer = m_buffer.mid(endIndex + 1); // 移除已处理数据 // 将数据存入公共池 datapool::instance()->addData(frame.trimmed()); } }
03-08
<think>嗯,用户给了一个C++的代码片段,是关于Qt串口通信的类qserial的实现。我需要帮他理解这段代码的结构和功能。首先,我要分步骤分析每个部分的作用,然后组织成易于理解的中文解释。 首先看头文件和构造函数。qserial类继承了QObject,构造函数接收UI指针和父对象。初始化列表里初始化了成员变量,包括UI和serialPort。这里用到了QSerialPort,所以这个类应该是用来管理串口通信的。构造函数里还连接了readyRead信号到onReadyRead槽函数,这样当有数据可读时会自动处理。 接下来,构造函数里获取了可用的串口列表和标准波特率,然后把这些信息添加到UI的下拉框中。这里用了foreach循环遍历端口和波特率,添加到对应的控件里。设置默认波特率为115200,这可能是个常用值。 析构函数释放了serialPort和ui,这需要注意是否正确,因为UI通常由父窗口管理,这里直接delete可能有问题?不过用户代码里可能结构特殊,暂时按代码解释。 connect函数负责配置和打开串口。设置了端口名、波特率、数据位、停止位、流控制等参数,然后尝试以读写模式打开。成功返回true,否则false。这里要提到各个参数设置的细节,比如Data8、无校验位等。 dis_connect方法关闭串口,简单直接。 onReadyRead槽函数处理数据读取。这里用了缓冲区m_buffer来累积数据,直到遇到换行符。每次读取所有可用数据,然后循环查找换行符,分割出完整帧,存入数据池datapool的单例中。trimmed()可能用于去除首尾空白,比如回车换行符。 需要注意的是,数据处理部分可能存在不完整帧的情况,但代码通过循环处理确保每次处理完整的帧。同时,datapool的单例模式用于共享数据。 用户可能需要了解这个类如何与UI交互,串口配置的流程,以及数据接收处理的机制。要确保解释清楚每个函数的作用,特别是信号槽的连接和数据缓冲的处理方式。可能还需要指出潜在的问题,比如UI指针的管理,或者缓冲区处理是否足够健壮,但用户的问题主要是介绍代码,所以重点在功能说明而非代码审查。</think>这个`qserial`类是基于Qt框架实现的串口通信模块,主要用于管理串口连接和数据接收。以下是核心功能的逐步解析: **一、构造函数初始化** ```cpp qserial::qserial(Ui::MainWindow *ui, QObject *parent) : QObject(parent), ui(ui), serialPort(new QSerialPort(this)) { // 信号槽连接:当串口有数据可读时触发onReadyRead QObject::connect(serialPort, &QSerialPort::readyRead, this, &qserial::onReadyRead); // 动态获取系统可用串口 QList<QSerialPortInfo> PORT = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &port, PORT) { ui->port_chose->addItem(port.portName()); // 填充端口下拉框 } // 加载标准波特率列表 QList<qint32> bands = QSerialPortInfo::standardBaudRates(); foreach (qint32 band, bands) { ui->band_rate->addItem(QString::number(band)); // 填充波特率下拉框 } ui->band_rate->setCurrentText("115200"); // 默认波特率 } ``` *关键点:* - 自动检测可用串口设备 - 提供标准波特率选项(9600、115200等) - 默认使用115200高速通信 **二、串口连接管理** ```cpp bool qserial::connect() { // 配置串口参数 serialPort->setPortName(ui->port_chose->currentText()); // 端口名 serialPort->setBaudRate(ui->band_rate->currentText().toInt()); // 波特率 serialPort->setDataBits(QSerialPort::Data8); // 8位数据位 serialPort->setParity(QSerialPort::NoParity); // 无校验位 serialPort->setStopBits(QSerialPort::OneStop); // 1位停止位 serialPort->setFlowControl(QSerialPort::NoFlowControl); // 无流控 return serialPort->open(QIODevice::ReadWrite); // 返回连接状态 } void qserial::dis_connect() { serialPort->close(); // 断开连接 } ``` *参数说明:* $$ \begin{cases} \text{数据位} \rightarrow 8\text{bit} \\ \text{校验位} \rightarrow \text{None} \\ \text{停止位} \rightarrow 1\text{bit} \\ \text{流控制} \rightarrow \text{Disabled} \end{cases} $$ **三、数据接收处理** ```cpp void qserial::onReadyRead() { m_buffer += serialPort->readAll(); // 读取全部可用数据 while(true) { int endIndex = m_buffer.indexOf('\n'); // 查找换行符 if(endIndex == -1) break; QByteArray frame = m_buffer.left(endIndex + 1); // 提取完整帧 m_buffer = m_buffer.mid(endIndex + 1); // 移除已处理数据 datapool::instance()->addData(frame.trimmed()); // 存入数据池 } } ``` *数据处理流程:* 1. 持续累积接收数据到`m_buffer` 2. 通过`\n`识别数据帧结束符 3. 拆分完整数据帧后存入共享数据池 4. 使用`trimmed()`去除首尾空白字符 **四、设计特点** 1. **UI解耦**:通过`Ui::MainWindow`指针操作界面控件 2. **异步通信**:采用Qt信号槽机制实现非阻塞数据传输 3. **数据分帧**:支持基于换行符的协议格式(如JSON、CSV等) 4. **单例数据池**:通过`datapool::instance()`实现跨模块数据共享 **典型应用场景**:工业控制、传感器数据采集、嵌入式设备通信等需要可靠串口通信的领域。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值