当前位置: 首页 > 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…...

从训练到推理全链路断电不丢数据,AI研发团队必须掌握的4类异构备份策略,

第一章&#xff1a;AI原生软件研发容灾备份策略设计 2026奇点智能技术大会(https://ml-summit.org) AI原生软件具备模型权重、训练流水线、推理服务、向量数据库与动态提示工程等多模态状态&#xff0c;其容灾备份不能简单套用传统应用的冷备/热备范式&#xff0c;而需构建语义…...

在Windows 10/11上部署ArcGIS 10.2开发环境:ArcEngine SDK for .NET配置详解

在Windows 10/11上构建ArcGIS 10.2开发环境&#xff1a;从零开始打造GIS应用 当你第一次尝试在Visual Studio中调用ArcEngine的类库时&#xff0c;是否遇到过令人抓狂的"未找到引用"错误&#xff1f;或是明明按照教程一步步操作&#xff0c;却在运行时遭遇神秘的许可…...

nomic-embed-text-v2-moe GPU算力利用:A10单卡并发16路请求的稳定性压测报告

nomic-embed-text-v2-moe GPU算力利用&#xff1a;A10单卡并发16路请求的稳定性压测报告 1. 引言&#xff1a;当嵌入模型遇上高并发挑战 最近在折腾一个多语言检索项目&#xff0c;需要找一个既强大又高效的文本嵌入模型。试了一圈&#xff0c;最终锁定了nomic-embed-text-v2…...

如何通过Winhance中文版实现Windows系统全面优化与个性化定制

如何通过Winhance中文版实现Windows系统全面优化与个性化定制 【免费下载链接】Winhance-zh_CN A Chinese version of Winhance. C# application designed to optimize and customize your Windows experience. 项目地址: https://gitcode.com/gh_mirrors/wi/Winhance-zh_CN …...

higress 这个中登才是AI时代的心头好众

核心摘要&#xff1a;这篇文章能帮你 ?? 1. 彻底搞懂条件分支与循环的适用场景&#xff0c;告别选择困难。 ?? 2. 掌握遍历DOM集合修改属性的标准姿势与性能窍门。 ?? 3. 识别流程控制中的常见“坑”&#xff0c;并学会如何优雅地绕过去。 ?? 主要内容脉络 ?? 一、痛…...

2026奇点大会AI部署白皮书深度解密(Kubernetes+LLM Runtime双栈融合架构首次公开)

第一章&#xff1a;2026奇点智能技术大会&#xff1a;AI原生容器化部署 2026奇点智能技术大会(https://ml-summit.org) AI原生容器化部署已成为大模型服务落地的核心范式。与传统微服务容器化不同&#xff0c;AI原生部署需同时满足GPU资源弹性调度、模型权重分片加载、推理请求…...

收藏!2026开年AI爆火,正在重塑程序员职业命运(小白/程序员必看)

2026开年以来&#xff0c;AI技术的爆发式发展彻底打破了技术圈的平静&#xff0c;这场变革不再是“遥不可及的趋势”&#xff0c;而是实实在在渗透到每一位程序员的日常工作中&#xff0c;悄悄改写着我们的职业轨迹——无论是大厂布局还是行业需求&#xff0c;都在释放一个强烈…...

Go赋值操作的关键细节

一、: 短变量声明的细节1.作用域规则2.重复声明规则3类型推断二、 赋值操作的细节1.类型必须匹配2.多重赋值特性三、 零值初始化细节1.Go为所有类型提供零值四、指针赋值的细节1.基本指针操作理解这段代码的关键在于搞清楚两个概念&#xff1a;普通变量、指针变量&#xff0c;…...

如何快速上手cxmooc-tools:5分钟搞定三大网课平台自动刷课

如何快速上手cxmooc-tools&#xff1a;5分钟搞定三大网课平台自动刷课 【免费下载链接】cxmooc-tools 一个 超星(学习通)/智慧树(知到)/中国大学mooc 学习工具,火狐,谷歌,油猴支持.全自动任务,视频倍速秒过,作业考试题库,验证码自动打码(੧ᐛ੭挂科模式,启动) 项目地址: http…...

C++一维数组完全指南

一、什么是一维数组&#xff1f;用来一次性存储多个相同类型的数据内存中连续存放有统一的名字&#xff0c;用 ** 下标&#xff08;索引&#xff09;** 区分每个元素下标从 0 开始&#xff08;非常重要&#xff09;二、定义与初始化&#xff08;四种常用方式&#xff09;// 1. …...