QtModbus Serial 简单示例

2023-10-31

来自QQ群 Linux && 技术分享 311078264
打开链接加入QQ群:https://jq.qq.com/?_wv=1027&k=5Gr3bAx
此文档由elikang整理,为了文章简单直接,许多细节未能在文章中体现,如有疑问请进群讨论。

 

Qt Modbus在QtCreator的示例里面有例子,直接搜modbus就可以看到了,简单学一下就能学会了。

首先,QT5是自带Modbus相关类的,使用时需要在pro文件里面添加一行:

QT += serialbus

 

My_Modbus.h

/*
 * My_Modbus.h
 *
 *  Created on: 2021年3月11日
 *      Author: elikang
 */

#ifndef MY_MODBUS_H
#define MY_MODBUS_H

#include <QObject>
#include <QSerialPort>
#include <QModbusDataUnit>
#include <QModbusRtuSerialMaster>

class My_Modbus : public QObject
{
    Q_OBJECT
    
public:
    My_Modbus();
    ~My_Modbus();
    
    void modbusConnect(void);
    void modbusDisconnect(void);
    void modbusRead(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries);
    void modbusWrite(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data);
    
signals:
    void modbusReadReady(QModbusDataUnit dataUnit);
        
public slots:
    void modbusStateChanged(void);    
    void modbusReadData(void);
    
    void modbusMessage(void);
    void modbusMessage(QString mess);
    
public:
    struct Settings {
        QString portName;
        int parity = QSerialPort::EvenParity;
        int baud = QSerialPort::Baud115200;
        int dataBits = QSerialPort::Data8;
        int stopBits = QSerialPort::OneStop;
        int responseTime = 1000;
        int numberOfRetries = 1;
    };        
    
private:
    QModbusClient *modbusDevice = nullptr;
    
    Settings m_settings;        
}

#endif

My_Modbus.cpp

/*
 * My_Modbus.cpp
 *
 *  Created on: 2021年3月11日
 *      Author: elikang
 */

#include “my_modbus.h”
#include “qdebug.h”

My_Modbus::My_Modbus()
{
    modbusDevice = new QModbusRtuSerialMaster(nullptr);
    connect(modbusDevice, SIGNAL(errorOccurred()), this, SLOT(modbusMessage()));
    
    if(modbusDevice)
    {
        qDebug("创建 Modbus Master 成功。");
        connect(modbusDevice, &QModbusClient::stateChanged, this, &My_Modbus::modbusStateChanged);
    }
    else
    {
        qDebug("创建 Modbus Master 失败。");        
    }
}

My_Modbus::~My_Modbus()
{
    delete modbusDevice;
}

void My_Modbus::modbusConnect(void)
{
    if(!modbusDevice) return;
    
    if(modbusDevice->state() != QModbusDevice::Connected)
    {
           modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, m_settings.portName);        
           modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_settings.baud);   
           modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, m_settings.parity);             
           modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, settings.dataBits);        
           modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_settings.stopBits);        
           
           modbusDevice->setTimeout(m_settings.responseTime);        
           modbusDevice->setNumberOfRetries(m_settings.numberOfRetries);           
           
           if(modbusDevice->connectDevice())
           {
                qDebug("Modbus 连接成功。");
           }
           else
           {
                qDebug("Modbus 连接失败。");
           }
    }
}

void My_Modbus::modbusDisconnect(void)
{
    if (modbusDevice)   modbusDevice->disconnectDevice();    
    delete modbusDevice;
    modbusDevice = nullptr;    
}

void My_Modbus::modbusStateChanged(int state)
{
    if(state == QModbusDevice::UnconnectedState)
    {
        qDebug("Modbus 已断开。");
    }
    else if(state == QModbusDevice::ConnectedState)
    {
        qDebug("Modbus 已连接。");
    }
}

void My_Modbus::modbusMessage(void)
{
    qDebug() << modbusDevice->errorString();
}

void My_Modbus::modbusMessage(QString mess)
{
    qDebug() << mess;
}


void My_Modbus::modbusRead(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data)
{
        if(!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) 
        {
                qDebug("Modbus Device is not connected!");        
                return;    
        }
        
        QModbusDataUnit dataUnit = QModbusDataUnit(table, startAddress, numOfEntries);    
        
        if(auto *reply = modbusDevice->sendReadRequest(dataUnit, serverAddress))
        {
                if(reply->isFinished())
                {
                    connect(reply, &QModbusReply::finished, this, &My_Modbus::modbusReadData);
                }
        }
        else
        {
             modbusMessage(tr("Write error:") + modbusDevice->errorString());
        }
}

void My_Modbus::modbusReadData()
{
    QModbusDataUnit dataUnit;
    auto reply = qobject_cast<QModbusReply *>(sender());
    if(!reply) return;
    
    if(reply->error() == QModbusDevice::NoError)
    {
        dataUnit = reply->result();
        emit modbusReadReady(dataUnit);
    }
    else if(reply->error() == QModbusDevice::ProtocolError)
    {
        modbusMessage(tr("Read response error: %1 (Modbus exception :0x%2)")
                                        .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1 ,16));
    }
    else
    {
        modbusMessage(tr("Read response: %1 (code :0x%2)")
                                        .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1 ,16));    
    }
    
    reply->deleteLater();
}

//服务器地址、寄存器类型、起始地址、变量数量、写入数据
void My_Modbus::modbusWrite(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data)
{
        if(!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) 
        {
                qDebug("Modbus Device is not connected!");        
                return;    
        }
        
        //QModbusDataUnit,是用来处理通过串口一次传输的数据    
        QModbusDataUnit dataunit = QModbusDataUnit(table, startAddress, numOfEntries);
        
        for(uint i = 0; i < dataunit.valueCount(); i++)
        {
                dataunit.setValue( i,  data.at(i));
        }
        
        if(auto *reply = modbusDevice->sendWriteRequest(dataunit,  serverAddress))
        { 
                      connect(reply, &QModbusReply::finished, this, [this, reply](){
                                if(reply->error() == QModbusDevice::ProtocolError){          
                                          modbusMessage(tr("Write response error:%1 (modbus exception:0x%2)")
                                                                           .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);                
                                }else{         
                                          modbusMessage(tr("Write response:%1 (code:0x%2)")
                                                                           .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);                
                                }
     
                                reply->deleteLater();            
                                });                       
         }
         else{            
                        statusBar()->showMessage(tr("Write error:") + modbusDevice->errorString(), 5000);        
               }    
   }


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QtModbus Serial 简单示例 的相关文章

  • 在Qt中,如何正确实现委托?

    我遵循模型 视图 控制器范例 我很确定模型和视图是正确的 但我认为我的代表做错了一些事情 一切都 有效 除了第一次单击控件只是 点亮控件 而第二次单击与之交互之外 这是代表通常的实施方式吗 我的实现需要大量的构造和销毁 由scoped pt
  • 如何使用 qt 库中的调试符号为 qt 5.5 创建开发 shell

    我有一个开发外壳buildInputs条目包括qt55 qtbase 这很好用 今天 我在 qt 库中发生了段错误 我想要带有调试符号的 qt 库 我看了一下nixpkgs pkgs development libraries qt 5 5
  • QT C++ QRegularExpression 多个匹配

    我想使用正则表达式从 QString html 中提取信息 我明确想使用正则表达式 无解析器解决方案 和类Q正则表达式 http qt project org doc qt 5 0 qtcore qregularexpression htm
  • MSVC C4100:“应用程序”:未引用的形式参数警告

    使用 MSVC 编译时 以下代码会生成 C4100 警告 这怎么可能 显然引用了 应用程序 class ApplicationInfo public QObject Q OBJECT public static void initializ
  • qt 如何知道按钮被点击?

    我正在尝试编写一个程序 用声音进行一些操作 我的问题是我有 3 个播放按钮和 3 个标签 我希望无论我单击 播放 按钮 都应该播放按钮附近标签中名称的声音 我有一个没有任何参数的播放插槽 那么 如何分别连接到每个播放按钮和每个标签呢 实际上
  • 在另一个中使用 QAbstractListModel

    我在尝试使用 Qt QML 为我的应用程序开发数据模型时遇到问题 我已经用过一个QAbstractListModel能够将海关数据模型从 C 传递到 QML 并且它对于简单模型 例如基于字符串和布尔的模型 来说就像一个魅力 但现在我需要建立
  • 构建qt程序时未定义的符号:找不到qt_version_tag

    我正在学习Qt5 6 我正在使用 Ubuntu 14 4 当我链接我的程序时 出现以下错误 undefined reference to qt version tag 在 CMakeLists txt 中 link libraries Qt
  • 如何从键盘为 QTableWidget 创建信号?

    我有一张桌子 可以通过左 右 上 下按钮在里面移动 现在 当我停留在某个单元格并按空格键时 我需要创建一个信号 该信号还应该带来该单元格的坐标 我尝试使用 QTableWidget 的标准信号 但它不起作用 我该如何解决这个问题 创建一个单
  • 仅当从 Qt 连接时网页返回 HTTP 406 错误

    我有一个测试页面设置http mlecturedownload com test qt php http mlecturedownload com test qt php有以下代码
  • Qt 码头调整大小事件

    有没有办法在 Qt 中捕捉码头的调整大小事件 我需要能够检测到扩展坞何时调整大小 而不仅仅是其位置或 功能 发生变化时 看起来 QDockWidget 没有 调整大小 信号 如果您不希望子类化以仅获得调整大小事件控件 您可以安装事件过滤器
  • 如何在Qt中更快地读取数据?

    Qt读取数据库比C 慢吗 我想我错过了一些东西 为了比较阅读速度 我在 Qt 中编写了以下内容 QElapsedTimer t t start int count 0 QString cs Driver SQL Server Server
  • 如何从 ffmpeg 中打开的文件获取流信息?

    我正在尝试使用 ffmpeg 读取视频文件 我有与其旧版本相对应的工作代码 并开始尝试升级到最新的构建版本 将所有这些已弃用的函数替换为其实际的类似函数 但是我遇到了问题 似乎没有检索到任何流 并且视频负载停止在轨道中 这是我正在使用的代码
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何改善 Qt5 程序的启动时间?

    我最近切换到 Qt5 我注意到与 Qt4 相比 初始化 QApplication 花费的时间明显更长 大约几分钟 仔细一看 程序似乎把时间花在了这里 Qt5Guid dll QGlobalStatic
  • 在 Qt 中旋转图像

    在我的应用程序中 我想旋转图像 我已将图像设置为QLabel 我已经设置了一个QPushButton 单击该按钮时我想向四个方向旋转图像 右 gt 底部 gt 左 gt 顶部 有什么帮助吗 假设您有一个指向 QLabel 的指针 您可以执行
  • 在 Qt 中构建 Android 项目不再有效

    所以我对 Android SDK NDK 和 Apache Ant 进行了一些更新 现在我无法构建任何 Android 项目 我收到一条警告 然后它说找不到 build xml 文件 错误 Warning Android platform
  • 如何在 PySide/PyQt 中制作一个位于屏幕中央的小部件?

    这段代码有效 但我想知道是否有更简单的方法 def center self qr self frameGeometry cp gui QDesktopWidget availableGeometry center qr moveCenter
  • { Qt5.0.2/QML/QtQuick2.0/C++ } 运行没有错误的示例项目? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我的设置是Qt5 0 2 MinGW 32位 我在寻找 Qt5 0 2 QML QtQuick2 0 C 代码项目示例 不是Qt Qu
  • 关于在 Qt 中使用未记录的类

    使用无证文件是否安全QObjectUserData类和QObject setUserData in Qt 相反 你可以看看使用QObject setProperty http doc qt io qt 5 qobject html setP
  • C++:头文件中全局函数的多重定义错误

    该函数是全局的 在头文件中定义 暂时地我想把它留在那里 头文件还构成一个具有内联函数的特定类 其中一个函数调用this全局函数 源文件不包含任何有问题的全局函数 有关错误原因的任何提示吗 如果有人感兴趣的话我可以发布代码 mainwindo

随机推荐

  • VScode使用pip已经下载了faker,但还是报错ModuleNotFoundError: No module named ‘faker‘

    修复一下pip python m ensurepip pip install faker 但是在安装faker的时候 出现了这样的情况 提示warning 换一种写法 pip install faker i http pypi douban
  • 给定一个介于0和1之间的实数,类型为double,打印它的二进制表示

    给定一个介于0和1之间的实数 0 625 类型为double 打印它的二进制表示 如果该数字无法精准地用32位以内的二进制表示 则打印 ERROR 先上代码 public class printbinary public static vo
  • ABAP DOI 技术

    用户提出的报表 是用EXCLE显示的 有许多特殊格式 比如 加粗 大小字体等 普通的ALV报表输出并不能满足用户的要求 那么只能用ALV与EXCLE的集成技术 目前已知的技术有两种 一种是OLE技术 用SMW0上传模板 然后填写数据 多数用
  • Springboot的pom.xml需要用到的依赖总结:

  • 蜣螂优化(DBO)算法(含MATLAB代码)

    先做一个声明 文章是由我的个人公众号中的推送直接复制粘贴而来 因此对智能优化算法感兴趣的朋友 可关注我的个人公众号 启发式算法讨论 我会不定期在公众号里分享不同的智能优化算法 经典的 或者是近几年提出的新型智能优化算法 并附MATLAB代码
  • python怎么生成词云图

    词云图是什么 词云图又称文字云 是信息可视化的表现形式之一 词云是把文本中出现频率较高的关键词进行视觉上的突出显示 形成关键词云层或关键词渲染 从而过滤掉大量的文本信息 读者可以快速领略文本的主旨 相对柱状图 折线图 饼图等用来显示数据的图
  • log4j2 JNDI注入漏洞问题复现

    最近大家应该都有被log4j2的JNDI注入漏洞搞的心烦意乱 当程序将用户输入的数据进行日志输出时 即可触发此漏洞 成功利用此漏洞可以在目标服务器上执行任意代码 以下为改问题的复现方法 1 首先下载JNDI Injection 起 RMI
  • 在docker里使用jupyterhub

    准备工作 需要先安装docker 具体方法参考我的上一篇文章 1 查看本地镜像docker images D go 练习 go zero demo gt docker images REPOSITORY TAG IMAGE ID CREAT
  • 程序切片知识点整理(程序依赖图、静态切片、动态切片)

    整理了很久很久的一篇文章 觉得有收获的可以点个赞点个关注哇 有问题也可以评论或找我交流 有评论必回复 目录 一 基础知识概念 关于控制流信息有如下几个基本概念 1 基本块 2 控制流图 cfg 3 有向图G 基于数据流分析的一些定义 1 到
  • SPDK/NVMe存储技术分析之SSD设备的发现(一)

    源代码及NVMe协议版本 SPDK spdk 17 07 1 DPDK dpdk 17 08 NVMe Spec 1 2 1 1 识别NVMe固态硬盘的方法 NVMe SSD是一个PCIe设备 那么怎么识别这种类型的设备 有两种方法 方法1
  • 工厂模式(分简单工厂模式、工厂方法模式、抽象工厂模式)

    1 工厂模式概述 1 1 简单工厂模式 简单工厂模式是一种创建型设计模式 它实现了创建对象的功能 但不使用任何具体类的名称 客户端通过调用工厂类的静态方法来创建一个具体的对象 无需关心对象创建的细节 1 2 工厂方法模式 工厂方法模式是一种
  • STM32 的定时器解析

    STM32有3种类型的定时器 分别是基本定时器 通用定时器和高级定时器 基本定时器有TIM6和TIM7 通用定时器有TIM2 TIM3 TIM4和TIM5 高级定时器有TIM1和TIM8 根据芯片的型号不同定时器的个数也会有所区别 本文主要
  • 《第四部分:测试用例--等价类、边界值与用例编写》

    目录 关联实例练习文档 一 认识基本术语 一 术语一 二 术语二 三 术语三 控制流图的概念 四 圈复杂度计算公式 二 用例设计 一 等价类 1 1 等价类介绍 1 2 等价类划分举例 1 3 等价类划分的设计用例思路 1 4 小结 等价类
  • JavaScript复选框的使用

    div p 请选择你的爱好 p div
  • 十行代码搞定目标检测

    大数据文摘出品 编译 邢畅 宁静 计算机视觉是人工智能的一个重要领域 是关于计算机和软件系统的科学 可以对图像和场景进行识别 理解 计算机视觉还包括图像识别 目标检测 图像生成 图像超分辨率重建等多个领域 由于存在大量的实际需求 目标检测可
  • 小技巧(5):将TT100K数据集转成VOC格式,并且用Python脚本选出45类超过100张的图片和XML

    上一篇 小技巧 4 将txt中的某两列数据写入csv文件中 制作图像分类标签 文章目录 一 相关准备 1 1 下载数据集 1 2 下载代码文件 1 3 将相关文件移入代码文件 二 创建标准的VOC文件夹 三 生成整个数据集的XML文件 四
  • leetcode-第247场周赛-5798循环轮转矩阵(模拟题)

    5798 循环轮转矩阵 模拟题 题目链接 https leetcode cn com problems cyclically rotating a grid 题目 给你一个大小为 m x n 的整数矩阵 grid 其中 m 和 n 都是 偶
  • Code=201 “Siri and Dictation are disabled“

    iOS 15 之前的语音识别是使用SpeechKit和AVFoundation两个框架来配合使用 其中主要的类有SFSpeechRecognizer SFSpeechAudioBufferRecognitionRequest SFSpeec
  • SSHLibrary本地远程访问LINUX遇Incompatible ssh peer错误

    FAIL SSHException Incompatible ssh peer no acceptable kex algorithm 使用python写了段脚本 远程访问LINUX主机 同样的一段脚本 访问主机A可以 访问主机B就报标题中
  • QtModbus Serial 简单示例

    来自QQ群 Linux 技术分享 311078264 打开链接加入QQ群 https jq qq com wv 1027 k 5Gr3bAx 此文档由elikang整理 为了文章简单直接 许多细节未能在文章中体现 如有疑问请进群讨论 Qt