Qt 转发两串口数据(二桌面程序版)

Posted 福州-司马懿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt 转发两串口数据(二桌面程序版)相关的知识,希望对你有一定的参考价值。

需求

两串口设置统一,均如下图:

项目实战(桌面程序版,这里采用的是动态布局)

项目的pro文件

在项目的pro文件中添加

QT += serialport

forwardobj.h

#ifndef FORWARDOBJ_H
#define FORWARDOBJ_H

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

/** 波特率:位/秒(B) */
const QSerialPort::BaudRate BAUND_RATE = QSerialPort::Baud115200;
/** 数据位(D) */
const QSerialPort::DataBits DATA_BITS = QSerialPort::Data8;
/** 奇偶校验(P) */
const QSerialPort::Parity PARITY = QSerialPort::NoParity;
/** 停止位(S) */
const QSerialPort::StopBits STOP_BITS = QSerialPort::OneStop;
/** 流控制(F) */
const QSerialPort::FlowControl FLOW_CONTROL = QSerialPort::NoFlowControl;

class ForwardObj : public QObject

    Q_OBJECT
public:
    explicit ForwardObj(QObject *parent = 0);
    ~ForwardObj();
    /** @brief 获取可用端口数目 */
    static int getAvaliablePortsCount();
    /** @brief 获取可用的端口名称 */
    static QStringList getAvaliablePortNames();
    /** @brief 获取可用端口详细信息 */
    static QString getAvailablePorts();
    /** @brief 打开串口并设置相应的参数 */
    bool openPort(const QString &portName1, const QString &portName2);
    /** @brief  连接两串口,用于转发 */
    void connectDoublePort();
    /** @brief 关闭串口 */
    void close();
signals:
    void log(QString str);
public slots:
    void port1ReadyRead();
    void port2ReadyRead();
private:
    QSerialPort serialPort1;
    QSerialPort serialPort2;
    /** @brief 打开串口并设置相应的参数 */
    bool openPort(QSerialPort &serialPort, const QString &portName);
    /** @brief 转发收到的数据 */
    void forward(QSerialPort &fromPort, QSerialPort &toPort);
;

#endif // FORWARDOBJ_H

logcontrol.h

#ifndef LOGCONTROL_H
#define LOGCONTROL_H
#include <QStringList>

/** 最大条目数 */
const int MAX_ITEMS_SIZE = 500;

class LogControl : public QStringList

public:
    LogControl();
    void append(QString str);
    QString toString();
;

#endif // LOGCONTROL_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTextBrowser>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#include "forwardobj.h"
#include "logcontrol.h"

class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    void onRefreshBtnClick();
    void onOpenSerialPortBtnClick();
    void onClearBtnClick();
    void onLog(QString str);
private:
    QComboBox *serialPortCb1;
    QComboBox *serialPortCb2;
    QTextBrowser *textBrowser;
    ForwardObj *forwardObj;
    LogControl logControl;
;

#endif // MAINWINDOW_H

forwardobj.cpp

#include "forwardobj.h"

ForwardObj::ForwardObj(QObject *parent) : QObject(parent)  

ForwardObj::~ForwardObj() 
    close();


int ForwardObj::getAvaliablePortsCount()

    int count = 0;
    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
    if(!ports.isEmpty()) 
        count = ports.count();
    
    return count;


QStringList ForwardObj::getAvaliablePortNames()

    QStringList serialPortNameList;
    foreach(QSerialPortInfo info, QSerialPortInfo::availablePorts()) 
        serialPortNameList.append(info.portName());
    
    return serialPortNameList;


QString ForwardObj::getAvailablePorts()

    QString str;
    QList<QSerialPortInfo> portInfoList = QSerialPortInfo::availablePorts();
    if(portInfoList.isEmpty()) 
        str.append("Not found any avaliable serial ports");
        return str;
    
    str.append(QString("Found %1 avaliable serial ports\\n\\n").arg(portInfoList.size()));
    foreach(QSerialPortInfo info, portInfoList) 
        str.append(QString("Name        : %1\\n").arg(info.portName()));
        str.append(QString("Description : %1\\n").arg(info.description()));
        str.append(QString("Manufacturer: %1\\n").arg(info.manufacturer()));
        str.append(QString("serialNumber: %1\\n").arg(info.serialNumber()));
        str.append("\\n");
    
    return str;


bool ForwardObj::openPort(const QString &portName1, const QString &portName2)

    bool ret;
    ret = openPort(serialPort1, portName1);
    if(ret) 
        ret = openPort(serialPort2, portName2);
    
    if(!ret) 
        close();
    
    return ret;


void ForwardObj::connectDoublePort()

    connect(&serialPort1, SIGNAL(readyRead()), this, SLOT(port1ReadyRead()));
    connect(&serialPort2, SIGNAL(readyRead()), this, SLOT(port2ReadyRead()));


void ForwardObj::close()

    disconnect(&serialPort1, SIGNAL(readyRead()), this, SLOT(port1ReadyRead()));
    disconnect(&serialPort2, SIGNAL(readyRead()), this, SLOT(port2ReadyRead()));
    if(serialPort1.isOpen()) 
        QString str(serialPort1.portName());
        str.append(" has closed");
        serialPort1.close();
        emit log(str);
    
    if(serialPort2.isOpen()) 
        QString str(serialPort1.portName());
        str.append(" has closed");
        serialPort2.close();
        emit log(str);
    


void ForwardObj::port1ReadyRead()

    forward(serialPort1, serialPort2);


void ForwardObj::port2ReadyRead()

    forward(serialPort2, serialPort1);


bool ForwardObj::openPort(QSerialPort &serialPort, const QString &portName)

    foreach (const QSerialPortInfo info, QSerialPortInfo::availablePorts()) 
        if(QString::compare(info.portName(), portName, Qt::CaseInsensitive) == 0) 
            serialPort.setPort(info);
            //打开串口后才能进行余下设置
            bool ret = serialPort.open(QIODevice::ReadWrite);
            if(ret) 
                serialPort.setBaudRate(BAUND_RATE);
                serialPort.setDataBits(DATA_BITS);
                serialPort.setParity(PARITY);
                serialPort.setStopBits(STOP_BITS);
                serialPort.setFlowControl(FLOW_CONTROL);
                serialPort.clearError();
                //The serial port has to be open before trying to clear any buffered data; otherwise returns false and sets the NotOpenError error code.
                serialPort.clear();
            
            if(ret) 
                emit log("Open serial port " + info.portName() + " succ");
             else 
                emit log("Open serial port " + info.portName() + " fail(" + serialPort.error() + ", " + serialPort.errorString() + ")");
            
            return ret;
        
    
    emit log("serial port \\""+ portName +"\\" not found");
    return false;


void ForwardObj::forward(QSerialPort &fromPort, QSerialPort &toPort)

    QByteArray buffer = fromPort.readAll();
    emit log("Read from " + fromPort.portName() + ", data : \\n\\t" + buffer.toHex());
    qint64 len = toPort.write(buffer);
    if(len == -1) 
        emit log("Forward to " + toPort.portName() + " fail, error occur: \\n\\t" + toPort.errorString());
     else 
        emit log("Forward to " + toPort.portName() + " succ");
    

logcontrol.cpp

#include "logcontrol.h"

LogControl::LogControl() : QStringList() 

void LogControl::append(QString str)

    while(size() >= MAX_ITEMS_SIZE) 
        removeAt(0);
    
   QStringList::append(str);


QString LogControl::toString()

    return join('\\n');

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)

    //Qt中父亲被删除的时候会自动销毁他的孩子。所以如果New出来的并且没有父亲,那么则需要手动删除它。
    QWidget *containerWidget = new QWidget(this);
    QVBoxLayout *vboxLayout = new QVBoxLayout(this);
    QWidget *topWidget = new QWidget(this);
    QHBoxLayout *hboxLayout = new QHBoxLayout(this);
    QLabel *serialPortLabel = new QLabel("Select two serial port: ", this);
    serialPortCb1 = new QComboBox(this);
    serialPortCb2 = new QComboBox(this);
    QPushButton *refreshBtn = new QPushButton("Refresh", this);
    QPushButton *openSerialPortBtn = new QPushButton("Connect", this);
    QPushButton *clearBtn = new QPushButton("Clear", this);
    textBrowser = new QTextBrowser(this);

    this->setCentralWidget(containerWidget);
    containerWidget->setLayout(vboxLayout);
    vboxLayout->addWidget(topWidget);
    topWidget->setLayout(hboxLayout);
    hboxLayout->addWidget(serialPortLabel, 0);
    hboxLayout->addWidget(serialPortCb1, 1);
    hboxLayout->addWidget(serialPortCb2, 1);
    hboxLayout->addWidget(refreshBtn, 1);
    hboxLayout->addWidget(openSerialPortBtn, 1);
    hboxLayout->addWidget(clearBtn, 1);
    vboxLayout->addWidget(textBrowser);

    forwardObj = new ForwardObj();

    connect(refreshBtn, SIGNAL(clicked()), this, SLOT(onRefreshBtnClick()));
    connect(openSerialPortBtn, SIGNAL(clicked()), this, SLOT(onOpenSerialPortBtnClick()));
    connect(clearBtn, SIGNAL(clicked()), this, SLOT(onClearBtnClick()));
    connect(forwardObj, SIGNAL(log(QString)), this, SLOT(onLog(QString)));

    onRefreshBtnClick();


MainWindow::~MainWindow()

    forwardObj->close();
    delete forwardObj;


void MainWindow::onRefreshBtnClick()

    onLog(ForwardObj::getAvailablePorts());
    QStringList serialPortNameList = ForwardObj::getAvaliablePortNames();
    if(serialPortNameList.size() < 2) 
       onLog("The count of serial ports cannot be smaller than two");
       return;
   
   serialPortCb1->clear();
   serialPortCb2->clear();
   serialPortCb1->addItems(serialPortNameList);
   serialPortCb2->addItems(serialPortNameList);
   serialPortCb1->setCurrentIndex(0);
   serialPortCb2->setCurrentIndex(1);


void MainWindow::onOpenSerialPortBtnClick()

    forwardObj->close();
    QString serialPortName1 = serialPortCb1->currentText();
    QString serialPortName2 = serialPortCb2->currentText();
    bool ret = forwardObj->openPort(serialPortName1, serialPortName2);
    if(ret) 
        onLog("two serial port open succ, start forward...");
        forwardObj->connectDoublePort();
     else 
        onLog("open fail, please try to reopen");
    


void MainWindow::onClearBtnClick()

    logControl.clear();
    textBrowser->clear();


void MainWindow::onLog(QString str)

    logControl.append(str);
    textBrowser->setText(logControl.toString());
    textBrowser->moveCursor(QTextCursor::End);

最后生成的可执行文件需要引用的DLL

  • libgcc_s_dw2-1.dll
  • libstdc++-6.dll
  • libwinpthread-1.dll
  • Qt5Core.dll
  • Qt5SerialPort.dll
  • Qt5Gui.dll
  • Qt5Widgets.dll
  • platforms(C:\\Qt\\5.7\\mingw53_32\\plugins\\platforms)

以上是关于Qt 转发两串口数据(二桌面程序版)的主要内容,如果未能解决你的问题,请参考以下文章

Qt 串口通信接收数据不完整,怎么解决?

QT c++不止一次打开串口

qt串口设置停止位出现

Qt编写推流综合应用示例(文件推流/桌面推流/本地摄像头/网络摄像头/转发推流/视频分发)

Qt串口数据显示

Python Qt GUI设计:做一款串口调试助手(实战篇—1)