Qt实现串口助手

 更新时间:2022年08月19日 11:07:10   作者:林子xxx  
这篇文章主要为大家详细介绍了Qt实现串口助手,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Qt实现串口助手的具体代码,供大家参考,具体内容如下

1.界面布局

这是一个常见的串口助手布局。要说有什么不常见,大概就是发送可以选择编码方式:GBK/UTF8

2.要点

没什么难度,就是水磨工夫,一点点写。容易错处的地方都写在代码注释里。

3.代码

下面是 mainwindow.cpp 文件。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qdebug.h>
 
QSerialPort *serial;
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    serial = new QSerialPort;
 
    findSerialPort();
 
    ui->cbbBaudrate->addItem(QStringLiteral("4800"), QSerialPort::Baud4800);
    ui->cbbBaudrate->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
    ui->cbbBaudrate->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
    ui->cbbBaudrate->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
    ui->cbbBaudrate->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
    ui->cbbBaudrate->setCurrentIndex(4);
    //添加数据位
     ui->cbbDataSize->addItem(QStringLiteral("5"), QSerialPort::Data5);
     ui->cbbDataSize->addItem(QStringLiteral("6"), QSerialPort::Data6);
     ui->cbbDataSize->addItem(QStringLiteral("7"), QSerialPort::Data7);
     ui->cbbDataSize->addItem(QStringLiteral("8"), QSerialPort::Data8);
     ui->cbbDataSize->setCurrentIndex(3);
     //添加奇偶校验位
     ui->cbbParity->addItem(tr("None"), QSerialPort::NoParity);
     ui->cbbParity->addItem(tr("Even"), QSerialPort::EvenParity);
     ui->cbbParity->addItem(tr("Odd"), QSerialPort::OddParity);
     ui->cbbParity->addItem(tr("Mark"), QSerialPort::MarkParity);
     ui->cbbParity->addItem(tr("Space"), QSerialPort::SpaceParity);
     ui->cbbParity->setCurrentIndex(0);
     //添加停止位
     ui->cbbStopbit->addItem(QStringLiteral("1"), QSerialPort::OneStop);
     ui->cbbStopbit->addItem(QStringLiteral("1.5"), QSerialPort::OneAndHalfStop);//
     ui->cbbStopbit->addItem(QStringLiteral("2"), QSerialPort::TwoStop);
     ui->cbbStopbit->setCurrentIndex(0);
     //添加流控位
     ui->cbbFlowbit->addItem(tr("None"), QSerialPort::NoFlowControl);
     ui->cbbFlowbit->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
     ui->cbbFlowbit->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);
     ui->cbbFlowbit->setCurrentIndex(0);
     //禁用发送按钮
     ui->btnSend->setEnabled(false);
 
     ui->btnOpen->setStatusTip(tr("打开/关闭串口"));
     ui->rdbGbk->setStatusTip("以GBK编码发送" );
     ui->rdbUtf8->setStatusTip(tr("以UTF8编码发送"));
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::findSerialPort()
{
    ui->cbbPort->clear();
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort tempserial;
        tempserial.setPort(info);
 
        if(tempserial.open(QIODevice::ReadWrite))
        {
            ui->cbbPort->addItem(info.description()+":"+tempserial.portName(),tempserial.portName());
 
            tempserial.close();
        }
    }
}
 
void MainWindow::setsuienable( bool en )
{
    ui->cbbPort->setEnabled(en);
    ui->cbbBaudrate->setEnabled(en);
    ui->cbbDataSize->setEnabled(en);
    ui->cbbParity->setEnabled(en);
    ui->cbbStopbit->setEnabled(en);
    ui->cbbFlowbit->setEnabled(en);
}
 
void MainWindow::on_btnOpen_clicked()
{
    if(ui->btnOpen->text()  != "关闭")
    {
        if( !ui->cbbPort->currentText().isNull() )
        {
 
            ui->btnOpen->setText("关闭");
            ui->btnSend->setEnabled(true);
            ui->btnFind->setEnabled(false);
            setsuienable(false);
 
            serial->setPortName(ui->cbbPort->currentData(Qt::UserRole).value<QString>()  );
            serial->setBaudRate(ui->cbbBaudrate->currentData(Qt::UserRole).value<qint32>() );
            serial->setDataBits(ui->cbbDataSize->currentData(Qt::UserRole).value<QSerialPort::DataBits>() );
            serial->setFlowControl(ui->cbbDataSize->currentData(Qt::UserRole).value<QSerialPort::FlowControl>() );
            serial->setParity(ui->cbbDataSize->currentData(Qt::UserRole).value<QSerialPort::Parity>() );
            serial->setStopBits(ui->cbbDataSize->currentData(Qt::UserRole).value<QSerialPort::StopBits>() );
            serial->open(QIODevice::ReadWrite);
 
 
            connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialReadData);
        }
    }
    else
    {
        serial->close();
        setsuienable(true);
        ui->btnSend->setEnabled(false);
        ui->btnOpen->setText("打开");
        ui->btnFind->setEnabled(true);
    }
}
 
//字符串数据转为HEX,16进制形式。譬如将 “30”转为“0”
bool StringToHex( QString &dst,const QString src )
{
    QStringList list = src.trimmed().split(QRegExp("\t|\n|\r\n|\r| |,|;")); //去除头尾空白,再分割
 
    foreach (QString n,  list )
    {
        bool res;
        if(n.isEmpty())continue;
        int d= n.toInt(&res,16);
        if(d>255){  return  false ;}
 
        char  c = d;
        if(res)
            dst.append(c);
        else
            return  false ;
    }
    return true;
}
//UTF8转为GBK
QByteArray Utf8ToGbk(QByteArray buf)
{
    QTextCodec* Utf8Codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(Utf8Codec);
    QTextCodec* GbkCodec = QTextCodec::codecForName("GBK");
 
    QByteArray ByteGbk = GbkCodec->fromUnicode( Utf8Codec->toUnicode( buf ) );   //先Unicode编码,后arr
 
    return  ByteGbk ;
}
//串口发送
void MainWindow::on_btnSend_clicked()
{
    if( ui->teSend->toPlainText() .isEmpty() )return;
 
    if( ui->ckbSendhex->isChecked()  )
    {
        QString txt;
        if( StringToHex( txt ,ui->teSend->toPlainText() ) )
        {
            serial->write( txt.toLatin1()  );
        }else
        {
            QMessageBox::about(this,tr("提示"),tr("HEX数据格式错误,\n数据形式类似:30 34 56"));
        }
    }
    else{
        if( ui->rdbUtf8->isChecked() )
        {
            serial->write( ui->teSend->toPlainText().toUtf8()   );
        }else
        {
            QByteArray arrutf8 =ui->teSend->toPlainText().toLocal8Bit();
            serial->write( Utf8ToGbk(arrutf8)   );
        }
    }
}
 
//串口接收处理
void MainWindow::serialReadData()
{
   //注意,直接append会从下一行开始,所以先放入QString
    QByteArray buf = serial->readAll();
    if(!buf.isEmpty())
    {
        QString txt = ui->teReceive->toPlainText();
 
        if( ui->ckbReceivehex->isChecked() )
        {
            ui->teReceive->append( QString( buf.toHex(' ') ) );
        }
        else
        {
            QTextCodec::ConverterState state;
            QTextCodec *codec = QTextCodec::codecForName("UTF-8");
            QString str = codec->toUnicode( buf.constData(), buf.size(), &state);
            if ( state.invalidChars )
            {
               str = QTextCodec::codecForName( "GBK" )->toUnicode(buf);
            }
            else
            {
               str =  codec->toUnicode(buf);
            }
            ui->teReceive->clear();
            ui->teReceive->append(  txt+str  );
        }
    }
 
}
 
void MainWindow::on_btnClearReceive_clicked()
{
    ui->teReceive->clear();
}
 
void MainWindow::on_btnClearSend_clicked()
{
    ui->teSend->clear();
}
 
void MainWindow::on_btnFind_clicked()
{
    ui->btnFind->setEnabled(false);
    findSerialPort();
    ui->btnFind->setEnabled(true);
}

4.效果

测试可以发送和接收GK/UTF8编码的数据。下图是和ATK-XCOM通过虚拟串口交互。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈C++的浅拷贝出现的错误

    浅谈C++的浅拷贝出现的错误

    下面小编就为大家带来一篇浅谈C++的浅拷贝出现的错误。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • C++详细讲解函数调用与Struct和CLass的区别

    C++详细讲解函数调用与Struct和CLass的区别

    主调函数使用被调函数的功能,称为函数调用。在C语言/C++中,只有在函数调用时,函数体中定义的功能才会被执行,下面让我们详细来了解
    2022-05-05
  • C++编写实现图书管理系统

    C++编写实现图书管理系统

    这篇文章主要为大家详细介绍了C++编写实现图书管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • c++自定义sort()函数的排序方法介绍

    c++自定义sort()函数的排序方法介绍

    这篇文章主要介绍了c++自定义sort()函数的排序方法介绍,文章通过围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • C++ JSON库 nlohmann::basic_json::array 的用法示例详解

    C++ JSON库 nlohmann::basic_json::array 的用法示例详解

    nlohmann::json是一个C++的JSON库,它提供了一种容易和直观的方法来处理JSON数据,nlohmann::json::array()是用来创建一个JSON数组的方法,这篇文章主要介绍了C++ JSON库nlohmann::basic_json::array的用法,需要的朋友可以参考下
    2023-06-06
  • c++中的static修饰符示例详解

    c++中的static修饰符示例详解

    在c++中,静态成员是属于整个类而不是某个对象,静态成员变量只存储一份供所有对象共用,下面这篇文章主要给大家介绍了关于c++中static修饰符的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • C++数据结构之搜索二叉树的实现

    C++数据结构之搜索二叉树的实现

    了解搜索二叉树是为了STL中的map和set做铺垫,我们所熟知的AVL树和平衡搜索二叉树也需要搜索二叉树的基础。本文将详解如何利用C++实现搜索二叉树,需要的可以参考一下
    2022-05-05
  • 详解C++中的const和constexpr

    详解C++中的const和constexpr

    这篇文章主要为大家介绍了C++中的const和constexpr ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • C++提取文件中信息的方法

    C++提取文件中信息的方法

    这篇文章主要为大家详细介绍了C++提取文件中信息的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • C语言中单目操作符++、–的实例讲解

    C语言中单目操作符++、–的实例讲解

    C语言的操作符共分为算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符,逗号表达式,下表引用、函数调用和结构成员这10大类,这篇文章主要给大家介绍了关于C语言中单目操作符++、–的相关资料,需要的朋友可以参考下
    2021-12-12

最新评论