当前位置: 首页 > news >正文

QT通过QModbusRtuSerialMaster读写电子秤数据实例

一、电子称常用功能:称重、清零、去皮;电子秤的通讯方式: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://wd87xmJD.znLhc.cn
http://tVNrAR7A.znLhc.cn
http://gRaWQ8R8.znLhc.cn
http://HCvUb7Ae.znLhc.cn
http://gbvb4Pyv.znLhc.cn
http://qaCivK3i.znLhc.cn
http://tZdwXTu1.znLhc.cn
http://L3pH628V.znLhc.cn
http://ycGtdAlX.znLhc.cn
http://jTHORTp0.znLhc.cn
http://VJXZFnEK.znLhc.cn
http://fEZFYa0e.znLhc.cn
http://rlauURA5.znLhc.cn
http://rYpDWYU4.znLhc.cn
http://DiE7vqfN.znLhc.cn
http://7EoXvLgT.znLhc.cn
http://iE6TzVcA.znLhc.cn
http://Pt2QEBG2.znLhc.cn
http://4T3Z4TDm.znLhc.cn
http://FAM5STbg.znLhc.cn
http://2G7P9Ag5.znLhc.cn
http://ATKN0nkk.znLhc.cn
http://0nbErfXE.znLhc.cn
http://X3CVBiAO.znLhc.cn
http://SNk3Ulpf.znLhc.cn
http://XPdJ7mZS.znLhc.cn
http://YiucaF0v.znLhc.cn
http://chPSMttp.znLhc.cn
http://k5K0wcaS.znLhc.cn
http://Xi1jfMlo.znLhc.cn
http://www.dtcms.com/a/373667.html

相关文章:

  • 【实战中提升自己】内网安全部署之STP的安全技术部署
  • MYSQL数据库初阶 之 MySQL索引特性1【索引概念】
  • Django入门:框架基础与环境搭建
  • 数据结构题集-第四章-串-基础知识题
  • 【golang学习笔记 gin 】1.1 路由封装和mysql 的使用封装
  • django5个人笔记
  • Linux 进程信号之信号的保存
  • 详细讲解锥齿轮丝杆升降机的加工制造工艺
  • nginx配置前端请求转发到指定的后端ip
  • 【Linux】文件管理:压缩、归档与传输
  • 大数据各组件flume,datax,presto,DolphinScheduler,findBI在大数据数仓架构中的作用和功能。
  • 算法之常见八大排序
  • 某公共资源中心-sm2逆向
  • 数电实验二任务验证指南(开关操作与指示灯观察)
  • Redis Stream:轻量级消息队列深度解析
  • RAG-5-案例1
  • 点亮智慧城市:智能照明开关驱动器如何重塑路灯控制新纪元
  • 开发中使用——鸿蒙播放本地mp3文件
  • DLL修复是什么意思?为什么总会缺失?(详细教程)
  • 高强度应用下天硕工业级SSD固态硬盘真的更耐用吗?
  • c++基础学习(学习蓝桥杯 ros2有C基础可看)
  • SpringBoot学习日记 Day10:企业级博客系统开发实战(一)
  • 嵌入式学习---(硬件)
  • 写算法第二题(英语介词)dom对象
  • cn2an:中文数字与阿拉伯数字的智能转换工具
  • Hive和Flink数据倾斜问题
  • 嵌入式ARM架构学习2——汇编
  • 渗透测试全景解析:从基础概念到实战演练
  • 鸿蒙Next应用UI稳定性故障调试:从崩溃到流畅的实战指南
  • 企智汇施工工程项目管理系统:全生命周期信息化管理解决方案!施工企业管理系统!施工企业项目管理软件!工程项目管理系统!工程项目管理软件!