失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > C++语言Qt实现 串口软件 用于嵌入式软件开发上位机通信调试软件

C++语言Qt实现 串口软件 用于嵌入式软件开发上位机通信调试软件

时间:2021-11-03 12:05:14

相关推荐

C++语言Qt实现 串口软件 用于嵌入式软件开发上位机通信调试软件

我遇到个需求:

目标:开发一个串口上位机软件,用于和单片机等进行串口通信。

内部原理:调用串口类,接收到数据进行解析和显示

效果:提供了友好的简洁美观界面,下面就是软件的界面:(支持hex十六进制显示和发送)

代码简单展示

核心代码如下

头文件:

#ifndef MAINWINDOWUART_H#define MAINWINDOWUART_H#include <QMainWindow>class QSerialPort;class QLabel;namespace Ui/*Uart*/ {class MainWindowUart;}class MainWindowUart : public QMainWindow{Q_OBJECTpublic:explicit MainWindowUart(QWidget *parent = 0);~MainWindowUart();bool statusPort=false;QSerialPort *serial;QLabel *lableStatusBar;QList<QByteArray> listByte;int hex2Str(QByteArray buf, QString &hex);int Str2HexMe(QString str, QByteArray &data);void deletStrBlank(QString &s);private slots:void read32ByteData();void on_pushButtonFresh_clicked();void on_pushButtonOpen_clicked();void on_pushButtonSend_clicked();void on_pushButtonClearRxd_clicked();void on_pushButtonClearTxd_clicked();void on_actionS_triggered();void on_action_T_triggered();void on_action_D_triggered();private:Ui/*Uart*/::MainWindowUart *ui;};#endif // MAINWINDOWUART_H

源文件:

#include "mainwindowuart.h"#include "ui_mainwindowuart.h"#include "mainwindow.h"#include "mainwindowdraw.h"#include <QTime>#include <QFileDialog>#include <QFileInfo>#include <QTextStream>#include <QTextCodec>#include <QMessageBox>#include <QGraphicsOpacityEffect>#include <QIcon>#include <QInputDialog>#include <QMessageBox>#include <QDebug>#include <QtSerialPort/QSerialPort>#include <QtSerialPort/QSerialPortInfo>#include <QLabel>#include <QFile>MainWindowUart::MainWindowUart(QWidget *parent) :QMainWindow(parent),ui(new Ui/*Uart*/::MainWindowUart){ui->setupUi(this);// 设置波特率下拉菜单默认显示第三项ui->BaudBox->setCurrentIndex(3);on_pushButtonFresh_clicked();// 关闭发送按钮的使能qDebug() << tr("界面设定成功!")<<endl;lableStatusBar=new QLabel(this);// 初始化类中定义的这个状态栏标签,由于类里面无法指定其父对象,所以在这个构造函数这里指定QString port="Not Open";// 状态栏显示串口未打开信息lableStatusBar->setText("串口打开状态:"+QObject::tr("<font color=red>%1</font>").arg(port));lableStatusBar->setFont(QFont("nihao",8));ui->statusbar->addWidget(lableStatusBar);}/*********************************************************************************************** 读取接收到的数据,注:为了和前面函数名兼容,虽然这个槽函数名字还是读取一字节,但是由于已经* 改了接收缓冲区为默认值(32B),所以这里不会一字节就读一次**********************************************************************************************/void MainWindowUart::read32ByteData(){QByteArray buf;buf = serial->readAll();if(!buf.isEmpty()){// 如果勾选了Hex显示if(ui->checkBoxHexRxd->isChecked()){QString strHex = ui->textEditRxd->toPlainText();QString str1Hex;hex2Str(buf,str1Hex);strHex=strHex+str1Hex;ui->textEditRxd->clear();ui->textEditRxd->setText(strHex);}else{//说明本次刚好接收到换行符的一半,这时先别显示,否则会多一个换行if(buf.at(buf.size()-1) == '\r') {listByte.append(buf);}else{QString str = ui->textEditRxd->toPlainText();for (int i = 0; i < listByte.size(); ++i) {str=str+QString(listByte.at(i));}str=str+QString(buf);listByte.clear();ui->textEditRxd->clear();ui->textEditRxd->setText(str);}// ui->textEditRxd->append(QString(buf)); //append会自动换行qDebug()<<QString(buf);}}buf.clear();}MainWindowUart::~MainWindowUart(){delete ui;}void MainWindowUart::on_pushButtonFresh_clicked(){ui->PortBox->clear();foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){QSerialPort serial1;serial1.setPort(info);ui->PortBox->addItem(serial1.portName());}ui->PortBox->setCurrentIndex(ui->PortBox->count()-1);}void MainWindowUart::on_pushButtonOpen_clicked(){if(statusPort==false){if(ui->PortBox->currentText() == "")return;serial = new QSerialPort;// 设置串口名serial->setPortName(ui->PortBox->currentText());// 打开串口,成功才能往下走if(!serial->open(QIODevice::ReadWrite)){if(serial->error() == QSerialPort::PermissionError){QMessageBox::critical(this,"erro","串口打开失败,该串口已被占用");serial->deleteLater();return;}}statusPort=true;QIcon icoButtonOpenPort(":/new/prefix1/openPort.PNG");ui->pushButtonOpen->setIcon(icoButtonOpenPort);ui->pushButtonOpen->setIconSize(QSize(71,37));// 设置波特率serial->setBaudRate(ui->BaudBox->currentText().toInt());// 设置数据位数switch(ui->BitNumBox->currentIndex()){case 0: serial->setDataBits(QSerialPort::Data8); break;default: break;}// 设置奇偶校验switch(ui->ParityBox->currentIndex()){case 0: serial->setParity(QSerialPort::NoParity); break;default: break;}// 设置停止位switch(ui->StopBox->currentIndex()){case 0: serial->setStopBits(QSerialPort::OneStop); break;case 1: serial->setStopBits(QSerialPort::TwoStop); break;default: break;}// 设置流控制serial->setFlowControl(QSerialPort::NoFlowControl);QString port=ui->PortBox->currentText()+" 波特率:"+ui->BaudBox->currentText()+" 数据位:"+ui->BitNumBox->currentText()+" 停止位:"+ui->StopBox->currentText();lableStatusBar->setText("串口打开状态:"+QObject::tr("<font color=green>%1</font>").arg(port));lableStatusBar->setFont(QFont("nihao",8));ui->statusbar->addWidget(lableStatusBar);// 关闭设置菜单使能ui->PortBox->setEnabled(false);ui->BaudBox->setEnabled(false);ui->BitNumBox->setEnabled(false);ui->ParityBox->setEnabled(false);ui->StopBox->setEnabled(false);ui->pushButtonFresh->setEnabled(false);ui->pushButtonSend->setEnabled(true);// 连接信号槽QObject::connect(serial, &QSerialPort::readyRead, this, &MainWindowUart::read32ByteData);}else{statusPort=false;QIcon icoButtonOpenPort(":/new/prefix1/closePort.PNG");ui->pushButtonOpen->setIcon(icoButtonOpenPort);ui->pushButtonOpen->setIconSize(QSize(71,37));// 关闭串口serial->clear();serial->close();serial->deleteLater();// 恢复设置使能ui->PortBox->setEnabled(true);ui->BaudBox->setEnabled(true);ui->BitNumBox->setEnabled(true);ui->ParityBox->setEnabled(true);ui->StopBox->setEnabled(true);ui->pushButtonFresh->setEnabled(true);ui->pushButtonSend->setEnabled(false);QString port="Not Open";lableStatusBar->setText("串口打开状态:"+QObject::tr("<font color=red>%1</font>").arg(port));lableStatusBar->setFont(QFont("nihao",8));ui->statusbar->addWidget(lableStatusBar);}}void MainWindowUart::on_pushButtonSend_clicked(){if(statusPort==true){if(ui->checkBoxHexSend->isChecked()){QString str=ui->textEditTxd->toPlainText();QByteArray data; //由于char *类型是有符号型的,只能表示0-127,所以得//用QByteArray类型,刚好串口write刚好有这个重载函数int len=Str2HexMe(str,data);serial->write(data,len); //因为发送的char里面可能含有0x00,所以}else{QTextCodec *codec=QTextCodec::codecForName("UTF-8");serial->write(codec->fromUnicode(ui->textEditTxd->toPlainText()));}}}/*********************************************************************************************** @brief 把十六进制数转为字符串格式** @param_i buf输入十六进制数组* @param_o hex输出字符串* @return 输入的十六进制个数* @note: (1).此函数用于窗口的十六进制显示模式显示接收到的数据**********************************************************************************************/int MainWindowUart::hex2Str(QByteArray buf,QString &hex){for (int i = 0; i < buf.size(); ++i){if(buf[i]==0x00){hex=hex+"00";}else{hex=hex+QString("%1").arg((unsigned char)buf[i],2,16,QChar('0')).toUpper();}hex=hex+" ";}return buf.size();}/*********************************************************************************************** @brief 把字符串转为十六进制数格式** @param_i str输入十六进制字符串* @param_o data 输出十六进制数* @return 输出的十六进制个数* @note: (1).此函数用于窗口的十六进制发送模式发送数据**********************************************************************************************/int MainWindowUart::Str2HexMe(QString str,QByteArray &data){deletStrBlank(str);int len=str.length();bool ok;for (int i = 0; i < len/2; ++i) {data[i]=str.mid(2*i,2).toInt(&ok,16);}return len/2;}/*********************************************************************************************** @brief 删除字符串中空格** @param_i s 输入字符串* @note: (1).此函数用于把一个字符串中的空格都删除掉,使得我们更容易处理数据**********************************************************************************************/void MainWindowUart::deletStrBlank(QString &s){int len=s.length();int j=0;for (int i = 0; i < len; ++i) {if(!s.at(i).isSpace()){s[j]=s[i];++j;}}s.remove(j,s.length()-j); //经过计算和验证这是完全正确的}void MainWindowUart::on_pushButtonClearRxd_clicked(){ui->textEditRxd->clear();}void MainWindowUart::on_pushButtonClearTxd_clicked(){ui->textEditTxd->clear();}void MainWindowUart::on_actionS_triggered(){// 获取系统时间QDateTime time=QDateTime::currentDateTime();QString strTime=time.toString("yy-MM-dd&&hh-mm-ss");// 打开文件选择对话框QString fileName = QFileDialog::getSaveFileName(this,tr("保存串口接收数据"), "串口接收数据"+strTime, tr("文本文档 (*.txt)"));if(!fileName.isNull())// 如果确实选取了目标保存文件路径,就保存,否则就是不保存{// 以只写方式打开,如果文件不存在,那么会创建该文件QFile file(fileName);if (!file.open(QIODevice::WriteOnly | QIODevice::Text))qDebug() << file.errorString();QTextStream out(&file);out<<ui->textEditRxd->toPlainText();file.close();}}void MainWindowUart::on_action_T_triggered(){(new MainWindow())->show();close();}void MainWindowUart::on_action_D_triggered(){(new MainWindowDraw())->show();close();}

如果有需要学习和使用这个软件源码的,通过我的QQ邮箱:2488890051@(马上就能回复)联系我,算是对我的劳动成果的鼓励,开发花了大量的时间和精力,作为学生,着实不容易。(大佬们,记得关注我的博客,且下面评论留言喔,谢谢哈~)

如果觉得《C++语言Qt实现 串口软件 用于嵌入式软件开发上位机通信调试软件》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。