基于Qt 5实现串口调试助手总结(包括源码)
Qt实现串口调试总结
文章中用到的源码已上传至https://download.csdn.net/download/m0_51294753/57091077,无需积分下载。
**文章代码已作修改,修改之前十六进制接收0xA0–0xFF有误的问题,增加了窗口自适应(ui文件增加栅格)。
一、前言
本篇文章主要介绍使用Qt Creator编程实现串口调试助手的过程和源代码实现。网络上关于这方面的资源和开源程序很多,本人初学Qt编程,主要目的是记录学习过程,和大家交流,总结经验。程序通过与其他串口调试助手通信测试,总体功能实现良好。代码为个人编写,部分借鉴了网上资源,存在不规范或出错的问题,若内容陈述或程序代码有错误欢迎告知我。
二、界面和功能介绍
设计的串口通信调试界面如图所示:


实现目前通用串口调试助手的大部分功能,包括串口、波特率、数据位、校检位、停止位选择;文本、十六进制接收发送;发送文件、保存接收缓存区;定时发送、自动换行等。
三、实现过程
1.创建工程
选择基类为QWidget,勾选Generate form选项(显示窗口)。

2.界面布置
在布局管理窗口布置基本控件,设计串口调试助手的界面。上图为本实例中的界面布置,具体的控件大家可以根据自身要求选择和放置。

3.在.pro文件添加代码
添加核心库,增加一行代码
QT += core gui
QT += serialport
4.在头文件定义相关变量和函数
控件对象名称起初没有命名,采用的都是默认值,但注释得比较清楚就不再修改了。
#ifndef WIDGET_H
#define WIDGET_H#include
#include
#include QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget(); int Times,portTime,lineEditData;
private:Ui::Widget *ui;QSerialPort *serial; //串口端口QTimer *timer; //定时器QByteArray Sendtext,Receivetext; //发送、接收缓存区long int SendByte,ReceByte; //发送、接收字符数QStringList portStringLine; //端口链表private slots:void serialPort_readyRead(); //串口接收void TimerEvent(); //定时发送、更新串口void on_pushButton_clicked(); //扫描串口void on_pushButton_2_clicked(); //打开串口键按下void on_pushButton_7_clicked(); //串口发送void on_pushButton_8_clicked(); //清除计数void on_pushButton_4_clicked(); //清除接收区void on_pushButton_6_clicked(); //清除发送区void on_checkBox_clicked(); //文本接收void on_checkBox_2_clicked(); //十六进制接收void on_checkBox_3_clicked(); //暂停接收void on_checkBox_4_clicked(); //文本发送void on_checkBox_5_clicked(); //十六进制发送void on_pushButton_5_clicked(); //打开文件void on_pushButton_3_clicked(); //保存文件void on_lineEdit_editingFinished(); //输入定时时间
};
#endif // WIDGET_H
5.编写程序实现功能
这部分内容比较多,都是基于功能的实现,本人在实现过程中遇到的问题大都是在这部分。因为注释的比较详细,具体步骤不再说明,实现程序如下:
#include "widget.h"
#include "ui_widget.h"#include
#include
#include
#include
#include
#include Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);resize(800,600); //窗口限制setWindowTitle("Serial_Port");SendByte=0;ReceByte=0;serial = new QSerialPort(this);ui->comboBox_2->setCurrentIndex(5); //初始化ui->comboBox_3->setCurrentIndex(3);ui->comboBox_4->setCurrentIndex(2);ui->comboBox_5->setCurrentIndex(0);ui->lineEdit->setText("1000");ui->checkBox->setCheckState(Qt::Checked);ui->checkBox_4->setCheckState(Qt::Checked);ui->pushButton_7->setEnabled(false);ui->checkBox_7->setEnabled(false);connect(serial,SIGNAL(readyRead()), //信号与槽函数this,SLOT(serialPort_readyRead()));Times=0;portTime=0;lineEditData=1000;timer = new QTimer;timer->start(1);//connect(timer,&QTimer::timeout,this,&Widget::TimerEvent);connect(timer,SIGNAL(timeout()),this,SLOT(TimerEvent())); //信号与槽函数
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_2_clicked()
{if(ui->pushButton_2->text()==QString("打开串口")){//设置串口名serial->setPortName(ui->comboBox->currentText());//设置波特率serial->setBaudRate(ui->comboBox_2->currentText().toInt());//设置数据位switch(ui->comboBox_3->currentText().toInt()){case 5:serial->setDataBits(QSerialPort::Data5);break;case 6:serial->setDataBits(QSerialPort::Data6);break;case 7:serial->setDataBits(QSerialPort::Data7);break;case 8:serial->setDataBits(QSerialPort::Data8);break;default:serial->setDataBits(QSerialPort::UnknownDataBits);break;}//设置奇偶校验位switch(ui->comboBox_4->currentIndex()){case 0:serial->setParity(QSerialPort::EvenParity);break;case 1:serial->setParity(QSerialPort::MarkParity);break;case 2:serial->setParity(QSerialPort::NoParity);break;case 3:serial->setParity(QSerialPort::OddParity);break;default:serial->setParity(QSerialPort::UnknownParity);break;}//设置停止位switch (ui->comboBox_5->currentIndex()){case 0:serial->setStopBits(QSerialPort::OneStop);break;case 1:serial->setStopBits(QSerialPort::OneAndHalfStop);break;case 2:serial->setStopBits(QSerialPort::TwoStop);break;default:serial->setStopBits(QSerialPort::UnknownStopBits);break;}//设置流控制serial->setFlowControl(QSerialPort::NoFlowControl);//打开串口if(!serial->open(QIODevice::ReadWrite)){QMessageBox::about(NULL,"提示","无法打开串口");return;}//下拉控件失能ui->comboBox->setEnabled(false);ui->comboBox_2->setEnabled(false);ui->comboBox_3->setEnabled(false);ui->comboBox_4->setEnabled(false);ui->comboBox_5->setEnabled(false);ui->pushButton->setEnabled(false);ui->checkBox_7->setEnabled(true);ui->pushButton_2->setText(tr("关闭串口"));ui->pushButton_7->setEnabled(true);}else{//关闭串口serial->close();//下拉按键使能ui->comboBox->setEnabled(true);ui->comboBox_2->setEnabled(true);ui->comboBox_3->setEnabled(true);ui->comboBox_4->setEnabled(true);ui->comboBox_5->setEnabled(true);ui->pushButton->setEnabled(true);ui->checkBox_7->setEnabled(false);ui->pushButton_2->setText(tr("打开串口"));//发送失能ui->pushButton_7->setEnabled(false);}
}void Widget::on_pushButton_clicked() //扫描串口
{int i,n;ui->comboBox->clear();portStringLine.clear();foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())portStringLine +=info.portName();n=portStringLine.size();for(i=0;i<n;i++){serial->setPortName(portStringLine[i]);if(!serial->open(QIODevice::ReadWrite)){portStringLine[i]+="(不可用)";QVariant v(0); //禁用ui->comboBox->setItemData(1, v, Qt::UserRole - 1);}else{QVariant v(1|32); //可用ui->comboBox->setItemData(1, v, Qt::UserRole - 1);}serial->close();}ui->comboBox->addItems(portStringLine);
}void Widget::serialPort_readyRead() //串口接收
{int i,length;QByteArray lasttext;if(ui->checkBox_3->checkState()!=Qt::Checked){lasttext=ui->textEdit->toPlainText().toUtf8();Receivetext = serial->readAll();ReceByte+=Receivetext.length();ui->label_10->setText(QString::number(ReceByte));if(ui->checkBox_2->checkState()==Qt::Checked){Receivetext=Receivetext.toHex().toUpper(); //字符串转十六进制length=Receivetext.length();for(i=0;i<=length/2;i++){Receivetext.insert((2+3*i),' '); //插入空格字符串}}lasttext=lasttext.append(Receivetext);ui->textEdit->setText(lasttext);}
}void Widget::on_pushButton_7_clicked() //串口发送
{QByteArray bytearray;Sendtext=ui->textEdit_2->toPlainText().toUtf8();if(ui->checkBox_6->checkState()==Qt::Checked)Sendtext += '\n';if(ui->checkBox_5->checkState()!=Qt::Checked)bytearray = Sendtext;elsebytearray = QByteArray::fromHex(Sendtext); //十六进制转字符串serial->write(bytearray);//定长发送//serial->write((const char *)param_data,16);SendByte+=Sendtext.length();ui->label_9->setText(QString::number(SendByte));ui->textEdit_2->moveCursor(QTextCursor::End);
}void Widget::TimerEvent() //定时事件,1ms
{int t=500; //扫描串口时间Times++;portTime++;if(Times>=lineEditData) //定时发送{if(ui->checkBox_7->checkState()==Qt::Checked)Widget::on_pushButton_7_clicked();Times=0;}if(portTime==t) //定时扫描串口{QStringList newPortStringList;newPortStringList.clear();foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())newPortStringList += info.portName();if(newPortStringList.size() != portStringLine.size()){portStringLine = newPortStringList;ui->comboBox->clear();ui->comboBox->addItems(portStringLine);}portTime=0;}
}void Widget::on_pushButton_8_clicked() //清除计数
{SendByte=0;ReceByte=0;ui->label_9->setText(QString::number(SendByte));ui->label_10->setText(QString::number(ReceByte));
}void Widget::on_pushButton_4_clicked() //清除接收区
{ui->textEdit->clear();
}void Widget::on_pushButton_6_clicked() //清除发送区
{ui->textEdit_2->clear();
}void Widget::on_checkBox_clicked() //文本接收
{ui->checkBox->setCheckState(Qt::Checked);ui->checkBox_2->setCheckState(Qt::Unchecked);ui->checkBox_3->setCheckState(Qt::Unchecked);
}void Widget::on_checkBox_2_clicked() //十六进制接收
{ui->checkBox->setCheckState(Qt::Unchecked);ui->checkBox_2->setCheckState(Qt::Checked);ui->checkBox_3->setCheckState(Qt::Unchecked);
}void Widget::on_checkBox_3_clicked() //暂停接收
{ui->checkBox->setCheckState(Qt::Unchecked);ui->checkBox_2->setCheckState(Qt::Unchecked);ui->checkBox_3->setCheckState(Qt::Checked);
}void Widget::on_checkBox_4_clicked() //文本发送
{ui->checkBox_4->setCheckState(Qt::Checked);ui->checkBox_5->setCheckState(Qt::Unchecked);
}void Widget::on_checkBox_5_clicked() //十六进制发送
{ui->checkBox_4->setCheckState(Qt::Unchecked);ui->checkBox_5->setCheckState(Qt::Checked);
}void Widget::on_pushButton_5_clicked() //打开文件
{QString fileName = QFileDialog::getOpenFileName(this);QFile file(fileName); //新建QFile对象if(!file.open(QFile::ReadOnly|QFile::Text)){QMessageBox::warning(this,tr("多文档编辑器"),tr("无法读取文件 %1:\n%2").arg(fileName,file.errorString()));}QTextStream in(&file); //新建文本流对象// 鼠标指针变为等待状态QApplication::setOverrideCursor(Qt::WaitCursor);//读取文件的全部文本内容,并添加到编辑器中ui->textEdit_2->setPlainText(in.readAll());//鼠标指针恢复为原来状态QApplication::restoreOverrideCursor();ui->textEdit->setVisible(true);
}void Widget::on_pushButton_3_clicked() //保存文件
{QString fileName = QFileDialog::getSaveFileName(this);QFile file(fileName);if (!file.open(QFile::WriteOnly | QFile::Text)){// %1和%2分别对应后面arg两个参数,/n起换行的作用QMessageBox::warning(this, tr("多文档编辑器"),tr("无法写入文件 %1:/n %2").arg(fileName, file.errorString()));}QTextStream out(&file);// 鼠标指针变为等待状态QApplication::setOverrideCursor(Qt::WaitCursor);out << ui->textEdit->toPlainText();// 鼠标指针恢复原来的状态QApplication::restoreOverrideCursor();
}void Widget::on_lineEdit_editingFinished() //输入定时时间
{if(ui->lineEdit->text().toInt()>0)lineEditData=ui->lineEdit->text().toInt();
}
因为个人能力原因,以上程序可能存在纰漏,实现功能也不尽完善。期待和大家一起学习交流,共同进步。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
