本文实例为大家分享了Qt实现串口助手的具体代码,供大家参考,具体内容如下1.界面布局这是一个常见的串口助手布局。要说有什么不常见,大概就是发送可以选择编码方式:GBK/UTF82.要点没什么难度,就是...

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

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