基于qt的串口通信小助手

一、程序简介

        基于qt框架的串口通信助手小工具。在基础的通信调试功能基础上,添加了:发送文件,保存成文件;数据滤波;数据波形显示,对一个数据的分析,可同时显示多个波形。通过Linguist生成的qm文件进行中英文一键切换,通过全局的qss文件设置界面颜色风格。通过配置注册表来读取上次运行配置的一些初始设置进行初始化。

        其中加载qss文件的文章联接http://t.csdnimg.cn/XaNAv

二、辅助工具

        借用虚拟串口工具VSPD7.2,模拟COM1、COM2连接串口,并将两端口连接,COM1发COM2收,COM2发COM1,从而方便进行软件功能测试。

三、程序展示

1、基本功能

基本功能借鉴了xcom

.基础收发功能

可系统编码收发,16进制收发,定时发送,时间戳换行显示。

收到消息的处理槽函数源码:

/**
 * @brief 处理接收数据槽
 * @author LiDonglin
 * @date 20240707
 */
void MainWindow::readData() {
    QByteArray data = serial.readAll();
    QString text = QString::fromLocal8Bit(data.constData());
    readSize += text.size();
    /* 处理接收到的数据 */
    ui->label_3->setText(QString::number(readSize));
    if(ui->checkBox_12->isChecked())//16进制显示
    {
        QString hexStr = data.toHex().toUpper();
        QString initialStrTemp = setFilteringDialog.getInitialStr();
        initialStrTemp.remove(" ");
        for(int i = 0;i<initialStrTemp.size();++i)//校验是否为字头
        {
            if(initialStrTemp[i]!=hexStr[i])return;
        }
        QString outDate;//去掉字头,将有用数据传给波形显示窗口
        int l = std::min(hexStr.size()-initialStrTemp.size(),(long long)setFilteringDialog.getLine());
        for(int i = initialStrTemp.size();i<initialStrTemp.size()+l;++i)
        {
            outDate.push_back(hexStr[i]);
        }
        emit valueChanged(outDate);
        switch(setFilteringDialog.getModle())
        {
        case 1:
            break;
        case 2:
            for(int i = 0;i<initialStrTemp.size();++i)//添加字头
            {
                ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
                ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
                if(i%2 == 1)
                {
                    ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
                    ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
                }
            }
            break;
        }
        for(int i = initialStrTemp.size();i<initialStrTemp.size()+setFilteringDialog.getLine()*2;++i)
        {
            if(i == hexStr.size())break;
            ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
            ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
            if(i%2 == 1)
            {
                ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
                ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
            }
        }
    }
    else//系统编码显示
    {
        ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
        ui->textBrowser->insertPlainText(text); // 在光标位置插入文本
    }
    if(ui->checkBox_13->isChecked())//时间戳换行
    {
        QDateTime currentDateTime = QDateTime::currentDateTime();
        ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
        ui->textBrowser->insertPlainText(currentDateTime.toString("[yyyy-MM-dd HH:mm:ss]")+"\r\n"); // 在光标位置插入文本
    }
}

发送消息的处理槽函数源码:

/**
 * @brief 16进制或普通发送工具
 * @param 要发送的数据
 * @param 是否16进制发送
 * @author LiDonglin
 * @date 202407010
 */
void MainWindow::is16OutTool(QString text,bool is)
{
    /* 更新已发送数据量 */
    writeSize += text.size();
    ui->label_4->setText(QString::number(writeSize));
    if(is)//16进制发送
    {
        QStringList strList = text.split(' ', Qt::SkipEmptyParts);
        for(const auto&it:strList)
        {
            bool ok;
            int value = it.toInt(&ok,16);
            QByteArray outdate;
            outdate.append(static_cast<char>(value));
            serial.write(outdate);
        }
    }
    else//系统编码发送
    {
        serial.write(text.toLocal8Bit());
    }
}
/**
 * @brief 发送数据槽
 * @author LiDonglin
 * @date 20240707
 */
void MainWindow::on_pushButton_5_clicked()
{
    QString text = ui->textEdit->toPlainText();
    is16OutTool(text,ui->checkBox_2->isChecked());
}

程序视频演示:

串口助手基础功能展示

.多条记忆发送

可同时发送多条指令,可进行文件导入导出。

记忆导入导出处理源码:

/**
 * @brief 导出记忆槽
 * @author LiDonglin
 * @date 20240710
 */
void MainWindow::on_pushButton_12_clicked()
{
    QString filePath = ReadFile.getOpenFileName(this,textDialogDio,"./","txt(*.txt*)");
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return;
    }
    QTextStream out(&file);
    for(int i = 0;i<OutLints.size();++i)
    {
        QString line = OutLints[i]->text();
        if(line.size() == 0)
        {
            out << "&nullptr&\n"; // 写入一行文本,并添加换行符
        }
        else
        {
            out << line << "\n"; // 写入一行文本,并添加换行符
        }
    }
    file.close();
}
/**
 * @brief 导入记忆槽
 * @author LiDonglin
 * @date 20240710
 */
void MainWindow::on_pushButton_13_clicked()
{
    QString filePath = ReadFile.getOpenFileName(this,textDialogDio,"./","txt(*.txt*)");
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return;
    }
    QTextStream in(&file);
    // 逐行读取文件内容
    int i = 0;
    while (!in.atEnd()) {
        QString line = in.readLine();
        if(line == "&nullptr&")
        {
            ++i;
            continue;
        }
        OutLints[i++]->setText(line);
    }
}

视频展示:

串口助手记忆发送功能展示

 .文件io

文件读写函数源码:

/**
 * @brief 发送文件
 * @author LiDonglin
 * @date 20240708
 */
void MainWindow::on_pushButton_9_clicked()
{
    QFile file(readTextPath);
    // 尝试以只读和文本模式打开文件
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "无法打开文件进行读取:" << file.errorString();
        return;
    }
    QTextStream in(&file);
    // 逐行读取文件内容
    long long value = 0;
    long long h = file.size();
    while (!in.atEnd()) {
        QString line = in.readLine()+"\r\n";
        serial.write(line.toLocal8Bit());
        value += line.size();
        ui->progressBar->setValue((int)(value*300/h));
        readSize += line.size();
        ui->label_3->setText(QString::number(readSize));
    }
    ui->progressBar->setValue(100);
    // 完成读取后,关闭文件
    file.close();
}
/**
 * @brief 保存窗口文件
 * @author LiDonglin
 * @date 20240710
 */
void MainWindow::on_pushButton_11_clicked()
{
    QFile file(writeTextPath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return;
    }
    QTextStream out(&file);
    ui->progressBar_2->setValue(50);
    out << ui->textBrowser->toPlainText();
    ui->progressBar_2->setValue(100);
    file.close();
}

 程序视频演示:

串口助手文件io展示

2、其他功能 

.数据波形显示功能

弹出窗口,在窗口上设置解析规则,在规则先用波形图显示解析内容,可同时显示多个窗口。

数据更新显示处理函数源码:

/**
 * @brief 信息更新处理槽
 * @param 主窗口发送的数据
 * @author LiDonglin
 * @date 202407017
 */
void DisplayDialog::getDate(QString date)
{
    QList<int> nums;

    for(int i = 0;i<date.size();++i)//转化数组为字节数字列表
    {
        int num;
        if(i % 2 == 0)
        {
            if(date[i]>='0'&&date[i]<='9')
            {
                num = (date[i].unicode()-'0')*16;
            }
            else
            {
                num = (date[i].unicode()-'A'+10)*16;
            }
        }
        else
        {
            if(date[i]>='0'&&date[i]<='9')
            {
                num += (date[i].unicode()-'0');
            }
            else
            {
                num += (date[i].unicode()-'A'+10);
            }
            nums.push_back(num);
        }
    }
    if(nums.size()<ui->spinBox_4->value()+1)//数据筛选合法性保证
    {
        ui->spinBox_4->setValue(ui->spinBox_4->value()+1);
    }
    if(ui->spinBox_4->value()<ui->spinBox_3->value())
    {
        ui->spinBox_3->setValue(ui->spinBox_4->value());
    }
    showNum = 0;
    for(int i = ui->spinBox_4->value(),j = 0;i>=ui->spinBox_3->value();--i,++j)
    {
        showNum += nums[i]*std::pow(256,j);
    }
}
/**
 * @brief 开启关闭串通信
 * @param 新选中的选项的文本内容
 * @author LiDonglin
 * @date 20240707
 */
void MainWindow::on_pushButton_clicked(bool checked)
{
    if(!checked)
    {
        serial.close();
        disconnect(&serial, &QSerialPort::readyRead, this, &MainWindow::readData);
        ui->pushButton->setText(noStr);
        ui->pushButton_5->setEnabled(false);
    }
    else
    {
        if(serial.open(QIODevice::ReadWrite))
        {
            connect(&serial, &QSerialPort::readyRead, this, &MainWindow::readData);
            ui->pushButton->setText(offStr);
            ui->pushButton_5->setEnabled(true);
        }
        else
        {
            QErrorMessage *errorMessage = new QErrorMessage(this);
            errorMessage->setModal(true);
            QString tempString = serial.portName()+OpenFailedStr;
            errorMessage->setWindowTitle(OpenFailedStr1);
            errorMessage->showMessage(tempString);
        }
    }

}
/**
 * @brief 处理接收数据槽
 * @author LiDonglin
 * @date 20240707
 */
void MainWindow::readData() {
    QByteArray data = serial.readAll();
    QString text = QString::fromLocal8Bit(data.constData());
    readSize += text.size();
    /* 处理接收到的数据 */
    ui->label_3->setText(QString::number(readSize));
    if(ui->checkBox_12->isChecked())//16进制显示
    {
        QString hexStr = data.toHex().toUpper();
        emit valueChanged(hexStr);
        for(int i = 0;i<readSize;++i)
        {
            if(i == hexStr.size())break;
            ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
            ui->textBrowser->insertPlainText(hexStr[i]); // 在光标位置插入文本
            if(i%2 == 1)
            {
                ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
                ui->textBrowser->insertPlainText(" "); // 在光标位置插入文本
            }
        }
    }
    else//系统编码显示
    {
        ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
        ui->textBrowser->insertPlainText(text); // 在光标位置插入文本
    }
    if(ui->checkBox_13->isChecked())//时间戳换行
    {
        QDateTime currentDateTime = QDateTime::currentDateTime();
        ui->textBrowser->moveCursor(QTextCursor::End); // 将光标移动到文本末尾
        ui->textBrowser->insertPlainText(currentDateTime.toString("[yyyy-MM-dd HH:mm:ss]")+"\r\n"); // 在光标位置插入文本
    }
}

程序视频演示:

串口助手波形显示功能展示

.一键切换加载的qss样式文件及qm语言

程序视频演示:

串口助手样式语言切换展示

.注册表保存状态

注册表保存上传运行程序时设置的样式表及语言状态,程序运行时读取状态。

关键代码:

/**
 * @brief 注册表初始化并获取注册表当前配置
 * @brief 程序的控制中心的引用
 * @author LiDonglin
 * @date 20240716
 */
void settingsInit(QApplication& a)
{
    QSettings settings("HKEY_CURRENT_USER\\Software\\LDLsQtApp", QSettings::NativeFormat);
    QString Value = settings.value("translator").toString();// 获取语言配置
    /* 配置语言 */
    if (Value == "") {//第一次运行程序,初始化注册表
        settings.setValue("translator", "0");
    } else {
        if(Value == "1")
        {
            if(g_translator.load(":/Qm/en.qm"))
            {
                qApp->installTranslator(&g_translator);
            }
        }
    }
    /* 配置样式表 */
    Value = settings.value("qss").toString();// 获取样式表配置
    if (Value == "") {//第一次运行程序,初始化注册表
        settings.setValue("qss", "0");
        QFile file(":/qss/day.qss"); // 注意路径是从资源文件的根开始的
        if (file.open(QFile::ReadOnly)) {
            QTextStream stream(&file);
            QString styleSheet = stream.readAll();
            a.setStyleSheet(styleSheet);
            file.close();
        }
    } else {
        if(Value == "0")//白
        {
            QFile file(":/qss/day.qss");
            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                QString styleSheet = stream.readAll();
                a.setStyleSheet(styleSheet);
                file.close();
            }
        }
        else if(Value == "1")//黑
        {
            QFile file(":/qss/night.qss");
            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                QString styleSheet = stream.readAll();
                a.setStyleSheet(styleSheet);
                file.close();
            }
        }
        else if(Value == "2")//天蓝
        {
            QFile file(":/qss/skyBlue.qss");
            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                QString styleSheet = stream.readAll();
                a.setStyleSheet(styleSheet);
                file.close();
            }
        }
    }
}

程序视频演示:

串口助手注册表展示

四、开源说明

.gitee仓库链接:

git@gitee.com:LDLmcu/uart-assistant.git

.UartAssistantApp:

动态库打包发布文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值