当前位置 : 主页 > 编程语言 > c语言 >

Qt实现串口助手

来源:互联网 收集:自由互联 发布时间:2023-02-01
本文实例为大家分享了Qt实现串口助手的具体代码,供大家参考,具体内容如下 1.界面布局 这是一个常见的串口助手布局。要说有什么不常见,大概就是发送可以选择编码方式:GBK/UT

本文实例为大家分享了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通过虚拟串口交互。

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

上一篇:Qt实现TCP客户端和服务器通讯程序
下一篇:没有了
网友评论