qt串口阻塞_Qt5 串口数据读取

本文介绍了如何在Qt5中利用QtSerialPort模块进行串口通信,包括QSerialPort和QSerialPortInfo类的使用,以及串口的配置、打开、读写操作。通过示例代码展示了如何获取可用串口信息、设置波特率和数据位,并提供了读取数据的信号槽机制。

由于RS232串口操作简单、通讯可靠,所以在工业领域中有大量的应用。

而普通家用PC已经逐步淘汰该串口,但usb转串口的设备依然存储,所以掌握Qt的串行数据读取便非常重要。

Qt以前的版本中,没有提供官方的对RS232串口的支持,编写串口程序很不方便。但在 Qt5.1 之后的版本提供了QtSerialPort模块,方便编程人员快速的开发应用串口的应用程序。

这里我们看一下具体的实现流程:

主要的类

当前的QtSerialPort模块中提供了两个C++类,分别是QSerialPort 和QSerialPortInfo。

QSerialPort 类提供了操作串口的各种接口。

QSerialPortInfo 是一个辅助类,可以提供计算机中可用串口的各种信息。

要在应用程序中使用这些类,请使用以下include语句:

#include

#include

要链接到模块,请将此行添加到XXX.pro文件中:

QT += serialport

QSerialPort

可以使用qserialPortInfo帮助程序类获取有关可用串行端口的信息,该类允许枚举系统中的所有串行端口。这对于获得要使用的串行端口的正确名称很有用。可以将helper类的对象作为参数传递给setport()或setportname()方法,以分配所需的串行设备。

设置端口后,可以使用open()方法以只读(r/o)、只写(w/o)或读写(r/w)模式打开它。

注意:串行端口总是以独占访问方式打开(即,没有其他进程或线程可以访问已经打开的串行端口)。

成功打开后,qserialport尝试确定端口的当前配置并初始化自身。可以使用setBaudRate()、setDataBits()、setParity()、setTopBits()和setFlowControl()方法将端口重新配置为所需的设置。

有两个属性可用于pinout信号,即:qserialport::dataterminalready、qserialport::requestToSend。也可以使用pinout signals()方法查询当前的pinout信号集。

一旦知道端口已准备好读或写,就可以使用read()或write()方法。或者,也可以调用readline()和readall()方便方法。如果不是一次读取所有数据,其余数据将在稍后可用,因为新的传入数据将附加到qserialport的内部读取缓冲区。可以使用setReadBufferSize()限制读取缓冲区的大小。

使用close()方法关闭端口并取消I/O操作。

QSerialPortInfo

提供有关现有串行端口的信息。

使用静态函数生成qserialPortInfo对象列表。列表中的每个qserialPortInfo对象表示单个串行端口,可以查询端口名、系统位置、说明和制造商。qserialPortInfo类也可以用作qserialPort类的setport()方法的输入参数。

实例

简单的验证性例程

#include

#include

#include

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())

{

qDebug() << "Name : " << info.portName();

qDebug() << "Description : " << info.description();

qDebug() << "Manufacturer: " << info.manufacturer();

qDebug() << "Serial Number: " << info.serialNumber();

qDebug() << "System Location: " << info.systemLocation();

}

return a.exec();

}

运行效果

通常需要指定程序使用某一个确定的串口,这时不能只使用串口名称,因为USB串口每次插在不同的USB口上时获得的串口名称都可能有变化。这时可以利用串口的序列号,这个号码一般来说是唯一的。

刚才我的序列号是:5583332383935110B111

例程如下:

#include

#include

#include

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

QSerialPortInfo com_info;

foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())

{

if( info.serialNumber() == "5583332383935110B111" )

{

com_info = info;

break;

}

}

qDebug() << "Name : " << com_info.portName();

qDebug() << "Description : " << com_info.description();

qDebug() << "serialNumber: " << com_info.serialNumber();

return a.exec();

}

运行效果

涉及的函数

1、availablePorts

static QList availablePorts();

返回系统上可用串行端口的列表。

2、setPort

void setPort(const QSerialPortInfo &info);

设置存储在串行端口信息实例serial port info中的端口。

3、open

bool QSerialPort::open(OpenMode mode)

从qiodevice::open()重新实现。

使用openmode模式打开串行端口,如果成功,则返回true;否则返回false,并设置一个错误代码,可以通过调用error()方法获得该代码。

注意:如果打开端口成功,该方法将返回false,但无法成功设置任何端口设置。在这种情况下,端口将自动关闭,以避免使用不正确的设置离开端口。

警告:模式必须是qiodevice::readonly、qiodevice::writeonly或qiodevice::readwrite。不支持其他模式。

4、setPortName

void setPortName(const QString &name);

设置串行端口的名称。如果需要,可以将串行端口的名称作为短名称或长系统位置传递。

5、setBaudRate

bool setBaudRate(qint32 baudRate, Directions directions = AllDirections);

qint32 baudRate(Directions directions = AllDirections) const;

设备波特率的函数,对应此属性保留所需方向的数据波特率。

如果设置成功或在打开端口之前设置,则返回“真”;否则返回“假”,并设置一个错误代码,可以通过访问qserialport::error属性的值来获取该代码。要设置波特率,请使用枚举qserialport::baud rate或任何正qint32值。

注意:如果在打开端口之前设置了该设置,则实际的串行端口设置将在qserialPort::open()方法中自动完成,然后端口打开成功。

默认值为baud9600,即每秒9600位。

6、setDataBits

bool setDataBits(DataBits dataBits);

DataBits dataBits() const;

设置数据的函数,此属性将数据位保存在帧中。

如果设置成功或在打开端口之前设置,则返回“真”;否则返回“假”,并设置一个错误代码,可以通过访问qserialport::error属性的值来获取该代码。

注意:如果在打开端口之前设置了该设置,则实际的串行端口设置将在qserialPort::open()方法中自动完成,然后端口打开成功。

默认值为data8,即8个数据位。

7、setParity

bool setParity(Parity parity);

Parity parity() const;

设置奇偶校验函数,此属性保持奇偶校验模式。

如果设置成功或在打开端口之前设置,则返回“真”;否则返回“假”,并设置一个错误代码,可以通过访问qserialport::error属性的值来获取该代码。

注意:如果在打开端口之前设置了该设置,则实际的串行端口设置将在qserialPort::open()方法中自动完成,然后端口打开成功。

默认值为no parity,即无奇偶校验。

8、setStopBits

bool setStopBits(StopBits stopBits);

StopBits stopBits() const;

设置停止位的函数,此属性保存帧中的停止位数。

如果设置成功或在打开端口之前设置,则返回“真”;否则返回“假”,并设置一个错误代码,可以通过访问qserialport::error属性的值来获取该代码。

注意:如果在打开端口之前设置了该设置,则实际的串行端口设置将在qserialPort::open()方法中自动完成,然后端口打开成功。

默认值为OneStop,即1个停止位。

9、setFlowControl

bool setFlowControl(FlowControl flowControl);

FlowControl flowControl() const;

设置控制流模式的函数,此属性保持所需的流控制模式。

如果设置成功或在打开端口之前设置,则返回“真”;否则返回“假”,并设置一个错误代码,可以通过访问qserialport::error属性的值来获取该代码。

注意:如果在打开端口之前设置了该设置,则实际的串行端口设置将在qserialPort::open()方法中自动完成,然后端口打开成功。

默认值为NoFlowControl,即没有流控制。

读取串口设备

QSerialPort 负责具体的串口操作。选定串口后,要先打开串口,才能设置波特率等参数。这些参数都设置好了就可以使用了。最基本的操作无非是read() 和 write()。需要注意的是这两个操作都是非阻塞的。还有一个重要的signal 也需要用到,那就是 void QIODevice::readyRead()。每次串口收到数据后都会发出这个signal。我们的程序中需要定义一个slot,并将其与这个signal 相连接。这样,每次新数据到来后,我们就可以在slot中读取数据了。这时一定要将串口缓冲区中的数据全部读出来,可以利用readAll() 来实现。

综合例程:

#include "widget.h"

#include "ui_widget.h"

#include

#include

Widget::Widget(QWidget *parent) :

QWidget(parent),

ui(new Ui::Widget)

{

ui->setupUi(this);

//查找可用的串口

foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())

{

QSerialPort serial;

serial.setPort(info);

if(serial.open(QIODevice::ReadWrite))

{

ui->PortBox->addItem(serial.portName());

serial.close();

}

}

//设置波特率下拉菜单默认显示第0项

ui->BaudBox->setCurrentIndex(0);

}

Widget::~Widget()

{

delete ui;

}

void Widget::on_OpenSerialButton_clicked()

{

if(ui->OpenSerialButton->text() == tr("打开串口"))

{

serial = new QSerialPort;

//设置串口名

serial->setPortName(ui->PortBox->currentText());

//打卡串口

serial->open(QIODevice::ReadWrite);

//设置波特率

serial->setBaudRate(ui->BaudBox->currentText().toInt());

//设置数据位数

switch (ui->BitBox->currentIndex())

{

case 8:

serial->setDataBits(QSerialPort::Data8);

case 7:

serial->setDataBits(QSerialPort::Data7);

case 6:

serial->setDataBits(QSerialPort::Data6);

case 5:

serial->setDataBits(QSerialPort::Data5);

break;

default:

break;

}

//设置校验位

switch (ui->ParityBox->currentIndex())

{

case 0:

serial->setParity(QSerialPort::NoParity);

break;

default:

break;

}

//设置停止位

switch (ui->BitBox->currentIndex())

{

case 1:

serial->setStopBits(QSerialPort::OneStop);

break;

case 2:

serial->setStopBits(QSerialPort::TwoStop);

default:

break;

}

//设置流控制

serial->setFlowControl(QSerialPort::NoFlowControl);

//关闭设置菜单使能

ui->PortBox->setEnabled(false);

ui->BaudBox->setEnabled(false);

ui->BitBox->setEnabled(false);

ui->ParityBox->setEnabled(false);

ui->StopBox->setEnabled(false);

ui->OpenSerialButton->setText(tr("关闭串口"));

//连接信号槽

connect(serial,SIGNAL(readyRead),this,SLOT(ReadData));

}

else

{

//关闭串口

serial->clear();

serial->close();

serial->deleteLater();

//恢复设置使能

ui->PortBox->setEnabled(true);

ui->BaudBox->setEnabled(true);

ui->BitBox->setEnabled(true);

ui->ParityBox->setEnabled(true);

ui->StopBox->setEnabled(true);

ui->OpenSerialButton->setText(tr("打开串口"));

}

}

//读取接收到的信息

void Widget::ReadData()

{

QByteArray buf;

buf = serial->readAll();

if(!buf.isEmpty())

{

QString str = ui->textEdit->toPlainText();

str+=tr(buf);

ui->textEdit->clear();

ui->textEdit->append(str);

}

buf.clear();

}

//发送按钮槽函数

void Widget::on_SendButton_clicked()

{

serial->write(ui->textEdit_2->toPlainText().toUtf8());

}

运行效果:

image.png

image.png

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值