当前位置: 首页 > news >正文

Modbus RTU协议及modbus库函数使用

一、与Modbus TCP的区别

在一般工业场景使用modbus RTU的场景还是更多一些,modbus RTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。

与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在TCP协议中不需要使用CRC校验码。

RTU和TCP的总体使用方法基本一致,只是在创建modbus对象时有所不同,TCP需要传入网络socket信息;而RTU需要传入串口相关信息。

二、Modbus RTU特点

Modbus RTU也是主从问答协议,由主机发起,一问一答

Modbus RTU通过串口进行通信

设置串口参数:

设置串口参数时要求:

波特率为9600

8位数据位

1位停止位

无流控

三、Modbus RTU协议格式

ModbusRTU数据帧包含:地址码 功能码 数据 校验码

地址码:一个字节 从机ID

功能码:一个字节 同TCP(八种)

数据:起始地址 数量  数据

校验码:2个字节,对 地址码+功能码+数据进行校验,可以通过函数自动生成。

四、报文详解

03功能码为例

主机---》从机:

01 03 00 00 00 01 84 0a

01:地址码

03:功能码

00 00 :起始地址

00 01:读的数量

84 0a :校验码

从机--》主机:

01 03 02 00 14 b8 44

01:地址码

03:功能码

02:字节计数(只计算数据的个数)

00 14:数据

b8 44:校验码 

参考示例:

值得收藏 Modbus RTU 协议详解-CSDN博客

五、模拟器的使用

由于实际硬件产品成本较高,我们这里可以使用Modbus软件模拟器,进行数据模拟从而分析Modbus协议。

使用工具:

1. ModbusPoll(模拟主机)和ModbusSlave(模拟从机)

2. vspd虚拟串口

3. UartAssist串口调试工具

设置串口参数要求:波特率为9600   8位数据位  1位停止位 无流控  无校验

虚拟串口的使用:

  • 虚拟串口的安装
  1. 将压缩包解压后,双击vspd.exe文件进行安装

2.安装完成后,找到安装目录,将Cracked下的文件复制到软件安装目录

  1. 打开软件,添加COM1COM2端口(用完之后记得删除端口)

4.添加完端口后,打开设备管理器,这里出现如下图所示即可。

二、虚拟机绑定端口

  1.  将虚拟机在系统关机(必须是关机状态,挂起不行)状态下,点击虚拟机->设置->硬件->添加串行端口,添加COM1
  2. 添加完成后,第一次使用需要将电脑重启
  3. 重启之后,打开虚拟机,点击虚拟机->可移动设备->串行端口->连接
  4. 当连接上虚拟串口后,在终端输入dmesg | grep tty,可以查看到对应的设备文件,其中默认的会有ttyS0文件,剩下的就是虚拟串口对应的设备文件
  • 测试通信

1.Windows打开串口调试工具,选择好串口COM2->COM1,设置对应的波特率

2. 在虚拟机运行minicom

在虚拟机安装minicom软件

sudo apt-get install minicom

在终端执行sudo minicom -s

1)选择serial port setup,回车

2)设置设备文件,波特率,关闭流控,按如下图设置(文件改成自己的

dmesg | grep tty 查看文件名

3)修改完成后,回车,保存修改,选择save setup as dfl,敲回车,再次选择exit回车

4)退出后就可以和windows下的串口调试工具进行通信测试

5)也可以在这个界面输入字符,查看串口助手的显示情况。

6)退出:ctrl+AZ,在弹出的界面里输入X,即可退出。

四、将Modbus Slave模拟器作为RTU设备的从机

虚拟机绑定COM1端口,slave连接COM2端口,虚拟机通过编程测试串口通信

Modbus Slave端的配置如下:

五、可能会遇到的问题

1. 虚拟串口完成主机与vmware下虚拟机进行串口通信

虚拟串口完成主机与vmware下虚拟机进行串口通信_xcom2v2.0怎么用-CSDN博客

2. VSPD虚拟串口工具——从此告别硬件串口调试

『实用教程』VSPD虚拟串口工具——从此告别硬件串口调试_虚拟串口vspd-CSDN博客

3. vmware虚拟机检测不到vspd虚拟串口问题

vmware虚拟机检测不到vspd虚拟串口问题_vmware虚拟机 串口 vspd-CSDN博客

练习:代码完成通过串口读取slave端

串口初始化与校验码获取函数一起编译,管理员身份执行命令,

六、Modbus库

  1. 安装库
    1. 安装配置

1. 在linux中解压压缩包

tar -xvf libmodbus-3.1.7.tar.gz

2. 进入源码目录,创建文件夹(存放头文件、库文件)

cd libmodbus-3.1.7

mkdir install 

3. 执行脚本configure,进行安装配置(指定安装目录)

./configure --prefix=$PWD/install

4. 执行make和make install

make//编译

make install//安装

执行完成后会在install文件夹下生产对应的头文件、库文件件夹install,用于存放产生的头文件、库文件等

    1. 库的使用

要想编译方便,可以将头文件和库文件放到系统路径下

sudo  cp install/include/modbus/*.h  /usr/include 

sudo  cp install/lib/*  -r /lib -d

后期编译时,可以直接gcc xx.c -lmodbus

头文件默认搜索路径:/usr/include  、/usr/local/include

库文件默认搜索路径:/lib、/usr/lib

  1. 函数接口
  1. 以TCP方式创建Modbus实例,并初始化

modbus_t*   modbus_new_tcp(const char *ip, int port)
功能:以TCP方式创建Modbus实例,并初始化
参数:
    ip   :ip地址
    port:端口号
返回值:成功:Modbus实例
      失败:NULL

  1. 设置从机ID

int modbus_set_slave(modbus_t *ctx, int slave)
功能:设置从机ID
参数:
    ctx   :Modbus实例
    slave:从机ID
返回值:成功:0
       失败:-1

  1. 和从机(slave)建立连接

一个modbus实例只能链接一个从机:根据提供的引用内容,一个modbus实例只能连接一个从机ID。因为modbus通信协议是基于主从模式的,每个从机都有一个唯一的从机地址,主机通过从机地址来访问不同的从机。因此,一个modbus实例只能连接一个从机ID,如果需要连接多个从机,需要创建多个modbus实例。

int   modbus_connect(modbus_t *ctx)
功能:和从机(slave)建立连接
参数:
    ctx:Modbus实例
返回值:成功:0
       失败:-1

  1. 释放Modbus实例

void   modbus_free(modbus_t *ctx)
功能:释放Modbus实例
参数:ctx:Modbus实例

  1. 关闭套接字

void   modbus_close(modbus_t *ctx)
功能:关闭套接字
参数:ctx:Modbus实例

  1. 读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01)

int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的状态值

7)读取输入状态,可读取多个连续输入的状态(对应功能码为0x02

int  modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb   :寄存器个数
    dest :得到的状态值
返回值:成功:返回nb的值

  1. 读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03

int  modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
       失败:-1

  1. 读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04

int   modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
       失败:-1

  1. 写入单个线圈的状态(对应功能码为0x05

int  modbus_write_bit(modbus_t *ctx, int addr, int status);
功能:写入单个线圈的状态(对应功能码为0x05)
参数:
    ctx     :Modbus实例
    addr  :线圈地址
    status:线圈状态
返回值:成功:0
      失败:-1

  1. 写入多个连续线圈的状态(对应功能码为15

int  modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
功能:写入多个连续线圈的状态(对应功能码为15)
参数:
    ctx     :Modbus实例
    addr  :线圈地址
    nb     :线圈个数
    src    :多个线圈状态
返回值:成功:0
      失败:-1

  1. 写入单个寄存器(对应功能码为0x06

int  modbus_write_register(modbus_t *ctx, int addr, int value);
功能:  写入单个寄存器(对应功能码为0x06)
参数: 
    ctx    :Modbus实例
    addr  :寄存器地址
    value :寄存器的值 
返回值:成功:0
       失败:-1

12)写入多个连续寄存器(对应功能码为16

int  modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
功能:写入多个连续寄存器(对应功能码为16
参数:
    ctx    :Modbus实例
    addr  :寄存器地址
    nb     :寄存器的个数
    src    :多个寄存器的值 
返回值:成功:0
      失败:-1

  1. 编程流程
  1. 创建实例 modbus_new_tcp
  2. 设置从机id modbus_set_slave
  3. 建立连接 modbus_connect
  4. 寄存器操作
  5. 关闭套接字 modbus_close
  6. 释放实例 modbus_free
  1. 练习

通过库函数实现03功能码采集数据

注意:编译不要忘了链接库、查看网络是否能用,查看slave端协议是否正确,查看slave端是否有对应的寄存器类型,查看slave id是否一致

gcc modbus.c -lmodbus

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <modbus.h>
int main(int argc, char const *argv[])
{
    int ret;
    uint16_t buf[32];
    // 1.创建实例 modbus_new_tcp,端口号字符型转整型
    modbus_t* md = modbus_new_tcp(argv[1],atoi(argv[2]));
    // 2.设置从机id modbus_set_slave
    ret = modbus_set_slave(md, 1);
    if (ret < 0)
    {
        printf("set err\n");
    }
    // 3.建立连接 modbus_connect
    ret = modbus_connect(md);
    if (ret < 0)
    {
        printf("connect err.\n");
    }
    // 4.寄存器操作
    //从0开始读十个寄存器值
    ret = modbus_read_registers(md, 0, 10, buf);
    for (int i = 0; i < 10; i++)
    {
        printf("%#x ", buf[i]);
    }
    // 5.关闭套接字 modbus_close,先关闭套接字,再释放实例
    modbus_close(md);   
    // 6.释放实例 modbus_free
    modbus_free(md);
    return 0;
}

1.任务:编程实现采集传感器数据和控制硬件设备(传感器和硬件通过slave模拟)

传感器:2个,光线传感器、加速度传感器(x\y\z)

硬件设备:2个,led灯、蜂鸣器

要求:

1.多任务编程:多线程

2.循环1s采集一次数据,并将数据打印至终端

3.同时从终端输入指令控制硬件设备

0  1 :led灯打开

0  0:led灯关闭

1  1:蜂鸣器开

1 0 :  蜂鸣器关

相关文章:

Modbus RTU协议及modbus库函数使用

一、与Modbus TCP的区别 在一般工业场景使用modbus RTU的场景还是更多一些&#xff0c;modbus RTU基于串行协议进行收发数据&#xff0c;包括RS232/485等工业总线协议。 与modbus TCP不同的是RTU没有报文头MBAP字段&#xff0c;但是在尾部增加了两个CRC检验字节&#xff08;CRC…...

Linuxfork,写时拷贝

1.prinf隐藏的缓冲区 1.思考:为什么会有缓冲区的存在? 2.演示及思考? 1).演示缓存区没有存在感 那为什么我们感觉不到缓冲区的存在呢?我们要打印东西直接就打印了呢? 我们用代码演示一下: 比如打开一个main.c,输入内容如下: #include <stdio.h> int main() { …...

Android控件全解手册 - 自定义实现水波进度

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列...

Halcon Solution Guide I basics(4.1): Blob Analysis 自主练习

文章目录 文章专栏前言自主练习题目输出电路板焊点个数解决方案:正确率&#xff1a;90 文章专栏 我的Halcon开发 CSDN 专栏 Halcon学习 练习项目gitee仓库 CSDN Major 博主Halcon文章推荐 随笔分类 - Halcon入门学习教程 前言 为了更加熟练的掌握Halcon的练习&#xff0c;我之…...

视频网站适合租用服务器吗?

视频网站适合租用服务器吗&#xff1f; 谈到服务器租用&#xff0c;在服务器租用市场中&#xff0c;通常比较常见的用户群体有电商、外贸和视频等网站。在这里相信很多用户都有疑问&#xff1a;租用的服务器适不适合用来建立视频网站呢&#xff1f;接下来我们一起来看看吧~ 首…...

2024年度投资策略:AI大模型和半导体国产化加速

今天分享的是AI系列深度研究报告&#xff1a;《2024年度投资策略&#xff1a;AI大模型和半导体国产化加速》。 &#xff08;报告出品方&#xff1a;东方证券&#xff09; 报告共计&#xff1a;48页 前言: 行情回顾与未来展望 电子板块涨幅转正&#xff0c;信心逐渐回归。截至…...

【Amazon】创建Amazon EFS 文件系统并将其挂载到Amazon EC2实例

文章目录 1. Amazon EFS文件系统2. Amazon EFS文件系统工作原理图3. 创建Amazon EFS 文件系统操作步骤3.1 创建安全组3.2 创建 EFS 文件系统3.3 启动 EC2 实例并挂载文件系统 4.清理资源4.1 终止 EC2 实例4.2 删除 EFS 文件系统 5.参考链接 1. Amazon EFS文件系统 Amazon EFS …...

微机原理_5

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 8086微处理器CLK引脚输入时钟信号是由(提供。 A. 8284 B. 8288 C.8287 D. 8289 2.下面4个寄存器中,不能作为间接寻址的寄存器是(…...

我的128天创作纪念日

嘿&#xff0c;大家好&#xff01;今天我想和大家聊一聊CSDN创作者128天纪念日的话题。 机缘 首先&#xff0c;让我们来谈谈机缘。作为CSDN创作者&#xff0c;我们都有自己的创作机缘。可能是因为对某个领域感兴趣&#xff0c;可能是因为想要分享自己的知识和经验&#xff0c…...

【高可用架构】Haproxy 和 Keepalived 的区别

Haproxy 和 Keepalived 的区别 1.负载均衡器介绍2.Haproxy 和 Keepalived 的基本概念和特点2.1 Haproxy2.2 Keepalived 3.Haproxy 和 Keepalived 的区别3.1 功能上的区别3.2 架构上的区别3.3 配置上的区别 4.总结 1.负载均衡器介绍 负载均衡器是一种解决高并发和高可用的常用的…...

python-opencv 人脸68点特征点检测

python-opencv 人脸68点特征点检测 不是很难&#xff0c;主要还是掉包&#xff0c;来看一下代码啊&#xff1a; # coding: utf-8 # 导包 import numpy as np import dlib import cv2class face_emotion(object):def __init__(self):# 人脸检测器对象&#xff0c;通过它拿到人…...

无线网络下VMWare+CentOS7使用桥接模式无法联通网络问题

因为最近新配了台带无线网卡的主机&#xff0c;所以准备把所有的内容都转移到新电脑上&#xff0c;其中就包括虚拟机 安装好VMWareCentOS7选择桥接模式 然后我们去修改一下网络配置 cd /etc/sysconfig/network-scripts/进入这个ifcfg-ens33文件 我们修改箭头所示内容&#xff…...

vue2.x中使用JS与路由守卫配置、vue2.x中使用TS与路由守卫的配置和vuex的配置以及TS在vue2.x中的使用说明

vue2.x 事件修饰符 <button click.stop.self"handleDelete(item)"></button>在使用 $confirm 时&#xff0c;使用 await 方式时&#xff0c;需要添加 catch 回调&#xff0c;否则无法获取 $confirm 关闭和取消时的标识值&#xff0c;并且后续代码停止执…...

C语言第三十二弹---打印整数二进制的奇数位和偶数位

使用C语言打印整数二进制的奇数位和偶数位。 思路&#xff1a;分别实现奇数位和偶数位&#xff0c;那么二进制只有0 和 1 那么如何判断一个数的二进制位是0还是1呢?那我们就可以使用位操作符&与1比较&#xff0c;都是1证明该二进制位是1&#xff0c;为0证明该二进制位是0…...

车载电子电器架构 ——电子电气架构设计方案概述

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 注:本文1万多字,认证码字,认真看!!! 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证…...

《C++PrimePlus》第10章 对象和类

10.1 过程性编程和面向对象编程 10.2 抽象和类 10.3 类的构造函数和析构函数 类的定义和使用&#xff08;买卖股票&#xff09; 头文件stock10.h #ifndef __STOCK00__H__ #define __STOCK00__H__#include <string>class Stock { // pravate的内容只能通过public访问 p…...

实现极坐标图表QPolarChart的角度轴范围是[0,360]时,0度在水平右侧

目录 参考角度轴范围是[0,360]时&#xff0c;0度在水平右侧.h.cpp 参考 Qt数据可视化(QPolarChart雷达图) 默认QPolarChart的范围是[0,360]时&#xff0c;0度在垂直上方 如官方例子QValueAxis角度轴范围是[-100,100] 角度轴范围是[0,360]时&#xff0c;0度在水平右侧 原理&am…...

讲述 什么是鸿蒙 为什么需要鸿蒙 为什么要学习鸿蒙

首先 我们为什么要学习鸿蒙开发&#xff1f; 因为 鸿蒙发展前景巨大 鸿蒙自发布依赖 一直受社会各界关注 强两百的 App厂商 大部分接受了与鸿蒙的合作 硬件也有非常多与鸿蒙合作的厂商 鸿蒙的合作企业基本已经覆盖整个互联网客户的主流需求 所以鸿蒙的崛起不过是早晚的问题 …...

【深度学习笔记】05 线性回归

线性回归 线性回归基于几个简单的假设&#xff1a; 首先&#xff0c;假设自变量 x \mathbf{x} x和因变量 y y y之间的关系是线性的&#xff0c; 即 y y y可以表示为 x \mathbf{x} x中元素的加权和&#xff0c;这里通常允许包含观测值的一些噪声&#xff1b; 其次&#xff0c;我…...

二叉树算法—后继节点

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 1 后继节点1.1 解题思路1.2 代码实现 &#x1f48e;总结 1 后继节点 1.1 解题思路 二叉树节点结构定义如下&#xff1a; public static class Node { public int cal; public Node left; public Node right; public…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...