Qt6.2+QtDS的多功能串口助手(QML学习)

开发平台:Qt 6.2 + Qt Design Studio 3.2.0

编译环境:MinGW 11.2.0 64bit --release

主要内容:Qt Quick Application载入QML,C++与QML交互处理逻辑

实现功能:串口调试,网络调试,数据操作等

源码与安装包免费下载链接在文末!不再赘述请参照源码学习!

部分原理可参考这篇文章学习(欢迎吐槽):

(87条消息) Qt学习记录_阿衰0110的博客-CSDN博客

main.cpp代码片段:

//#include <QGuiApplication>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QtQml>
#include <QDebug>
#include "userfunc.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    //QGuiApplication app(argc, argv);
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.addImportPath("qrc:/AS_TOOL_UI/imports"); // 添加imports文件路径
    engine.load(QUrl(QStringLiteral("qrc:/AS_TOOL_UI/content/App.qml"))); // 加载QML

    UserFunc myClass(engine.rootObjects()); // 获取QML对象
    app.installNativeEventFilter(myClass.mySerialEvent); // 安装window串口拔插事件

    engine.rootContext()->setContextProperty("myClass", &myClass); // 将C++类添加进QML使用
    engine.rootContext()->setContextProperty("mySerial", myClass.serial_main); // 将C++类添加进QML使用

    //myClass.set_QMLObject(engine.rootObjects()); // 获取QML对象

    return app.exec();
}

serial.cpp代码片段,实现串口功能

#include "serial.h"
#include <QDebug>

Serial::Serial()
{
    // 定义文本编码
    tc = QTextCodec::codecForName("UTF-8");
}

QStringList Serial::serialScan(void)
{
    QStringList serialPortList;
    serialDescription.clear(); // 每次扫描先清除串口描述信息
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        this->setPort(info);
        serialPortList.append(this->portName());
        serialDescription.append(info.description());
        //qDebug() << this->portName();
        //qDebug() << info.description();
    }
    return serialPortList;
}

bool Serial::serialOpen(QString serialName, int baudRate)
{
    this->setPortName(serialName);
    if(this->open(QIODeviceBase::ReadWrite)) {
        this->setBaudRate(baudRate);
        this->setDataBits(QSerialPort::Data8);
        this->setParity(QSerialPort::NoParity);
        this->setStopBits(QSerialPort::OneStop);
        this->setFlowControl(QSerialPort::NoFlowControl);
        // 下位机发送数据会响应这个槽函数
        connect(this, &QSerialPort::readyRead, this, &Serial::ReadData);
        return true;
    }
    return false;
}
// 读数据
void Serial::ReadData()
{
    dataBuf = this->readAll();
    this->rxByte += tc->toUnicode(dataBuf).length();
    emit this->readSignal(this->rxByte);
}
// 写数据
void Serial::sendData(QByteArray sendData)
{
    int byteTemp;
    byteTemp = this->write(sendData);
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->txByte += byteTemp;
        emit this->sendSuccess(this->txByte);
    }
}
// 关闭串口
void Serial::serialClose()
{
    this->clear();
    this->close();
}

 serial.h代码片段

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QStringList>
#include <QString>
#include <QByteArray>
#include <QTextCodec>

class Serial : public QSerialPort
{
    Q_OBJECT
public:
    explicit Serial();
    // 发送字节数
    int txByte = 0;
    // 接收字节数
    int rxByte = 0;
    // 数据缓存区
    QByteArray dataBuf;
    // 串口描述内容
    QStringList serialDescription;
    // 串口扫描函数
    QStringList serialScan(void);
    bool serialOpen(QString serialName, int baudRate);
    void ReadData();
    void sendData(QByteArray sendData);
    void serialClose();
private:
    QTextCodec *tc;
signals:
    void readSignal(int recByte);
    void sendSuccess(int sendByte);
public slots:
};

#endif // SERIAL_H

network.cpp代码片段,实现TCP Server,TCP Client,UDP功能

#include "network.h"
#include <QNetworkDatagram>
#include <QDebug>

network::network(QObject *parent)
    : QObject{parent}
{
    // 定义文本编码
    tc = QTextCodec::codecForName("UTF-8");
    // 实例化TCP服务端
    tcpServer = new QTcpServer();
    connect(tcpServer, &QTcpServer::newConnection, this, &network::TCPServer_newConnect);
    // 实例化TCP客户端
    tcpClient = new QTcpSocket();
    connect(tcpClient, &QTcpSocket::connected, this, &network::TCPClient_newConnect);
    connect(tcpClient, &QTcpSocket::disconnected, this, &network::TCPClient_disconnect);
    connect(tcpClient, &QTcpSocket::readyRead, this, &network::TCPClient_readData);
    // 实例化UDP
    udpSocket = new QUdpSocket();
    connect(udpSocket, &QUdpSocket::readyRead, this, &network::UDP_readData);
}

bool network::TCPServer_open(QString ownIp, unsigned short ownPort)
{
    bool result = true;
    if(ownIp.length() < 10)
    {
        // 监听本地ip和port以监测有无接收数据
        result = tcpServer->listen(QHostAddress::Any, ownPort);
    }
    else
    {
        result = tcpServer->listen(QHostAddress(ownIp), ownPort);
    }
    return result;
//    if(!result)
//    {
//        qDebug() << "(TCP Server) listen fail";
//        return false;
//    }
//    qDebug() << "(TCP Server) listen success";
//    return true;
}

void network::TCPServer_close()
{
    tcpServer->close();
}

void network::TCPServer_newConnect()
{
    QTcpSocket *newTcpClient = tcpServer->nextPendingConnection(); // 新的客户端发起的连接
    //QHostAddress newClientIp = newTcpClient->peerAddress(); // 新的客户端的IP
    //quint16 newClientPort = newTcpClient->peerPort(); // 新的客户端的端口
    // 是否已存在连接列表中
    if(clientList.contains(newTcpClient))
    {
        //qDebug() << QString("(TCP Server) already exist IP:%1 PORT:%2").arg(newClientIp.toString()).arg(newClientPort);
    }
    else
    {
        clientList.append(newTcpClient); // 记录新的客户端
        // 连接信号
        connect(newTcpClient, &QTcpSocket::disconnected, this, &network::TCPServer_disconnect); // 断开连接的信号与槽
        connect(newTcpClient, &QTcpSocket::readyRead, this, &network::TCPServer_readData); // 数据接收的信号与槽 readyRead()是QIODevice下的信号
        //qDebug() << QString("(TCP Server) new connect IP:%1 PORT:%2").arg(newClientIp.toString()).arg(newClientPort);
    }
}

void network::TCPServer_disconnect()
{
    QTcpSocket *newTcpClient = static_cast<QTcpSocket *>(QObject::sender());
    clientList.removeOne(newTcpClient); // 移除断开连接的客户端
    // 断开信号
    disconnect(newTcpClient, &QTcpSocket::disconnected, this, &network::TCPServer_disconnect); // 断开连接的信号与槽
    disconnect(newTcpClient, SIGNAL(readyRead()), this, SLOT(TCPServer_readData())); // 数据接收的信号与槽
    //qDebug() << "(TCP Server) disconnect";
}

void network::TCPServer_readData()
{
    QTcpSocket *newTcpClient = static_cast<QTcpSocket *>(QObject::sender());
    this->TCPServer_dataBuf = newTcpClient->readAll();
    this->TCPServer_rxByte += tc->toUnicode(this->TCPServer_dataBuf).length();
    emit this->tcpServer_readSuccess(this->TCPServer_rxByte);
    //qDebug() << "(TCP Server) rec data:" + tc->toUnicode(TCPServer_dataBuf);
}

void network::TCPServer_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    foreach(QTcpSocket *socket, clientList)
    {
        byteTemp = socket->write(sendData);
    }
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->TCPServer_txByte += byteTemp;
        emit this->tcpServer_sendSuccess(this->TCPServer_txByte);
    }
}

bool network::TCPClient_open(QString remoteIp, unsigned short remotePort)
{
    QHostAddress serverIp;
    // IP错误则返回false
    if(!serverIp.setAddress(remoteIp))
    {
        //qDebug() << "(TCP Client) remoteIp error";
        return false;
    }
    // 防止TCP Client已打开
    if(tcpClient->isOpen())
    {
        tcpClient->close();
    }
    tcpClient->connectToHost(serverIp, remotePort);
    // 是否连接成功
    if(!tcpClient->waitForConnected(500))
    {
        //qDebug() << "(TCP Client) tcp client connect fail";
        return false;
    }
    return true;
}

void network::TCPClient_close()
{
    tcpClient->close();
}

void network::TCPClient_newConnect()
{
    //qDebug() << "(TCP Client) new connect";
}

void network::TCPClient_disconnect()
{
    if(tcpClient->isOpen())
    {
        tcpClient->close();
    }
    //qDebug() << "(TCP Client) disconnect";
}

void network::TCPClient_readData()
{
    this->TCPClient_dataBuf = tcpClient->readAll();
    this->TCPClient_rxByte += tc->toUnicode(this->TCPClient_dataBuf).length();
    emit this->tcpClient_readSuccess(this->TCPClient_rxByte);
    //qDebug() << "(TCP Client) rec data:" + tc->toUnicode(TCPClient_dataBuf);
}

void network::TCPClient_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    byteTemp = tcpClient->write(sendData);
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->TCPClient_txByte += byteTemp;
        emit this->tcpClient_sendSuccess(this->TCPClient_txByte);
    }
    //qDebug() << "(TCP Client) send byte:" << byteTemp;
}

bool network::UDP_open(QString ownIp, unsigned short ownPort, QString remoteIp, unsigned short remotePort)
{
    bool result = true;
    if(ownIp.length() < 10)
    {
        // 绑定本地ip和port以监测有无接收数据
        result = udpSocket->bind(QHostAddress::Any, ownPort);
    }
    else
    {
        result = udpSocket->bind(QHostAddress(ownIp), ownPort);
    }
    this->UDP_remoteIp = QHostAddress(remoteIp);
    this->UDP_remotePort = remotePort;
    return result;
//    if(!result)
//    {
//        qDebug() << "UDP open fail";
//        return false;
//    }
//    qDebug() << "UDP open success";
//    return true;
}

void network::UDP_close()
{
    udpSocket->close();
}

void network::UDP_readData()
{
    while(udpSocket->hasPendingDatagrams())
    {
         QNetworkDatagram datagram = udpSocket->receiveDatagram();
         this->UDP_dataBuf = datagram.data();
         this->UDP_rxByte += tc->toUnicode(this->UDP_dataBuf).length();
         emit this->udp_readSuccess(this->UDP_rxByte);
         //qDebug() << datagram.data();
    }
}

void network::UDP_sendData(QByteArray sendData)
{
    int byteTemp = 0;
    byteTemp = udpSocket->writeDatagram(sendData, this->UDP_remoteIp, this->UDP_remotePort);
    // 发送失败返回-1
    if(byteTemp != -1)
    {
        this->UDP_txByte += byteTemp;
        emit this->udp_sendSuccess(this->UDP_txByte);
    }
}

network.h代码片段

#ifndef NETWORK_H
#define NETWORK_H

#include <QObject>
#include <QList>
#include <QByteArray>
#include <QTextCodec>
#include <QHostAddress>

#include <QTcpSocket>
#include <QTcpServer>
#include <QUdpSocket>


class network : public QObject
{
    Q_OBJECT
public:
    explicit network(QObject *parent = nullptr);
    // 数据缓存区
    QByteArray TCPServer_dataBuf;
    QByteArray TCPClient_dataBuf;
    QByteArray UDP_dataBuf;
    // 发送/接收字节数
    int TCPServer_txByte = 0;
    int TCPServer_rxByte = 0;
    int TCPClient_txByte = 0;
    int TCPClient_rxByte = 0;
    int UDP_txByte = 0;
    int UDP_rxByte = 0;

    bool TCPServer_open(QString ownIp, unsigned short ownPort);
    void TCPServer_close();
    void TCPServer_sendData(QByteArray sendData);

    bool TCPClient_open(QString remoteIp, unsigned short remotePort);
    void TCPClient_close();
    void TCPClient_sendData(QByteArray sendData);

    bool UDP_open(QString ownIp, unsigned short ownPort, QString remoteIp, unsigned short remotePort);
    void UDP_close();
    void UDP_sendData(QByteArray sendData);
private:
    QTextCodec *tc; // 编码
    QTcpServer *tcpServer; // tcp服务端
    QList<QTcpSocket*> clientList; // 保存连接的客户端
    QTcpSocket *tcpClient; // tcp客户端
    QUdpSocket *udpSocket; // udp
    QHostAddress UDP_remoteIp;
    unsigned short UDP_remotePort;
signals:
    void tcpServer_readSuccess(int recByte);
    void tcpServer_sendSuccess(int sendByte);

    void tcpClient_readSuccess(int recByte);
    void tcpClient_sendSuccess(int sendByte);

    void udp_readSuccess(int recByte);
    void udp_sendSuccess(int sendByte);
private slots:
    void TCPServer_readData();
    void TCPServer_newConnect();
    void TCPServer_disconnect();

    void TCPClient_readData();
    void TCPClient_newConnect();
    void TCPClient_disconnect();

    void UDP_readData();
};

#endif // NETWORK_H

界面如下:

 

Qt6.2+QtDS多功能串口助手源码与安装包下载地址:

https://download.csdn.net/download/m0_50669075/85347047

END 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿衰0110

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值