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://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;把官方提供…