Qt串口助手
林子xxx 人气:01.界面布局
这是一个常见的串口助手布局。要说有什么不常见,大概就是发送可以选择编码方式: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通过虚拟串口交互。
加载全部内容