QModbus例程分析
由于有一个Modebus
上位机的需要,分析一下QModbus Slave
的源代码,方便后面的开发。
什么是Modbus
Modbus是一种常用的串行通信协议,被广泛应用于工业自动化领域。它最初由Modicon(目前属于施耐德电气公司)于1979年开发,旨在实现PLC(可编程逻辑控制器)和外部设备之间的数据交换。以下是对Modbus的详细解析:
一、Modbus协议的特点
- 免费使用:Modbus协议是免费开放的,用户可以自由使用,无需支付任何版权费用。
- 多种电气接口和传输介质:Modbus支持多种电气接口,如RS-232、RS-485等,以及多种传输介质,如双绞线、光纤、无线等,使得数据传输更加灵活。
- 帧格式简单:Modbus的帧格式简单易懂,方便开发人员快速上手和使用。
- 可靠性好:Modbus协议对数据进行了严格的校验,确保数据传输的可靠性。同时,它还支持主从方式定时收发数据,能够及时检测和恢复通信故障。
二、Modbus的传输方式与格式
Modbus协议可以使用串口和网线(含光纤)等方式进行传输,根据常用传输介质,它主要支持以下三种传输模式:
- ASCII模式:将数据以ASCII码形式进行传输,适用于低速率的串行通信。
- RTU模式:使用二进制格式传输数据,相比ASCII模式,在同样的波特率下可以传输更多的数据,适用于中高速率的串行通信。
- TCP/IP模式:利用TCP/IP协议进行网络通信,称为Modbus TCP/IP,适用于需要远程通信的场合。
三、Modbus协议的应用领域
Modbus协议广泛应用于工业自动化领域,包括但不限于以下几个方面:
- 工业自动化控制:连接PLC、传感器、执行器等设备,实现监控和控制功能。
- 智能家居:连接各种传感器和执行器,实现远程控制和监测。
- 能源监控:连接电表、燃气表、水表等设备,实现能源数据的采集和分析。
- 环境监测:连接各种传感器和仪器,监测环境参数如温度、湿度、气压等。
- 智能交通:连接交通控制设备、车辆检测器等,实现交通信号的控制和管理。
四、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);}
}
相关文章:

QModbus例程分析
由于有一个Modebus上位机的需要,分析一下QModbus Slave的源代码,方便后面的开发。 什么是Modbus Modbus是一种常用的串行通信协议,被广泛应用于工业自动化领域。它最初由Modicon(目前属于施耐德电气公司)于1979年开发…...

Vue万字学习笔记(入门1)
目录 简介 Vue是什么 渐进式框架 单文件组件 API 风格 选项式 API (Options API) 组合式 API (Composition API) 创建一个 Vue 应用 挂载应用 DOM 中的根组件模板 应用配置 多个应用实例 模板语法 文本插值 原始 HTML Attribute 绑定 简写…...

Cesium手动建模模型用Cesiumlab转3D Tiles模型位置不对,调整模型位置至指定经纬度
Cesium加载3Dtiles模型的平移和旋转_3dtiles先旋转再平移示例-CSDN博客 Cesium 平移cesiumlab生产的3Dtiles切片模型到目标经纬度-CSDN博客 【ArcGISCityEngine】自行制作Lod1城市大尺度白膜数据_cityengine 生成指定坐标集指定区域的白模-CSDN博客 以上次ArcGISCityEngine制…...

学习C语言第23天(程序环境和预处理)
1. 程序的翻译环境和执行环境 在ANSIC的任何一种实现中,存在两个不同的环境 第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境,它用于实际执行代码。 2. 详解编译链接 2.1 翻译环境 每个源文件单独经过编…...

Ubuntu22.04安装
使用Vmware安装好后 首先执行下面命令,不然每次打开终端会出现To run a command as administrator (user root)… touch ~/.sudo_as_admin_successful换源 参考 sudo cp /etc/apt/sources.list /etc/apt/sources.list.baksudo gedit /etc/apt/sources.list清空…...

从入门到自动化:一篇文章掌握Python的80%
Python作为一种高级编程语言,以其简洁明了的语法和强大的功能性,在全球编程社区内享有极高的声誉。本文将带领你从Python的基础语法入手,介绍其常用库的应用,以及如何将Python用于数据分析、网络爬虫和简单的自动化任务࿰…...
开源的主流机器学习框架
主流的开源机器学习框架包括: 1. TensorFlow:由Google开发和维护的深度学习框架,广泛用于生产环境和研究。支持多种平台,并具有丰富的工具和库支持。 2. PyTorch:由Facebook开发的深度学习框架,以其动态计…...
RabbitMQ:发送者的可靠性之配置发送者重试机制
文章目录 为什么需要重试机制?如何配置重试机制?测试重试机制使用重试机制的注意事项 在使用消息队列(MQ)系统时,网络故障是不可避免的问题,尤其是在与RabbitMQ等服务交互时。如果生产者在发送消息时遇到网…...

基于深度学习的大规模MIMO信道状态信息反馈
MIMO系统 MIMO系统利用多个天线在发送端和接收端之间建立多条独立的信道,从而使得同一时间可以传输多个数据流,从而使得同一之间可以传输多个数据流,提高数据传输速率。 优势 增加传输速率和容量,提高信号覆盖范围和抗干扰能力…...

在Docker中部署Rasa NLU服务
最近因为项目需要将rasa nlu配置到docker容器中供系统调用,本篇主要整理该服务的docker配置过程。 本篇的重点在于docker的使用,不在Rasa NLU。 系统环境:Ubuntu 18.04.6 1. Rasa介绍 Rasa是一个开源的机器学习框架,专为构建基于文…...

SQL语句创建数据库(增删查改)
SQL语句 一.数据库的基础1.1 什么是数据库1.2 基本使用1.2.1 连接服务器1.2.2 使用案例 1.2 SQL分类 二.库的操作2.1 创建数据库2.2 创建数据库示例2.3 字符集和校验规则2.3.1 查看系统默认字符集以及校验规则2.3.2查看数据库支持的字符集2.3.3查看数据库支持的字符集校验规则2…...

微信小程序-Vant组件库的使用
一. 在app.json里面删除style:v2 为了避免使用Vant组件库和微信小程序组件样式的相互影响 二.在app.json里面usingComponents注册Vant组件库的自定义组件 "usingComponents": {"van-icon": "./miniprogram_npm/vant-weapp/icon/index&qu…...

为什么企业需要进行能源体系认证?
通过能源体系认证,企业可以向公众和利益相关方展示其在节能减排方面的承诺和成就。这不仅提升了企业的社会责任形象,还增强了品牌的信誉度。在当今消费者更加关注环境问题的背景下,绿色企业形象有助于赢得市场和客户的认可与信任。 能源体系认…...
【日常记录-MySQL】EVENT
Author:赵志乾 Date:2024-08-07 Declaration:All Right Reserved!!! 1. 简介 在MySQL中,EVENT是一种数据库对象,其用于设定数据库任务自动执行。这些任务可以是任意有效的SQL语句&a…...

嵌入式学习day12(LinuxC高级)
由于C高级部分比较零碎,各部分之间没有联系,所以学起来比较累,多练习就好了 一丶Linux起源 寻科普|第二期:聊聊Linux的前世今生 UNIX和linux的区别: (1)linux是开发源代码的自由软件.而unix是…...
pytorch中的hook机制register_forward_hook
上篇文章主要介绍了hook钩子函数的大致使用流程,本篇文章主要介绍pytorch中的hook机制register_forward_hook,手动在forward之前注册hook,hook在forward执行以后被自动执行。 1、hook背景 Hook被成为钩子机制,pytorch中包含forwa…...
使用Gin框架返回JSON、XML和HTML数据
简介 Gin是一个高性能的Go语言Web框架,它不仅提供了简洁的API,还支持快速的路由和中间件处理。在Web开发中,返回JSON、XML和HTML数据是非常常见的需求。本文将介绍如何使用Gin框架来返回这三种类型的数据。 环境准备 在开始之前࿰…...

网工内推 | 国企运维工程师,华为认证优先,最高年薪20w
01 上海陆家嘴物业管理有限公司 🔷招聘岗位:IT运维工程师 🔷岗位职责: 1、负责对公司软、硬件系统、周边设备、桌面系统、服务器、网络基础环境运行维护、故障排除。 2、负责对各部门软件操作、网络安全进行检查、指导。 3、负责…...
c# 使用异步函数实现线程的功能
c#程序执行时 想要拖动窗口 需要使用线程,但是使用线程 对操作前端窗体很不友好. 所以写了一个异步函数,网上搜了一下,貌似异步函数比线程 更加友好,更加现代 做这个功能的原因是 主要是想等程序执行完 走一个提示.用线程很难做到 using System; using System.Threading; usi…...
MySQL之MySQL server has gone away复现测试
测试MySQL server has gone away复现条件 环境情形一报错信息复现测试 情形二报错信息复现测试 环境 Python: 3.8/3.9 MySQL: 5.x 情形一 报错信息 File "/usr/local/lib/python3.6/dist-packages/MySQLdb/cursors.py", line 319, in _querydb.query(q)File "/…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...