QModbus例程分析

由于有一个Modebus上位机的需要,分析一下QModbus Slave的源代码,方便后面的开发。

什么是Modbus

Modbus是一种常用的串行通信协议,被广泛应用于工业自动化领域。它最初由Modicon(目前属于施耐德电气公司)于1979年开发,旨在实现PLC(可编程逻辑控制器)和外部设备之间的数据交换。以下是对Modbus的详细解析:

一、Modbus协议的特点

  1. 免费使用:Modbus协议是免费开放的,用户可以自由使用,无需支付任何版权费用。
  2. 多种电气接口和传输介质:Modbus支持多种电气接口,如RS-232、RS-485等,以及多种传输介质,如双绞线、光纤、无线等,使得数据传输更加灵活。
  3. 帧格式简单:Modbus的帧格式简单易懂,方便开发人员快速上手和使用。
  4. 可靠性好:Modbus协议对数据进行了严格的校验,确保数据传输的可靠性。同时,它还支持主从方式定时收发数据,能够及时检测和恢复通信故障。

二、Modbus的传输方式与格式

Modbus协议可以使用串口和网线(含光纤)等方式进行传输,根据常用传输介质,它主要支持以下三种传输模式:

  1. ASCII模式:将数据以ASCII码形式进行传输,适用于低速率的串行通信。
  2. RTU模式:使用二进制格式传输数据,相比ASCII模式,在同样的波特率下可以传输更多的数据,适用于中高速率的串行通信。
  3. TCP/IP模式:利用TCP/IP协议进行网络通信,称为Modbus TCP/IP,适用于需要远程通信的场合。

三、Modbus协议的应用领域

Modbus协议广泛应用于工业自动化领域,包括但不限于以下几个方面:

  1. 工业自动化控制:连接PLC、传感器、执行器等设备,实现监控和控制功能。
  2. 智能家居:连接各种传感器和执行器,实现远程控制和监测。
  3. 能源监控:连接电表、燃气表、水表等设备,实现能源数据的采集和分析。
  4. 环境监测:连接各种传感器和仪器,监测环境参数如温度、湿度、气压等。
  5. 智能交通:连接交通控制设备、车辆检测器等,实现交通信号的控制和管理。

四、Modbus协议的工作原理

Modbus协议是一种使用主从关系实现的请求-响应协议。在主从关系中,通信总是成对发生——一个设备(主设备)发起请求,然后等待另一个设备(从设备)的响应。主站通常是人机界面(HMI)或监控和数据采集(SCADA)系统,从站则是传感器、PLC或可编程自动化控制器(PAC)等。

Modbus协议定义了一系列功能码,用于指定设备执行不同的操作。例如,读取线圈状态(Read Coil Status)功能码用于读取设备中的开关量输出状态;写单个寄存器(Write Single Register)功能码用于写入设备中的单个寄存器数据。在进行数据交换时,主设备会向从设备发送包含功能码和地址等信息的请求帧,从设备则根据请求帧中的信息执行相应的操作,并将结果以响应帧的形式返回给主设备。

五、总结

Modbus协议以其简单性、可靠性和广泛的兼容性,成为了工业自动化领域中最流行的通信协议之一。它支持多种电气接口和传输介质,适用于各种设备和系统之间的数据交换。同时,Modbus协议还具有良好的可扩展性和灵活性,能够满足不同应用场景的需求。

SettingDialog

SettingDialog中,是串口的参数配置,从上到下依次是:校验,波特率,数据位,停止位。

源代码

  • 头文件
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H#include <QtSerialBus/qtserialbusglobal.h>
#include <QDialog>
#if QT_CONFIG(modbus_serialport)
#include <QSerialPort>
#endifQT_BEGIN_NAMESPACEnamespace Ui {
class SettingsDialog;
}QT_END_NAMESPACEclass SettingsDialog : public QDialog
{Q_OBJECTpublic:// 串口配置数据结构struct Settings {
#if QT_CONFIG(modbus_serialport)int parity = QSerialPort::EvenParity; // 校验位初始化为偶校验int baud = QSerialPort::Baud19200; // 波特率初始化为19200int dataBits = QSerialPort::Data8; // 数据位初始化为8位int stopBits = QSerialPort::OneStop; // 停止位初始化为1位
#endif};explicit SettingsDialog(QWidget *parent = nullptr);~SettingsDialog();Settings settings() const;private:Settings m_settings;Ui::SettingsDialog *ui;
};#endif // SETTINGSDIALOG_H
  • 源文件
#include "settingsdialog.h"
#include "ui_settingsdialog.h"SettingsDialog::SettingsDialog(QWidget *parent) :QDialog(parent),ui(new Ui::SettingsDialog)
{ui->setupUi(this);ui->parityCombo->setCurrentIndex(1);
#if QT_CONFIG(modbus_serialport)// 从下拉框获取配置ui->baudCombo->setCurrentText(QString::number(m_settings.baud));ui->dataBitsCombo->setCurrentText(QString::number(m_settings.dataBits));ui->stopBitsCombo->setCurrentText(QString::number(m_settings.stopBits));
#endif/*信号和槽绑定,按下确认时修改默认参数,然后隐藏窗口。*/connect(ui->applyButton, &QPushButton::clicked, [this]() {
#if QT_CONFIG(modbus_serialport)m_settings.parity = ui->parityCombo->currentIndex();if (m_settings.parity > 0)m_settings.parity++;m_settings.baud = ui->baudCombo->currentText().toInt();m_settings.dataBits = ui->dataBitsCombo->currentText().toInt();m_settings.stopBits = ui->stopBitsCombo->currentText().toInt();
#endifhide();});
}SettingsDialog::~SettingsDialog()
{delete ui;
}// 获取配置结果
SettingsDialog::Settings SettingsDialog::settings() const
{return m_settings;
}

MainWindow

void MainWindow::initActions()
{ui->actionConnect->setEnabled(true);ui->actionDisconnect->setEnabled(false);ui->actionExit->setEnabled(true);ui->actionOptions->setEnabled(true);connect(ui->connectButton, &QPushButton::clicked,this, &MainWindow::onConnectButtonClicked);connect(ui->actionConnect, &QAction::triggered,this, &MainWindow::onConnectButtonClicked);connect(ui->actionDisconnect, &QAction::triggered,this, &MainWindow::onConnectButtonClicked);connect(ui->connectType, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::onCurrentConnectTypeChanged);connect(ui->actionExit, &QAction::triggered, this, &QMainWindow::close);connect(ui->actionOptions, &QAction::triggered, m_settingsDialog, &QDialog::show);
}

连接函数

void MainWindow::onConnectButtonClicked()
{// 判断是否连接bool intendToConnect = (modbusDevice->state() == QModbusDevice::UnconnectedState);statusBar()->clearMessage();if (intendToConnect) {// 确定连接方式 设置串口连接参数if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,ui->portEdit->text());
#if QT_CONFIG(modbus_serialport)modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,m_settingsDialog->settings().parity);modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,m_settingsDialog->settings().baud);modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,m_settingsDialog->settings().dataBits);modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,m_settingsDialog->settings().stopBits);
#endif} else {// 设置网络连接参数const QUrl url = QUrl::fromUserInput(ui->portEdit->text());modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());}modbusDevice->setServerAddress(ui->serverEdit->text().toInt());if (!modbusDevice->connectDevice()) {statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);} else {ui->actionConnect->setEnabled(false);ui->actionDisconnect->setEnabled(true);}} else {// 如果已经连接则断开modbusDevice->disconnectDevice();ui->actionConnect->setEnabled(true);ui->actionDisconnect->setEnabled(false);}
}

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

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

相关文章

C++:vector容器

概览 std::vector是C标准模板库(STL)中的一种动态数组容器。它提供了一种类似于数组的数据结构&#xff0c;但是具有动态大小和更安全的内存管理。 定义和基本特性 std::vector是C标准库中的一 个序列容器&#xff0c;它代表了能够动态改变大小的数组。与普通数组一样&#x…

模拟面试题1

目录 一、JVM的内存结构&#xff1f; 二、类加载器分为哪几类&#xff1f; 三、讲一下双亲委派机制 为什么要有双亲委派机制&#xff1f; 那你知道有违反双亲委派的例子吗&#xff1f; 四、IO 有哪些类型&#xff1f; 五、Spring Boot启动机制 六、Spring Boot的可执行…

关于儿童编程语言

青少年通常会通过Scratch或Python开始学习编程。在这两种语言中&#xff0c;代码的编写&#xff08;或者在Scratch中是构建&#xff09;方式类似于英语&#xff0c;这使得初学者更容易学习。Scratch的一个重要卖点是对视觉和运动感知学习者非常友好。这些代码块按颜色编码&…

最短路问题中的bellman-ford算法

最短路问题中的bellman-ford算法 题目 如果要处理单源最短路问题当中存在负权边的&#xff0c;那么就需要用到 bellman-ford算法和SPFA算法&#xff0c;一般情况下都是用 SPFA算法&#xff0c;除了有边数限制的情况只能用bellman-ford算法&#xff0c;比如下面这种 题目 给定…

混合密度网络Mixture Density Networks(MDN)

目录 简介1 介绍2 实现3 几个MDN的应用&#xff1a;参考 简介 平方和或交叉熵误差函数的最小化导致网络输出近似目标数据的条件平均值&#xff0c;以输入向量为条件。对于分类问题&#xff0c;只要选择合适的目标编码方案&#xff0c;这些平均值表示类隶属度的后验概率&#x…

《程序猿入职必会(10) · SpringBoot3 整合 MyBatis-Plus》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

Linux中DHCP服务器配置和管理

文章目录 一、DHCP服务1.1、DHCP的工作流程1.2、DHCP的工作模式1.3、dhcp的主要配置文件 二、安装DHCP服务2.1、更新yum源2.2、安装DHCP服务软件包2.3、配置DHCP服务2.4、启用DHCP服务&#xff08;解决报错&#xff09;2.4.1、查看dhcpd服务的状态和最近的日志条目2.4.2、查看与…

【网络安全】探索AI 聊天机器人工作流程实现RCE

未经许可,不得转载。 文章目录 前言正文前言 我发现了一个广泛使用的AI聊天机器人平台中的远程代码执行漏洞。该漏洞存在于聊天机器人的自定义工作流响应代码中,这些工作流允许开发人员通过创建定制的流程来扩展机器人的功能。 正文 在浏览自动化聊天机器人的多个特定功能…

AI界的“小钢炮“:MiniCPM-V 2.6 版本震撼发布!

MiniCPM-V 2.6 面壁智能推出了一款颠覆性的端侧AI多模态模型——MiniCPM-V 2.6。这个被亲切地称为"小钢炮"的模型&#xff0c;以其惊人的性能和极致的效率&#xff0c;向业界巨头发起了挑战。 MiniCPM-V 2.6 MiniCPM-V 2.6 是 MiniCPM-V 系列中最新、性能最佳的模型。…

算法板子:匈牙利算法——二分图的最大匹配

目录 1. 基础概念 &#xff08;1&#xff09;二分图的概念 &#xff08;2&#xff09; 匈牙利算法的作用 2. 代码 1. 基础概念 &#xff08;1&#xff09;二分图的概念 顶点集 V 分为两个集合&#xff0c;且图中每条边依附的两个顶点都分属于这两个子集&#xff0c;也就是第…

《UniverSeg: Universal Medical Image Segmentation》ICCV2023

摘要 这篇论文提出了一种名为 UniverSeg 的方法&#xff0c;它能够解决未见过的医学图像分割任务&#xff0c;而无需额外的训练。现有的深度学习模型通常无法泛化到新的解剖结构、图像模式或标签上。UniverSeg 利用一种新的 CrossBlock 机制&#xff0c;通过查询图像和定义新分…

倍福PLC数据 转 CCLink IE Field Basic项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 设置倍福PLC 2 5 配置网关参数采集倍福PLC数据 4 6 使用CCLINK协议转发数据 7 7 三菱PLC连接网关的CCLINK的设置 8 8 案例总结 12 1 案例说明 设置倍福PLC&#xff0c;开通ADS通信设置网关采集倍福PLC数据把采集的数…

小巧免费的笔记本电池检测工具

BatteryInfoView是一款免费的笔记本电池检测软件&#xff0c;适用于笔记本电脑和上网本。该软件能够提供电池的详细信息&#xff0c;包括电池名称、制造商名称、序列号、制造日期、电源状态&#xff08;充电/放电&#xff09;、当前电池容量、完全充电容量、设计容量、充电放电…

RAG私域问答场景超级详细方案(第一期方案)[1]:工业级别构建私域问答(知识处理、知识召回排序、搜索问答模块)

RAG私域问答场景整体夏详细方案(第一期方案):工业级别构建私域问答(知识处理、知识召回排序、搜索问答模块) 大模型性能的跳阶式增长给文本摘要、信息检索、信息抽取、语义问答等自然语言处理任务带来了卓越的性能提升。同时,LangChain 作为一种基于 LLM 的框架,能够快速…

基础岛 - 8G显存验证书生·浦语大模型的Demo

因为以前用过LMDeploy&#xff0c;所以本章的内容相对熟悉。 另外&#xff0c;因为教程写的很详细保姆级&#xff0c;所以大多数情况直接复制执行命令即可。开发机的创建略过。 总体验证结论&#xff1a; LMDeploy的模型加载有点慢&#xff0c;但推理速度快&#xff0c;符合预…

第三方软件检测机构服务类型

在信息技术飞速发展的今天&#xff0c;软件产品的质量已成为企业竞争力的重要组成部分。卓码软件测评这家第三方软件检测机构致力于提供一流的软件测试服务&#xff0c;帮助企业确保其软件产品的可靠性和安全性。 一、项目验收测试&#xff1a;确保交付质量   项目验收测试是…

【Nuxt】配置

runtimeConfig 运行时配置 // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({compatibilityDate: 2024-04-03,devtools: {enabled: true},runtimeConfig: {appKey: process.env.APP_KEY,public: {baseUrl: process.env.BASE_URL,}} …

suse SLE 12 SP3 安装 GeForce GT 730 显卡驱动

文章目录 [toc]获取驱动安装显卡驱动验证显卡驱动 获取驱动 浏览器打开 NVIDIA Official Drivers &#xff0c;找到自己对应的驱动&#xff0c;然后查询和下载 安装显卡驱动 下载完成后&#xff0c;有一个 .run 文件&#xff0c;可以直接 bash 执行&#xff0c; bash NVIDIA-Li…

Java每日一题———删除有序数组中的重复项

这个问题可以通过使用双指针技术来解决。我们可以使用两个指针&#xff0c;一个慢指针 slowRunner 用于跟踪新数组的末尾&#xff0c;另一个快指针 fastRunner 用于遍历数组。每当 fastRunner 遇到一个新的唯一元素时&#xff0c;就将其复制到 slowRunner 指向的位置&#xff0…

力扣——11.盛最多水的容器

题目 暴力解 思路&#xff1a; 遍历每一个可能组成的容器&#xff0c;然后计算比较最大值。 代码&#xff1a; int maxArea(vector<int>& height) {int z1 0, z2 0;int len height.size();int val 0;for (z1; z1 < len - 1; z1) {for (z2 z1 1; z2 < l…