QT QSerrialPort 串口信息获取和发送

发送/接收数据:

比较简单,一些选项可以使用下拉框或者菜单组件来选择都系,这里我个人用的菜单

    Nwidget *SP_configWidget = new Nwidget("SP_configWidget");
    Nlabel *SP_portLabel = new Nlabel("SP_portLabel");
    Nlabel *SP_baudLabel = new Nlabel("SP_baudLabel");
    Nlabel *SP_dtbitsLabel = new Nlabel("SP_dtbitsLabel");
    Nlabel *SP_stbitsLabel = new Nlabel("SP_stbitsLabel");
    Nlabel *SP_ckPlaceLabel = new Nlabel("SP_ckPlaceLabel");
    Nlabel *SP_scontrolLabel = new Nlabel("SP_scontrolLabel");
    QToolButton *SP_usbportBut = new QToolButton(SP_Widget);
    QToolButton *SP_dtplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_baudrateBut = new QToolButton(SP_Widget);
    QToolButton *SP_stplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_ckplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_scontrolBut = new QToolButton(SP_Widget);

    QMenu *SP_usbPortMenu = new QMenu();
    QMenu *SP_baudRateMenu = new QMenu();
    QMenu *SP_dtplaceMenu = new QMenu();
    QMenu *SP_stplaceMenu = new QMenu();
    QMenu *SP_ckplaceMenu = new QMenu();
    QMenu *SP_scontrolMenu = new QMenu();

    QAction *AS_baudr115200 = new QAction("115200", SP_baudRateMenu);
    QAction *AS_baudr57600 = new QAction("57600", SP_baudRateMenu);
    QAction *AS_baudr38400 = new QAction("38400", SP_baudRateMenu);
    QAction *AS_baudr19200 = new QAction("19200", SP_baudRateMenu);
    QAction *AS_baudr9600 = new QAction("9600", SP_baudRateMenu);
    QAction *AS_baudr4800 = new QAction("4800", SP_baudRateMenu);
    QAction *AS_baudr2400 = new QAction("2400", SP_baudRateMenu);
    QAction *AS_baudr1200 = new QAction("1200", SP_baudRateMenu);

    QAction *AS_oddParity = new QAction("奇校验", SP_ckplaceMenu);
    QAction *AS_evenParity = new QAction("偶校验", SP_ckplaceMenu);
    QAction *AS_unParity = new QAction("无校验", SP_ckplaceMenu);

    QAction *AS_dtbitsFive = new QAction("bits 5", SP_dtplaceMenu);
    QAction *AS_dtbitsSix = new QAction("bits 6", SP_dtplaceMenu);
    QAction *AS_dtbitsSeven = new QAction("bits 7", SP_dtplaceMenu);
    QAction *AS_dtbitsEight = new QAction("bits 8", SP_dtplaceMenu);

    QAction *AS_stbitsOne = new QAction("bits 1", SP_stplaceMenu);
    QAction *AS_stbitshalf = new QAction("bits 1.5", SP_stplaceMenu);
    QAction *AS_stbitsTwo = new QAction("bits 2", SP_stplaceMenu);

    QAction *AS_hardControl = new QAction("硬件控制", SP_scontrolMenu);
    QAction *AS_softControl = new QAction("软件控制", SP_scontrolMenu);
    QAction *AS_unControl = new QAction("无控制", SP_scontrolMenu);

把菜单放入QToolButton中,连接信号槽

    connect(SP_usbPortMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), SerialPort);});
    connect(SP_baudRateMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), BaudRate);});
    connect(SP_dtplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), DtPlace);});
    connect(SP_stplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), StPlace);});
    connect(SP_ckplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), CheckPlace);});
    connect(SP_scontrolMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), Scontrol);});

其中 SP_serialAttriCfg 函数整合了所有选项了,参数:
 

QString Actext 菜单选择的选项文本
SerialAttribute Attribute  属性

属性枚举:

typedef enum {
    SerialPort,
    BaudRate,
    DtPlace,
    StPlace,
    Scontrol,
    CheckPlace
} SerialAttribute;

接下来是SP_serialAttriCfg函数代码: 

void ToolLogicCT::SP_serialAttriCfg(QString Actext, SerialAttribute Attribute){
    switch (Attribute) {
        case BaudRate:
            if (Actext == "115200")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud115200);
            }
            else if (Actext == "57600")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud57600);
            }
            else if (Actext == "38400")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud38400);
            }
            else if (Actext == "19200")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud19200);
            }
            else if (Actext == "9600")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud9600);
            }
            else if (Actext == "4800")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud4800);
            }
            else if (Actext == "2400")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud2400);
            }
            else
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud1200);
            }
            RdoMap_Serial["SQL_SRLP_BAUD"] = QString("BaudRate = '%1'").arg(Actext);
            SP_baudrateBut->setText(Actext);
            break;

        case DtPlace:
            if (Actext == "bits 5")
            {
                SP_sralPort->setDataBits(QSerialPort::Data5);
            }
            else if (Actext == "bits 6")
            {
                SP_sralPort->setDataBits(QSerialPort::Data6);
            }
            else if (Actext == "bits 7")
            {
                SP_sralPort->setDataBits(QSerialPort::Data7);
            }
            else
            {
                SP_sralPort->setDataBits(QSerialPort::Data8);
            }
            SP_dtplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_DTPL"] = QString("DataPlace = '%1'").arg(Actext);
            break;

        case StPlace:
            if (Actext == "bits 1")
            {
                SP_sralPort->setStopBits(QSerialPort::OneStop);
            }
            else if (Actext == "bits 1.5")
            {
                SP_sralPort->setStopBits(QSerialPort::OneAndHalfStop);
            }
            else
            {
                SP_sralPort->setStopBits(QSerialPort::TwoStop);
            }
            SP_stplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_STPL"] = QString("StopPlace = '%1'").arg(Actext);
            break;

        case Scontrol:
            if (Actext == "硬件控制")
            {
                SP_sralPort->setFlowControl(QSerialPort::HardwareControl);
            }
            else if (Actext == "软件控制")
            {
                SP_sralPort->setFlowControl(QSerialPort::SoftwareControl);
            }
            else
            {
                SP_sralPort->setFlowControl(QSerialPort::NoFlowControl);
            }
            SP_scontrolBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_SCTL"] = QString("SControl = '%1'").arg(Actext);
            break;

       case CheckPlace:
            if (Actext == "奇校验")
            {
                SP_sralPort->setParity(QSerialPort::OddParity);
            }
            else if (Actext == "偶校验")
            {
                SP_sralPort->setParity(QSerialPort::EvenParity);
            }
            else
            {
                SP_sralPort->setParity(QSerialPort::NoParity);
            }
            SP_ckplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_PRTY"] = QString("CheckPlace = '%1'").arg(Actext);
            break;

        case SerialPort:
            QString portName = RdoMap_Serial[Actext];
            QFontMetrics portNameMetrics(SP_usbPortMenu->font());
            qDebug() << portNameMetrics.horizontalAdvance(portName) << SP_usbportBut->width();
            if (portNameMetrics.horizontalAdvance(Actext) <= SP_usbportBut->width())
            {
                SP_usbportBut->setText(Actext);
            }
            else
            {
                SP_usbportBut->setText(portName);
            }
            QSerialPortInfo SP_sralPortInfo(portName);
            SP_sralPort->setPort(SP_sralPortInfo);
            break;
    }
}

可以看到,代码中设置了 比特率、数据位、停止位、校验位、流控制以及串口名

其中串口名在最初切换到工具的时候已经获取了

    } else if ( RdoMap_Integer["ViewIndex"] == 3 ) {
        PBL_centraStackWidget->setCurrentWidget(SP_Widget);
        FL_fileaddBut->setVisible(false);
        TR_actionBut->setVisible(false);
        AS_assistBut->setVisible(false);
        VW_viewcutBut->setText("当前窗口-[串口工具]");
        DT_execBut->setText("连接");
        DT_scviewBut->setText("连接列表");
        DT_rsviewBut->setText("命令列表");
        QList<QSerialPortInfo> portInfoList = QSerialPortInfo::availablePorts();
        foreach(QSerialPortInfo port, portInfoList)
        {
            QString SerialInfo = port.description() + " " + port.portName();
            RdoMap_Serial[SerialInfo] = port.portName();
            SPActionList.append(new QAction(SerialInfo, SP_usbPortMenu));
        }
        SP_usbPortMenu->addActions(SPActionList);
        QStringList i = RdoMap_Serial.keys();
        SP_usbportBut->setText(i[0]);
        RdoMap_String["FunctionName"] = "SerialCTTools";
        SerialDelayCheckTimer->start();
        SP_setToolmenuActionAdjustSize(SP_usbportBut);
        SP_setToolmenuActionAdjustSize(SP_baudrateBut);
        SP_setToolmenuActionAdjustSize(SP_dtplaceBut);
        SP_setToolmenuActionAdjustSize(SP_stplaceBut);
        SP_setToolmenuActionAdjustSize(SP_ckplaceBut);
        SP_setToolmenuActionAdjustSize(SP_scontrolBut);

主要部分是QSerialPortInfo::availablePorts()列表中的 port.portName(),在后续的打开串口中就需要用到这个端口名了,根据所选项获取对应的保存好的端口名,设置端口

打开端口

void ToolLogicBT::DT_ExecButClick(){
    if (RdoMap_String["FunctionName"] == "SerialCTTools" && !RdoMap_Switch["SerialState"])
    {
        if (SP_sralPort->open(QIODevice::ReadWrite))
        {
            DT_execBut->setText("连接成功");
            RdoMap_Switch["SerialState"] = true;
            SP_sralPort->setRequestToSend(true);
            SP_sralPort->setBreakEnabled(true);
            SP_sralPort->setDataTerminalReady(true);
        }
        else
        {
            DT_execBut->setText("连接失败");
            RdoMap_Switch["SerialState"] = false;
        }
    }
    else
    {
        SP_sralPort->close();
        RdoMap_Switch["SerialState"] = false;
        DT_execBut->setText("连接断开");
    }
}

这时候需要把串口数据获取并显示到文本框中,所以需要连接信号槽,获取到串口信息并给它加上时间,焦点,获取部分就写好了。

connect(SP_sralPort, &QSerialPort::readyRead, this, &SignalTool::SP_FollowScEdit);




void ToolLogicCT::SP_FollowScEdit(){
    QString DateTimeFormat = "hh:mm:ss";
    QString FORMATDATE = QDateTime::currentDateTime().toString(DateTimeFormat);
    QString TimeStemp = QString("
[%1]->").arg(FORMATDATE);
    QStringList serialInfoList = QString(SP_sralPort->readAll()).split("
").filter(QRegularExpression("\w+"));
    QString AddtimeStemp = serialInfoList.join(TimeStemp);
    SP_serialInfoEdit->append(TimeStemp + AddtimeStemp);
    QTextCursor Cursor = SP_serialInfoEdit->textCursor();
    Cursor.movePosition(QTextCursor::End);
    SP_serialInfoEdit->setTextCursor(Cursor);
}

接下来是发送信息部分,发送串口数据,比如命令往往是需要 加回车换行的

而write函数中是没有这部分代码的,仅仅是发送。因此,需要设备收到命令并执行的话还需要加上回车换行,代码:

    connect(SP_sendBut, &QPushButton::clicked, this, [&]()
    {
        QByteArray orderCode = SP_orderEdit->text().toLocal8Bit();
        SP_sralPort->clear();
        orderCode.append("
");
        qint64 exec = SP_sralPort->write(orderCode);
        if (exec >= 0)
        {
            SP_sralPort->flush();
            SP_sralPort->waitForBytesWritten(10);
        };
    });

基本功能就是这样了,并不复杂,其他一些功能怎么方便怎么加就好了