为大家分享一下最近封装的串口通讯接口
效果演示
简易做了个界面,如右图,左图为著名串口助手
废话不多说直接上教程
添加库
如果为qmake项目中,在.pro文件添加 QT += serialport
QT += core gui
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
Serial封装
头文件// SerialPortManager.h
cpp
#ifndef SERIALPORTMANAGER_H
#define SERIALPORTMANAGER_H
#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QByteArray>
#include <QDebug>
#include <functional>
class SerialPortManager : public QObject
{
Q_OBJECT
public:
explicit SerialPortManager(QObject *parent = nullptr);
~SerialPortManager();
// 初始化串口连接,检查串口是否存在并打开串口
bool init(const QString &portName,
int baudRate = QSerialPort::Baud9600,
QSerialPort::DataBits dataBits = QSerialPort::Data8,
QSerialPort::Parity parity = QSerialPort::NoParity,
QSerialPort::StopBits stopBits = QSerialPort::OneStop,
QSerialPort::FlowControl flowControl = QSerialPort::NoFlowControl);
// 关闭串口
void closePort();
// 发送数据
bool sendData(const QByteArray &data);
// 接收数据
QByteArray readData();
// 检查串口是否存在
bool isPortAvailable(const QString &portName);
// 获取串口列表
QList<QSerialPortInfo> getAllPort();
// 设置接收数据的回调函数
void setDataReceivedCallback(std::function<void(const QByteArray &)> callback);
private slots:
void onDataReceived(); // 串口数据接收槽函数
private:
QSerialPort *m_serialPort;
std::function<void(const QByteArray &)> m_dataReceivedCallback; // 回调函数
};
#endif // SERIALPORTMANAGER_H
源文件// SerialPortManager.cpp
cpp
#include "SerialPortManager.h"
SerialPortManager::SerialPortManager(QObject *parent) : QObject(parent), m_serialPort(new QSerialPort(this))
{
// 连接接收数据的信号
connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortManager::onDataReceived, Qt::DirectConnection);
}
SerialPortManager::~SerialPortManager()
{
if (m_serialPort->isOpen()) {
m_serialPort->close();
}
}
bool SerialPortManager::init(const QString &portName,
int baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits,
QSerialPort::FlowControl flowControl)
{
// 检查串口是否存在
if (!isPortAvailable(portName)) {
qDebug() << "串口" << portName << "不存在!";
return false;
}
m_serialPort->setPortName(portName);
m_serialPort->setBaudRate(baudRate);
m_serialPort->setDataBits(dataBits);
m_serialPort->setParity(parity);
m_serialPort->setStopBits(stopBits);
m_serialPort->setFlowControl(flowControl);
// 尝试打开串口
if (m_serialPort->open(QIODevice::ReadWrite)) {
qDebug() << "串口连接成功:" << portName;
return true;
} else {
qDebug() << "串口连接失败:" << portName;
return false;
}
}
void SerialPortManager::closePort()
{
if (m_serialPort->isOpen()) {
m_serialPort->close();
qDebug() << "串口关闭";
}
}
bool SerialPortManager::sendData(const QByteArray &data)
{
if (m_serialPort->isOpen()) {
qint64 bytesWritten = m_serialPort->write(data);
return bytesWritten == data.size();
} else {
qDebug() << "串口未打开,无法发送数据";
return false;
}
}
QByteArray SerialPortManager::readData()
{
QByteArray data = m_serialPort->readAll();
return data;
}
bool SerialPortManager::isPortAvailable(const QString &portName)
{
// 获取系统中的所有串口信息
QList<QSerialPortInfo> availablePorts = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &port : availablePorts) {
if (port.portName() == portName) {
return true; // 找到指定的串口
}
}
return false; // 没有找到指定的串口
}
QList<QSerialPortInfo> SerialPortManager::getAllPort()
{
return QSerialPortInfo::availablePorts();
}
void SerialPortManager::setDataReceivedCallback(std::function<void(const QByteArray &)> callback)
{
m_dataReceivedCallback = callback;
}
void SerialPortManager::onDataReceived()
{
// 从串口读取数据
QByteArray data = m_serialPort->readAll();
// 如果回调函数已设置,调用回调函数
if (m_dataReceivedCallback) {
m_dataReceivedCallback(data);
}
}
使用方式
首先引入#include "SerialPortManager.h"
初始化
cpp
void MainWindow::initSerialPorts()
{
// 获取所有可用的串口信息
QList<QSerialPortInfo> list = serialManager.getAllPort();
// 清空下拉框内容
ui->comboBox->clear();
// 将串口名称添加到下拉框
for (const QSerialPortInfo &info : list) {
ui->comboBox->addItem(info.portName()); // 添加串口名
}
// 如果没有可用串口,提示用户
if (list.isEmpty()) {
QMessageBox::warning(this, "提示", "未检测到可用串口!");
}
}
创建回调函数
收到消息通过回调函数的方式来接收数据
cpp
void MainWindow::dataCallback(const QByteArray &data)
{
// 处理接收到的数据
QString receivedHex = data.toHex().toUpper(); // 转换为十六进制大写字符串
QString formattedHex;
// 添加空格分隔
for (int i = 0; i < receivedHex.size(); i += 2) {
formattedHex.append(receivedHex.mid(i, 2)); // 取两位
if (i + 2 < receivedHex.size()) {
formattedHex.append(' '); // 每两位后添加空格
}
}
// 将接收到的内容追加到文本框
QString existingText = ui->textEdit_2->toPlainText();
if (!existingText.isEmpty()) {
existingText.append(' '); // 如果已经有内容,先添加一个空格
}
existingText.append(formattedHex); // 追加新接收到的数据
// 更新文本框内容
ui->textEdit_2->setText(existingText);
// 可选:打印到调试控制台
qDebug() << "接收到的数据:" << formattedHex;
}
最后,我将项目放到GitHub,https://github.com/xiugou798/QT6-Serial-Demo,欢迎大家优化修改