从搜集到的资料中整理一些对 qt串口的理解
1、QSerialPort类源码解析
QSerialPort类继承自QIODevice,提供了基本的功能,包括配置,I/O操作,获取和设置RS-232引脚的信号:
与该类有关系的类主要是如下几个:
QIODevice、QSerialPort、QSerialPortPrivate、QSerialPortPrivateData。
它们的关系如下:
QSerialPort继承自QIODevice,继承了对设备文件基本的操作。
QSerialPortPrivate是QSerialPort对象中表示操作一类的,该部分与操作系统有关。QSerialPortPrivate继承自QSerialPortPrivateData。
QSerialPortPrivateData是一个串口设备的初始化数据,例如波特率等等。
QSerialPortPrivateData更多表示串口设备的初始数据,QSerialPortPrivate更多表示平台相关的对串口设备的操作。
2、QserialPortInfo类源码解析
QserialPortInfoSerialPortInfo是一个帮助类。它提供了系统上可用的串口的信息。
与该类的类主要是如下几个:
QSerialPort、QSerialPortInfo、QSerialPortInfoPrivate、QSerialPortInfoPrivateDeleter。
QSerialPortInfo的构造函数中使用到了QSerialPort。
QSerialPortInfoPrivate则代表QSerialPortInfo的私有数据。
【QSerialPort】
该类提供访问串口的功能。你可以使用QSerialPortInfo帮助类获取系统上可用的串口的信息,可以枚举系统上存在的所有串口。通过该类你可以获取串口的正确名称。你可以传递一个该类的对象作为setPort()或者setPortName()方法的参数指定想要访问的串口设备。
在设置完了串口,你就可以以只读或者只写或者读写模式调用open()方法打开串口。
注意:串口都是以互斥的方式访问,这也就是说我们不能打开一个已经打开的串口。
成功打开之后,QSerialPort尝试着获取串口当前的配置并初始化它。你也可以使用setBaudRate(),setDataBits(),setParity(), setStopBits()
和setFlowControl()方法重新配置它。控制管脚的状态是根据isDataTerminalReady(),isRequestToSend()和pinoutSignals()决定的。要改变控制信息,可以使用如下方法:setDataTerminalReady()和setRequestToSend()。
一旦你知道了串口可用于读或者写,你就可以调用read()或者write()方法。可选的还有readline()和readAll()方法。如果数据不能在一次读完,那么剩下的数据接下来就会存在QSerialPort的内部缓冲区中。你可以使用setReadBufferSize()方法设置缓冲区的大小。可以使用close()方法来关闭串口和取消I/O操作。
【QSerialPortInfo】
提供系统中已存在的串口信息。
使用该类的静态函数获取一系列的QSerialPortInfo对象。列表中的每一个QSerialPort对象都代表了一个单独的串口,可以用于获取串口名、
系统路径、描述以及制造商等信息。QSerialPortInfo类也可以作为QSerialPort类的setPort()方法的一个输入参数
/*********************************************************************************************/
工程文件.pro中添加
QT += serialport
在头文件中添加全局的串口对象
QSerialPort *serial;
在串口通讯文件中添加头文件
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
QT串口通讯需要大概7步
//1、设置串口名
serial = new QSerialPort;
// serial->setPortName(ui->PortBox->currentText());
//使用自动寻找可用串口直接自动设置串口名
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->PortBox->addItem(serial.portName());
serial.close();
}
}
//2、打开串口
serial->open(QIODevice::ReadWrite);
//3、设置波特率
serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200
//4、设置数据位
serial->setDataBits(QSerialPort::Data8);//设置数据位8
//5、设置校验位
serial->setParity(QSerialPort::NoParity); //校验位设置为0
//6、设置停止位
serial->setStopBits(QSerialPort::OneStop);//停止位设置为1
//7、设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
//到这里串口通信的设置就完成了,下面我们需要实现对数据的发送和接收
1、工程文件SerialPortTool.pro
#-------------------------------------------------
#
# Project created by QtCreator 2017-11-17T15:43:04
#
#-------------------------------------------------
QT += core gui
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = SerialPortTool
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
2、头文件mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_OpenSerialButton_clicked();
void ReadData();
void on_SendButton_clicked();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
};
#endif // MAINWINDOW_H
3、源文件mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
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);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_OpenSerialButton_clicked()
{
if(ui->OpenSerialButton->text() == tr("打开串口"))
{
serial = new QSerialPort;
//设置串口名
serial->setPortName(ui->PortBox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
//设置波特率
serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200
//设置数据位数
switch (ui->BitBox->currentIndex())
{
case 8:
serial->setDataBits(QSerialPort::Data8);//设置数据位8
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);//停止位设置为1
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("关闭串口"));
//连接信号槽
QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::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 MainWindow::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 MainWindow::on_SendButton_clicked()
{
serial->write(ui->textEdit_2->toPlainText().toLatin1());
}
4、界面文件mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>470</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>串口</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>波特率</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>130</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>数据位</string>
</property>
</widget>
<widget class="QComboBox" name="PortBox">
<property name="geometry">
<rect>
<x>100</x>
<y>50</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="BaudBox">
<property name="geometry">
<rect>
<x>100</x>
<y>90</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>9600</string>
</property>
</item>
<item>
<property name="text">
<string>19200</string>
</property>
</item>
<item>
<property name="text">
<string>38400</string>
</property>
</item>
<item>
<property name="text">
<string>57600</string>
</property>
</item>
<item>
<property name="text">
<string>115200</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="BitBox">
<property name="geometry">
<rect>
<x>100</x>
<y>120</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>8</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="ParityBox">
<property name="geometry">
<rect>
<x>100</x>
<y>160</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>160</y>
<width>61</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>校验位</string>
</property>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>10</x>
<y>200</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>停止位</string>
</property>
</widget>
<widget class="QComboBox" name="StopBox">
<property name="geometry">
<rect>
<x>100</x>
<y>200</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
</widget>
<widget class="QPushButton" name="OpenSerialButton">
<property name="geometry">
<rect>
<x>100</x>
<y>240</y>
<width>71</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>打开串口</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>200</x>
<y>30</y>
<width>221</width>
<height>291</height>
</rect>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_2">
<property name="geometry">
<rect>
<x>200</x>
<y>330</y>
<width>221</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="SendButton">
<property name="geometry">
<rect>
<x>430</x>
<y>330</y>
<width>75</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>发送</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>23</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
图形界面显示串口信息
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QtSerialPort/QSerialPortInfo>
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle(QObject::tr("Info about all available serial ports."));
QVBoxLayout *layout = new QVBoxLayout;
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
QString s = QObject::tr("Port: ") + info.portName() + "\n"
+ QObject::tr("Location: ") + info.systemLocation() + "\n"
+ QObject::tr("Description: ") + info.description() + "\n"
+ QObject::tr("Manufacturer: ") + info.manufacturer() + "\n"
+ QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ?QString::number(info.productIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n";
QLabel *label = new QLabel(s);
layout->addWidget(label);
}
w.setLayout(layout);
w.show();
return a.exec();
}