前言

串口确实是老生常谈的话题了,去到的几乎每家公司都有定制化串口工具的需求(测试、硬件、算法、技术支持方面),这是最基本的上位机和下位机的通信接口,通常不外乎做这几种功能:升级、数据采集、命令控制

介绍

串口是一种常见的串行通信总线,有双工、半双工等工作模式,常见的串口通信设备有:

  • HMI屏
  • GNSS模块
  • RTK模块
  • 烧录/调试工具,几乎每个嵌入式设备都会预留一个串口供烧录、调试使用
  • PC通信工具(232、485、422),工控场合用得最多,也就是上位机里边应用比较多
  • 运动控制器、机器臂

数据类型

QSerialPortInfo

获取系统上所有串口设备端口

1
2
3
4
5
6
7
8
9
// 函数原型
static QList<QSerialPortInfo> QSerialPortInfo::availablePorts();

// 用法示例
auto &&ports = QSerialPortInfo::availablePorts();
for(auto & iter : ports)
{
qDebug() << "port : " << iter.portName();
}

获取串口设备名称

1
2
3
4
5
6
// 函数原型
QString portName() const;

// 用法示例
QSerialPortInfo info = ports.last();
qDebug() << "name : " << info.portName();

获取系统支持哪些串口波特率参数

1
2
3
4
5
6
7
8
9
// 函数原型
static QList<qint32> QSerialPortInfo::standardBaudRates();

// 用法示例
auto &&rates = QSerialPortInfo::availableRates();
for(auto & iter : rates)
{
qDebug() << "rate : " << iter;
}

当前串口设备是否是空的

1
bool isNull() const;

串口设备厂商信息

1
QString manufacturer() const;

QSerialPort

成员函数

接口 用法 函数原型
portName 获取端口号名称 QString portName() const
setPortName 设置端口号 void setPortName(const QString &name)
open 打开串口设备(可以配置读写模式) bool open(OpenMode mode)
read 读取串口数据 qint64 read(char *data, qint64 maxlen)
write 写入串口数据 qint64 write(const QByteArray &data)
close 关闭串口设备 void close()
baudRate 获取串口通信波特率 qint32 baudRate(Directions directions = AllDirections)
setBaudRate 设置串口通信波特率 bool setBaudRate(qint32 baudRate, Directions directions = AllDirections)
dataBits 获取当前数据位设置 DataBits dataBits() const
setDataBits 设置当前数据位 bool setDataBits(DataBits dataBits)
parity 获取当前奇偶校验位设置 Parity parity() const
setParity 设置奇偶校验位 bool setParity(Parity parity)
stopBits 获取当前停止位设置 StopBits stopBits() const
setStopBits 设置停止位 bool setStopBits(StopBits stopBits)
flowControl 硬件流控设置 FlowControl flowControl() const
setFlowControl 设置硬件流控功能 bool setFlowControl(FlowControl flowControl)

一般处理以下两个信号就够了

  • readyRead:表示已经接收到串口数据
  • errorOccurred:表示串口通信已经发生异常,QSerialPort::SerialPortError是错误信息提示

工程构建

cmake

1
2
find_package(Qt6 REQURED COMPONENTS SerialPort)
target_link_libraries(${PROJECT_NAME} PRIAVTE Qt6::SerialPort)

qmake

1
QT += serialport

头文件

1
2
#include <QSerialPortInfo>
#include <QSerialPort>

GUI

常见的串口配置界面如下(这是Windows自带的,仅作参考使用),串口的常见参数配置:端口号、波特率、数据位、奇偶校验位、停止位、硬件流控

工作流程

Qt串口编码流程

  1. 配置串口参数:端口号、波特率、数据位、奇偶校验位、停止位、硬件流控
  2. 打开串口设备:需要配置读写模式
  3. 绑定readyRead信号进行数据读取操作
  4. 绑定errorOccurred信号可以查看串口通信异常信息
  5. 通过write函数进行数据发送操作
  6. 通过close接口关闭串口设备

注意事项

编程设计

建议用单例模式编写串口通信应用,好处是全局唯一可访问、多线程场合也能兼顾线程安全,在类销毁的时候要及时关闭串口号,防止第二次访问资源被占用;也可以让进程唯一,不让程序多开实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SerialManager : public QObject
{
Q_OBJECT
protected:
explicit SerialManager(QObject *parent = nullptr) {
m_serial = new QSerialPort(this);
}

~SerialManager() {

}

public:
static SerialManager *getInstance() {
static SerialManager instance;
return &instance;
}

private:
QSerialPort *m_serial;
};

热拔插

QAbstractNactiveEventFilter可以实现串口设备热拔插的动态识别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <windows.h>
#include <winuser.h>
#include <Dbt.h>
#include <QAbstractNativeEventFilter>

static QList<QSerialPortInfo> g_availablePorts = QSerialPortInfo::availablePorts();

class WindowsNativeEventFilter : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
{
if (eventType == "windows_generic_MSG") {
MSG *msg = static_cast<MSG *>(message);
if(msg->message == WM_DEVICECHANGE) {
// 总的来说,需要识别DBT_DEVICEARRIVAL DBT_DEVICEREMOVECOMPLETE两个消息
if(msg->wParam == DBT_DEVICEARRIVAL) {
// 检查一下QSerialPortInfo::availablePorts有没有变动
if(g_availablePorts.size() != QSerialPortInfo::availablePorts().size()) {

}
}
else if(msg->wParam == DBT_DEVICEREMOVECOMPLETE) {
// 检查一下QSerialPortInfo::availablePorts有没有变动
if(g_availablePorts.size() != QSerialPortInfo::availablePorts().size()) {

}
}
}

}
return false;
}
};

WindowsNativeEventFilter filter;
QApplication::instance()->installNativeEventFilter(&filter);

参考

【1】设备管理 - Win32 apps

【2】QAbstractNativeEventFilter Class

【3】Qt Serial Bus


『 下里巴人 』
海纳百川,文以载道
hywing技术自留地
总访问 113701 次 | 本页访问 326