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通過虛擬串口交互。

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: