一、电子称常用功能:称重、清零、去皮;电子秤的通讯方式:Modbus通信、串口通信。

二、QT读写电子秤软件界面如下:

三、核心代码如下:

.pro项目文件代码:

QT       += core gui serialbus serialport

.h头文件代码

#ifndef WEIGHTDATAHELPER_H
#define WEIGHTDATAHELPER_H//添加包含文件
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QModbusRtuSerialMaster>
#include <QMutex>
#include <QMutexLocker>class WeightDataHelper : public QObject
{Q_OBJECT
public:explicit WeightDataHelper(QObject *parent = nullptr);~WeightDataHelper();public slots:void OpenPort();//打开串口void ClosePort();//关闭串口void GetWeightData();//获取称重数据void ClearZeroData();//清零void SetPortName(QString strPortName);//设置端口号void GetPortNameList();//获取所有可用的串口列表void GetDeviceState();//获取设备连接状态private slots:void slotReadWeightData();//读取称重指令发送后的的返回消息void slotWriteZeroData();//读取清零指令发送后的的返回消息void slotStateChanged(QModbusDevice::State state);//连接状态改变槽函数void slotErrorOccurred(QModbusDevice::Error error);//错误发生处理槽函数signals:void sendResult(QString strResult);//发送文本消息private:QString m_PortName = "COM10";//端口号QModbusRtuSerialMaster *m_SerialMaster;//串口通信对象bool m_Connected = false;//是否打开连接QMutex m_mutex;};
#endif // WEIGHTDATAHELPER_H

.cpp详细代码如下:

#include "weightdatahelper.h"//构造函数
WeightDataHelper::WeightDataHelper(QObject *parent) : QObject(parent)
{m_SerialMaster = new QModbusRtuSerialMaster(this);//创建通信对象connect(m_SerialMaster, SIGNAL(stateChanged(QModbusDevice::State)), this, SLOT(slotStateChanged(QModbusDevice::State))); //状态改变处理connect(m_SerialMaster, SIGNAL(errorOccurred(QModbusDevice::Error)), this, SLOT(slotErrorOccurred(QModbusDevice::Error))); //发生错误处理
}//析构函数
WeightDataHelper::~WeightDataHelper()
{if (m_SerialMaster){m_SerialMaster->disconnectDevice();}delete m_SerialMaster;m_SerialMaster=nullptr;qDebug()<<"调用WeightDataHelper析构函数";
}//连接状态改变槽函数
void WeightDataHelper::slotStateChanged(QModbusDevice::State state)
{switch (state){case QModbusDevice::ConnectingState:{m_Connected = false;break;}case QModbusDevice::ConnectedState:{m_Connected = true;break;}case QModbusDevice::ClosingState:{m_Connected = false;break;}case QModbusDevice::UnconnectedState:{m_Connected = false;break;}default:break;}emit sendResult(QString("最新状态:%1").arg(m_Connected));
}//错误发生处理槽函数
void WeightDataHelper::slotErrorOccurred(QModbusDevice::Error error)
{emit sendResult("发生错误:"+m_SerialMaster->errorString());
}//设置端口号
void WeightDataHelper::SetPortName(QString strPortName)
{bool findFlag = false;foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){if(info.portName()==strPortName){findFlag = true;m_PortName = strPortName;}}if(findFlag){emit sendResult(QString("设置通信端口号为:%1成功!").arg(strPortName));}else{emit sendResult(QString("设置通信端口号为:%1失败,端口号不存在!").arg(strPortName));}
}//获取所有可用的串口列表
void WeightDataHelper::GetPortNameList()
{QString strPorName="";foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){strPorName += QString("%1;").arg(info.portName());}emit sendResult(strPorName.mid(0,strPorName.length()-1));
}//打开串口
void WeightDataHelper::OpenPort()
{if(!m_SerialMaster){return;}//设置串口相关参数m_SerialMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter,m_PortName);//设置串口信息m_SerialMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,QSerialPort::Baud9600);//设置波特率m_SerialMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,QSerialPort::Data8);//设置数据位m_SerialMaster->setConnectionParameter(QModbusDevice::SerialParityParameter,  QSerialPort::NoParity);//设置校验m_SerialMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,QSerialPort::OneStop);//设置停止位m_SerialMaster->setTimeout(1000);//设置超时时间m_SerialMaster->setNumberOfRetries(0);//设置失败重试次数//连接到设备if (m_SerialMaster->connectDevice()){m_Connected = true;//是否打开连接emit sendResult(QString("连接到串口%1成功").arg(m_PortName));}else{m_Connected = false;//是否打开连接emit sendResult("连接失败: "+ m_SerialMaster->errorString());}
}
//关闭串口
void WeightDataHelper::ClosePort()
{if (m_SerialMaster){qDebug()<<"调用关闭串口函数";m_SerialMaster->disconnectDevice();}emit sendResult(QString("断开到串口%1的连接成功").arg(m_PortName));
}//获取设备连接状态
void WeightDataHelper::GetDeviceState()
{emit sendResult(QString("连接状态:%1 串口号:%2").arg(m_Connected).arg(m_PortName));
}//清零操作入口
void WeightDataHelper::ClearZeroData()
{if(!m_Connected){emit sendResult("请连接电子称后再操作");return;}//[2025-09-08 15:11:49-524]COM10-发送:01 06 00 26 00 01 a9 c1//[2025-09-08 15:11:49-545]COM10-接收:01 06 00 26 00 01 a9 c1QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 38, 1);// 定义数据单元:保持寄存器类型、开始地址38和读取数量1QMutexLocker locker(&m_mutex); // 创建QMutexLocker对象并传入m_mutexif (QModbusReply *writeReply = m_SerialMaster->sendWriteRequest(unit, 1)){if (!writeReply->isFinished()){
//            connect(writeReply,&QModbusReply::finished,this,[this,writeReply](){
//                if(writeReply->error() == QModbusDevice::NoError)
//                {
//                    const QModbusDataUnit result = writeReply->result();
//                    QString strWeight;
//                    for (uint i = 0; i < result.valueCount(); ++i) {
//                        strWeight += QString::number(result.value(i)) + " "; //将数据值转换为字符串
//                    }
//                    qDebug()<<(QString("数据值:%1").arg(strWeight));
//                    emit sendResult(strWeight);
//                }
//                else
//                {
//                    qDebug()<<(QString("系统错误:%1").arg(writeReply->errorString()));
//                    emit sendResult(writeReply->errorString());
//                }
//            });connect(writeReply, SIGNAL(finished()), this, SLOT(slotWriteZeroData())); //异步处理槽函数}else{if (writeReply->error() != QModbusDevice::NoError){emit sendResult(writeReply->errorString());delete writeReply;}}}else{emit sendResult(QString("发送请求数据失败:%1").arg(m_SerialMaster->errorString()));}
}
//读取清零指令发送后的的返回消息
void WeightDataHelper::slotWriteZeroData()
{//接收:01 03 04 00 00 01 fe 7a 23auto writeReply = qobject_cast<QModbusReply*>(sender());if (!writeReply){qDebug()<<"写寄存器返回不为空";if (writeReply->error() == QModbusDevice::NoError){const QModbusDataUnit unit = writeReply->result();//读取响应数据QVector<quint16> vecResult = unit.values();int startAddress = unit.startAddress();qDebug()<<startAddress;if(unit.valueCount() >1){emit sendResult(QString("清零操作返回的数据长度:%1 数据1:%2 数据2:%3").arg(unit.valueCount()).arg(QString::number(vecResult.at(0))).arg(QString::number(vecResult.at(1))));}else{emit sendResult(QString("清零操作返回的数据长度:%1 数据值:%2").arg(unit.valueCount()).arg(QString::number(vecResult.at(0))));}}else if (writeReply->error() == QModbusDevice::ProtocolError){emit sendResult(QString("清零操作返回数据协议出错: %1").arg(writeReply->errorString()));}else{emit sendResult(QString("清零操作返回数据出错: %1").arg(writeReply->errorString()));}writeReply->deleteLater(); // 释放内存}else{qDebug()<<"写寄存器返回为空";emit sendResult("设置清零指令时返回空");}
}
//获取称重数据
void WeightDataHelper::GetWeightData()
{if(!m_Connected){emit sendResult("请连接电子称后再操作");return;}QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, 2);// 定义数据单元:保持寄存器类型、PLC的开始地址和地址读取数QMutexLocker locker(&m_mutex); // 创建QMutexLocker对象并传入m_mutex,当前函数执行完成则自动的调用析构函数来解锁if(QModbusReply *readReply = m_SerialMaster->sendReadRequest(unit, 1)){qDebug()<<"请求未完成";if(!readReply->isFinished()){qDebug()<<"绑定回复完成的信号";
//            connect(readReply,&QModbusReply::finished,this,[this,readReply](){
//                if(readReply->error() == QModbusDevice::NoError)
//                {
//                    const QModbusDataUnit result = readReply->result();
//                    QString strWeight;
//                    for (uint i = 0; i < result.valueCount(); ++i) {
//                        strWeight += QString::number(result.value(i)) + " "; //将数据值转换为字符串
//                    }
//                    qDebug()<<(QString("数据值:%1").arg(strWeight));
//                    emit sendResult(strWeight);
//                }
//                else
//                {
//                    qDebug()<<(QString("系统错误:%1").arg(readReply->errorString()));
//                    emit sendResult(readReply->errorString());
//                }
//            });connect(readReply, SIGNAL(finished()), this, SLOT(slotReadWeightData())); //异步处理槽函数}else{qDebug()<<"请求已完成";if (readReply->error() != QModbusDevice::NoError){emit sendResult(readReply->errorString());delete readReply;}}}else{qDebug()<<"请求错误";emit sendResult(m_SerialMaster->errorString());}
}//读取称重数据槽函数
void WeightDataHelper::slotReadWeightData()
{auto readReply = qobject_cast<QModbusReply*>(sender());if (readReply){qDebug()<<"读取称重数据时返回非空";if (readReply->error() == QModbusDevice::NoError){const QModbusDataUnit unit = readReply->result();//读取响应数据QString strWeight;for (uint i = 0; i < unit.valueCount(); ++i) {strWeight += QString::number(unit.value(i)) + " "; //将数据值转换为字符串}qDebug()<<(QString("数据值:%1").arg(strWeight));emit sendResult(strWeight);}else if (readReply->error() == QModbusDevice::ProtocolError){qDebug()<<"读取称重返回数据协议出错";emit sendResult(QString("读取称重返回数据协议出错: %1").arg(readReply->errorString()));}else{qDebug()<<"读取称重返回数据出错";emit sendResult(QString("读取称重返回数据出错: %1").arg(readReply->errorString()));}readReply->deleteLater(); //通过事件循环延迟删除}else{qDebug()<<"读取称重数据时返回空";emit sendResult("读取称重数据时返回为空");}
}

四、相关问题需处理:

      4.1  当前代码直接可以在QT中运行,但是封装称DLL后不能正常提供给C#调用,需要调整为同步获取返回结果。
4.2  返回的寄存器数据需要通过大小端转换显示正确的数据。

      4.3  使用串口调试助手可直接发命令给到电子秤读写内部寄存器数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/98794.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/98794.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/98794.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sqlmap常用命令

ZZHow(ZZHow1024) 一、扫描注入点 1.GET方法&#xff0c;给URL&#xff1a; #探测该url是否存在漏洞 python sqlmap.py -u "http://192.168.10.1/sqli/Less-1/?id1"#如果我们已经知道admin这里是注入点的话&#xff0c;可以在其后面加个*来让sqlmap对其注入 python …

JVM如何排查OOM

当JVM&#xff08;Java虚拟机&#xff09;出现OOM&#xff08;OutOfMemoryError&#xff09;时&#xff0c;可以按照以下步骤和方法&#xff0c;用于帮助定位和解决JVM中的OOM问题1.查看异常堆栈信息查看异常堆栈信息&#xff08;StackTrace&#xff09;是定位问题的关键。OOM异…

存算一体芯片生态评估:从三星PIM到知存科技WTM2101

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;注册即送-H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 引言&#xff1a;存算一体技术的崛起与意义 在传统冯诺…

[数据结构] 栈 · Stack

一.栈 stack 1.概念 栈 : 一种特殊的线性表 , 其只允许再固定的一段进行插入和删除元素操作 进行数据插入和删除操作的一段称为 栈顶 ; 另一端称为栈底栈中的数据元素遵循 先进后出 原则(LIFO)压栈 : 栈的插入操作叫做 进栈 或 压栈 或 入栈 , 入数据在栈顶出栈 : 栈的删除…

MySQL执行过程中如何选择最佳的执行路径

本篇文章介绍一个非常核心的数据库问题。MySQL 选择最佳执行路径&#xff08;即“查询优化”&#xff09;的过程是由其查询优化器&#xff08;Query Optimizer&#xff09; 完成的。 简单来说&#xff0c;优化器的目标是&#xff1a;在多种可能的执行方案中&#xff0c;选择一个…

【设计模式】从游戏角度开始了解设计模式 --- 抽象工厂模式

永远记住&#xff0c;你的存在是有意义的&#xff0c; 你很重要&#xff0c; 你是被爱着的&#xff0c; 而且你为这个世界带来了无可取代的东西。 -- 麦克西 《男孩、鼹鼠、狐狸和马》-- 从零开始了解设计模式抽象工厂模式抽象工厂模式 今天我们一起来探究抽象工厂模式&#x…

tensorflow.js 使用场景

TensorFlow.js (简称 TF.js) 是一个利用 WebGL 和 Node.js 在浏览器和服务器端进行机器学习模型训练和部署(推理)的 JavaScript 库。它的核心价值在于将机器学习的能力带入了 Web 开发者和 JavaScript 生态的领域。 其主要应用场景可以分为以下几大类: 一、在浏览器中直接进…

详解mcp以及agen架构设计与实现

文章目录1.MCP概念2.MCP服务端主要能力3.MCP技术生态4.MCP与Function call区别5.MCP生命周期6.MCP java SDK7.MCP应用场景8.基于springAIollma阿里qianwenmcp设计私有AIAgent应用实现9.AI java项目落地技术选型10.构建AI Agent四大模块11.LLM(大模型)与MCP之间关系12.A2A、MCP、…

六级第一关——下楼梯

上目录&#xff1a; 目录 题目描述 输入格式 输出格式 输入输出样例 说明/提示 一、DP的意义以及线性动规简介 在一个困难的嵌套决策链中&#xff0c;决策出最优解。 二、动态规划性质浅谈 三、子序列问题 &#xff08;一&#xff09;一个序列中的最长上升子序列&am…

【Linux基础】Linux系统配置IP详解:从入门到精通

目录 1 Linux网络配置概述 2 网卡配置文件位置和命名规则 2.1 配置文件位置 2.2 网卡命名规则 2.3 配置文件命名示例 3 网卡配置文件详解 3.1 主要参数说明 4 Linux系统配置IP步骤 4.1 DHCP动态配置 4.2 静态IP配置 5 Linux网络配置流程 5.1 网络配置流程 5.2 网卡…

C语言sprintf的高效替代方案

C语言的sprintf和snprintf将变量格式化输出到内存buffer&#xff0c;其功能强大&#xff0c;用起来很方便。但sprintf系列函数的运行效率低下&#xff0c;主要包括四方面的原因&#xff1a;格式字符串解析、变参处理、locale&#xff08;本地化&#xff09;支持和通用&#xff…

【知识堂】制造业与物流数字化全景图:系统缩写大全与专业名词速查手册

前言在制造业和物流行业的数字化转型过程中&#xff0c;我们经常会接触到大量的 系统缩写&#xff08;如 ERP、MES、WMS…&#xff09;和 专业名词&#xff08;如 AGV、BOM、LOT…&#xff09;。 这些缩写往往让刚入行的人“一头雾水”&#xff0c;即使是有经验的从业者&#x…

利用JSONCrack与cpolar提升数据可视化及跨团队协作效率

文章目录前言1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址前言 JSONCrack 是一款功能强大的开源数据可视化工具&#xff0c;专为解析和展示复杂的 JSON、XML 等结构化数据…

CANoe入门之一 CANoe功能概述

01 CANoe功能概述 CANoe软件在汽车电子领域被广泛应用。 CANoe软件的全称是CAN Open Environment&#xff0c;它是一个专业的系统级总线和ECU仿真、分析、开发、测试工具。支持ECU或总线网络开发从需求分析到系统实现的全过程&#xff0c;包括模型创建、仿真、测试、诊断及通信…

项目管理核心八项(软件篇)

2025年09月11日23:50:33&#xff1a;进来常思&#xff0c;写代码也五六年了&#xff0c;后面的路该何去何从呢&#xff1f; 项目管理核心八项一、项目管理之“建立开发人员 backup 机制”二、待补充一、项目管理之“建立开发人员 backup 机制” “建立开发人员 backup 机制” 是…

springboot redisson 分布式锁入门与实战

Spring Boot3 Redisson 项目地址 https://gitee.com/supervol/loong-springboot-study &#xff08;记得给个start&#xff0c;感谢&#xff09; Redisson 介绍 在分布式系统中&#xff0c;多节点部署的应用对共享资源&#xff08;如数据库记录、缓存键、文件&#xff09;的…

使用 Tkinter + Requests 实现地理信息安全系统学习时长助手

✨重磅&#xff01;盹猫的个人小站正式上线啦&#xff5e;诚邀各位技术大佬前来探秘&#xff01;✨ 这里有&#xff1a; 硬核技术干货&#xff1a;编程技巧、开发经验、踩坑指南&#xff0c;带你解锁技术新姿势&#xff01;趣味开发日常&#xff1a;代码背后的脑洞故事、工具…

构建一个优雅的待办事项应用:现代JavaScript实践

构建一个优雅的待办事项应用&#xff1a;现代JavaScript实践本文将介绍如何使用现代JavaScript&#xff08;ES6&#xff09;和DOM操作创建一个功能完整的待办事项应用&#xff0c;无需任何外部库或框架。功能概述添加新任务标记任务为完成/未完成编辑任务内容删除任务过滤任务&…

【数据可视化-111】93大阅兵后的军费开支情况———2024年全球军费开支分析:用Python和Pyecharts打造炫酷可视化大屏

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

3.2.Maven-概述-介绍安装

一.介绍&#xff1a;二.安装&#xff1a;Maven的安装比较简单&#xff0c;因为他是绿色版的软件&#xff0c;官方给我们提供Maven的安装包就是一个zip压缩包&#xff0c;在进行Maven安装以及配置的时候&#xff0c;主要进行如下4步操作&#xff1a;第一步&#xff1a;把官方提供…