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 简单示例 的相关文章

  • 在 4K 屏幕上使用 Matplotlib 和 TKAgg 或 Qt5Agg 后端

    我在 Ubuntu 16 04 上使用 Matplotlib 2 0 和 Python 3 6 来创建数据图 电脑显示器的分辨率为 4k 分辨率为 3840x2160 绘图数字看起来非常小 字体也很小 我已经尝试过TKAgg and Qt5
  • 另一个宏中的 Q_PROPERTY 宏

    如何放置Q PROPERTY另一个宏里面 辅助宏 define SimpleAllinOne member type public void Set member type arg member m member arg member ty
  • 第一个随机数始终小于其余随机数

    我碰巧注意到 在 C 中 使用 std rand 方法调用的第一个随机数大多数时候都明显小于第二个随机数 关于 Qt 实现 第一个几乎总是小几个数量级 qsrand QTime currentTime msec qDebug lt lt q
  • 如何将 QByteArray 转换为十六进制字符串?

    我有打击QByteArray QByteArray ba ba 0 0x01 ba 1 0x10 ba 2 0x00 ba 3 0x07 我真的不知道如何将此 QByteArray 转换为结果字符串 其中包含 01100007 我将使用 Q
  • 加载 QPixmap 数据的更好方法

    更好的方法来做到这一点 没有QImage QImage image width height QImage Format RGB888 memcpy image bits m frameRGB gt data 0 height width
  • 获取 QPushButton 在 2D 数组 QPushButton 上的索引

    我有一个二维数组QPushButton 当用户单击按钮时如何获取按钮的索引 例如当用户单击按钮时a 2 3 它会显示 2 3 该示例如下所示 Qt 4 5 使用对象名称 您可以为按钮指定唯一的对象名称 理想情况下 名称应该是有效的 C 标识
  • 如何从浮点数组创建新的 QImage

    我有一个代表图像的浮点数数组 列在前 我想在 QGraphicsSecene 上将图像显示为 QPixmap 为了做到这一点 我尝试使用 QImage 构造函数 QImage const uchar data int width int h
  • PyQt - 如何从给定的小部件获取顶级父级?

    给定的小部件如何访问它最旧的父级 即顶级小部件 我需要 showMinimized it 现在我正在使用 self parent parent parent showMinimized 但这似乎不是最好的方法 如果它移动了 我需要手动更改父
  • 无法将 QList 分配给 QString

    我遇到这个错误 Unable to assign QList
  • 用 C++/Qt 编写的程序中的 RTF / doc / docx 文本提取

    我正在写一些程序Qt https en wikipedia org wiki Qt 28software 29 C 我需要从中读取文本微软Word https en wikipedia org wiki Microsoft Word RTF
  • 第一次信号发射后自动断开

    我正在从文件加载网页 然后替换其中的一些 html self template web page QtWebKit QWebPage self template web page mainFrame load QtCore QUrl tem
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • QMainWindow 上的 Qt 布局

    我设计了一个QMainWindow with QtCreator s设计师 它由默认的中央小部件 aQWidget 其中包含一个QVBoxLayout以及其中的所有其他小部件 现在我想要的一切就是QVBoxLayout自动占据整个中央小部件
  • QTableView 并双击一个单元格

    我正在开发测试用例编辑器 该编辑器包含 USART 传输和接收数据包格式 编辑器是一个表格视图 发送和接收数据包的长度为八个字节 例如 0x01 0x02 0x03 0x08 它在我的第五和第六栏中 现在 我希望此列中的单元格为只读 但是当
  • 如何doxygen注释Qt属性?

    我想将 Doxygen 注释附加到我的 Q PROPERTY 例如 song h class Song public QObject Q OBJECT private Q PROPERTY QString title READ title
  • 如何在 Qt 应用程序中嵌入 Python 解释器?

    有没有一种简单的方法可以将 Python 解释器嵌入到 Qt 应用程序中 如果可能的话 我希望有一个跨平台的解决方案 这就是目的PythonQt http pythonqt sourceforge net 它支持 Windows Linux
  • 针对初学者的 QT 商业许可证与非商业许可证 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 QT 许可似乎非常反学习 因为据我所知 用它开发的任何东西都只能是商业的当且仅当 its entire开发是在使用商业许可证的情况下完成的
  • 如何将自定义 Qt 类型与 QML 信号一起使用?

    我在 Qt 5 2 qml 应用程序中创建了一个自定义类型 class Setting public QObject Q OBJECT Q PROPERTY QString key READ key WRITE setKey Q PROPE
  • 如何在Android中使用QML - QWebView

    我想在 Android 中部署一个 YouTube 应用程序 但它只能在我的电脑上运行 在安卓上不起作用 它不加载任何视频 问题仅出在 QWebView 上 我使用了与此类似的代码 http doc qt io archives qt 5
  • PyQt4 信号和槽

    我正在使用 PyQt4 编写我的第一个 Python 应用程序 我有一个 MainWindow 和一个 Dialog 类 它是 MainWindow 类的一部分 self loginDialog LoginDialog 我使用插槽和信号 这

随机推荐

  • 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