美文网首页
Qt5 串口数据读取

Qt5 串口数据读取

作者: 飞扬code | 来源:发表于2019-07-26 18:38 被阅读0次

由于RS232串口操作简单、通讯可靠,所以在工业领域中有大量的应用。
而普通家用PC已经逐步淘汰该串口,但usb转串口的设备依然存储,所以掌握Qt的串行数据读取便非常重要。

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

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

主要的类

当前的QtSerialPort模块中提供了两个C++类,分别是QSerialPort 和QSerialPortInfo。
QSerialPort 类提供了操作串口的各种接口。
QSerialPortInfo 是一个辅助类,可以提供计算机中可用串口的各种信息。

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

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

要链接到模块,请将此行添加到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 <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>

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 <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>

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<QSerialPortInfo> 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 <QSerialPort>
#include <QSerialPortInfo>

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

相关文章

  • Qt5 串口数据读取

    由于RS232串口操作简单、通讯可靠,所以在工业领域中有大量的应用。而普通家用PC已经逐步淘汰该串口,但usb转串...

  • WIFI 探针

    我使用的是四博智联提供的WIFI探针 DT-06产品 1.数据读取 可以直接通过串口即可读取数据,串口波特率设置为...

  • Linux/Android 上使用select监听串口数据

    在读取串口数据的时候,因为上位机读取速度和下位机发送速率之间的差异,如果仅仅使用read读取数据就需要循环去读取,...

  • 1、C语言自制串口助手

    一、串口助手 串口助手主要是帮助读取串口数据,使其在上位机上显示出来。下面的代码可以帮助我们理解串口通信的过程。 ...

  • 常用的串口JNI方法

    打开串口 定义的JNI方法 c代码 设置波特率方法 关闭串口 定义的JNI方法 c代码 读取串口数据 定义的JNI...

  • lua串口数据读取

    今天发现 PH 计读不出数据了,经过研究发现数据被分段了。 在 luat 上串口是以事件的形式出现,开始时认为数据...

  • Qt串口通信

    1. Qt串口通信类QSerialPort 在Qt5的的更新中,新增了串口通信的相关接口类QSerialPort,...

  • 考勤系统功能实现——打卡

    1.打卡界面 2.相关代码 自动获取串口列表 向卡中写入数据 打开或关闭串口 窗口关闭时,要关闭串口 “读取卡片”...

  • 使用epoll方式监控键盘等设备输入

    说明  由于需要读取键盘和串口输入,之前都是用循环读取的方式进行读取数据的,采用主动方式而不是等有数据过来的时候通...

  • MATLAB 串口读取姿态数据及GUI实时动态显示设计

    上一篇实现了Matlab 对串口数据的读取,数据可以读取并且保存到本地。本文主要设计GUI并且动态的显示曲线。可以...

网友评论

      本文标题:Qt5 串口数据读取

      本文链接:https://www.haomeiwen.com/subject/wcxdrctx.html