modbus的使用说明——个人使用心得
1.需求说明
在公司开发的项目中,为了实现云端modbus采集,在其中所学习到的关于mudbus不同数据位及不同寄存器读取的使用心得。
2.Modbus中的寄存器与数据位
Modbus的存储方式:
大端存储:
大端存储简单说就是一个int x = 0x12345678.
小端存储保存为: 78 56 34 12
大端存储则是: 12 34 56 78 (大端存储不需要倒过来)
Modbus基础格式:
主机读取从机输入寄存器数据格式:
数据格式:
8位举例:
modbus传递8位的 00 01 :这个表示的就是1。
换算方式可以理解为:2的 01次方就是这个8位数据的值。
16位举例:
modbus传递16位的 00 01 :这个表示的就是1。
换算方式可以理解为:前两位00*256 + 01*1就是这个16位数据的值。
32位举例:
modbus传递32位的 00 02 00 01 :这个表示的就是65538。
换算方式可以理解为:后两位(00 01)*65536 + (00 02)*1,这里需要倒过来了。
读功能码:
0x01: 读线圈寄存器
实际上就可以类比为开关量,每个bit都对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。
0x02: 读离散输入寄存器
他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的 0x02。
0x03: 读保持寄存器
这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。比如我我设置时间年月日,不但可以写也可以读出来现在的时间。
0x04: 读输入寄存器
这个和保持寄存器类似,但是也是只支持读而不能写。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。
3、Modbus协议的地址模型
为了简化数据模型与设备存储区的对应关系,引入了一种地址模型。该模型通过编号的方式对不同类型数据进行区分,各数据的地址编号请看下面的表格:
Modbus地址模型的编号从1开始。
由于每一种数据都最大支持65536个元素,因此理论上,
对于线圈型数据来说,其地址范围为:000001~065536;
类似的,
离散量输入,其地址范围为:100001~165536;
输入寄存器,其地址范围为:300001~365536;
保持寄存器,其地址范围为:400001~465536;
由于65536是比较大的数值,实际应用一般不需要这么大的存储区,因此PLC厂家普遍采用的是10000以内的地址范围,即:
线圈地址范围:00001~09999;
离散量输入地址范围:10001~19999;
输入寄存器地址范围:30001~39999;
保持寄存器地址范围:40001~49999;
有了该地址模型,我们就可以从Modbus寄存器的地址判断要访问的区块的类型。比如本文开头提到到地址40001就是保持存储器的第一个值的地址,而10001就是离散量输入的第一个值的地址;要注意的是,保持寄存器和输入寄存器的每个值的大小为16bits(字),而线圈和离散量输入每个值的大小为1bit(位);
各PLC厂家根据PLC的实际情况,将Modbus的地址模型映射到实际的存储区。一般来说,线圈对应过程输出映像区(Q);离散量输入对应过程输入映像区(I);输入寄存器对应模拟量输入(AI);保持寄存器对应数据块或V存储区或M存储区。以西门子S7-200 SMART为例,其Modbus地址与存储器地址的对应关系如下表所示:
4、Modbus 协议中对浮点数的处理
Step1 首先复习一下对于阶码、尾数
1、对于十进制
-12.5 * 10**0
12.5:就是尾数 0 就是阶码
2、对于二进制
1.1001*2**3
1.1001:就是尾数 3 就是阶码
Step2 什么是浮点数的存储方式
1、理论
地址 +0 +1 +2 +3
内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
这里
S 代表符号位,1是负,0是正
E 偏移127的幂,二进制阶码=(EEEEEEEE)-127。
M 24位的尾数保存在23位中,只存储23位,最高位固定为1。此方法用最较少的位数实现了
较高的有效位数,提高了精度。
零是一个特定值,幂是0 尾数也是0。
Step3 Modbus 中浮点数的标准存储实例
2、实例
浮点数-12.5作为一个十六进制数0xC1480000保存在存储区中,这个值如下:
地址 +0 +1 +2 +3
内容0xC1 0x48 0x00 0x00
浮点数和十六进制等效保存值之间的转换相当简单。下面的例子说明上面的值-12.5如何转
换。
浮点保存值不是一个直接的格式,要转换为一个浮点数,位必须按上面的浮点数保存格式表
所列的那样分开,例如:
地址 +0 +1 +2 +3
格式 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
二进制 11000001 01001000 00000000 00000000
十六进制 C1 48 00 00
从这个例子可以得到下面的信息:
符号位是1 表示一个负数
幂是二进制10000010或十进制130,130减去127是3,就是实际的幂。
尾数是后面的二进制数10010000000000000000000
在尾数的左边有一个省略的小数点和1,这个1在浮点数的保存中经常省略,加上一个1和小数
点到尾数的开头,得到尾数值如下:
1.10010000000000000000000
接着,根据指数调整尾数.一个负的指数向左移动小数点.一个正的指数向右移动小数点.因为
指数是3,尾数调整如下:
1100.10000000000000000000
结果是一个二进制浮点数,小数点左边的二进制数代表所处位置的2的幂,例如:1100表示
(1*2^3)+(1*2^2)+(0*2^1)+(0*2^0)=12。
小数点的右边也代表所处位置的2的幂,只是幂是负的。例如:.100...表示(1*2^(-1))+
(0*2^(-2))+(0*2^(-2))...=0.5。
这些值的和是12.5。因为设置的符号位表示这数是负的,因此十六进制值0xC1480000表示-
12.5。
Step3 更多的例子
这个是一个转换所用的一个在线的计算器,大家可以通过这个来计算 看看与自己的想的是否符合
http://www.styb.cn/cms/ieee_754.php
下面这个是我举得例子:
5、Modbus通信协议之四字节转浮点数
一、Modbus协议0x10功能码
0x10功能码:写多个寄存器
例: 请求在从机设备 17 中的 2 个寄存器中放入预置值, 起始寄存器为 40002 , 预置值为 00 0AH 和 01 02H。
Modbus主机查询
Modbus从机回复
二、数据在内存中存储方式
要想把字节正确组合成浮点数,首先要了解数据在内存中是怎么存储的。存储方式有两种:
大端模式
大端模式是指数据的高字节保存在内存的低地址单元中,而数据的低字节保存在内存的高地址单元中,这样的存储模式有点类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式
小端模式是指数据的高字节保存在内存的高地址单元中,而数据的低字节保存在内存的低地址单元中。
我使用的是STM32F4芯片,STM32的存储方式是小端模式,数据的低字节存在内存的低地址单元中,高字节存在内存的高地址单元中。如下图所示:
三、从机处理接收到的数据
我的Modbus主站是触摸屏,Modbus从站是STM32。主机输入浮点数之后,我的从机收到如下数据:
41 BC 00 00这四个字节就是我想提取的浮点数,根据Modbus协议可知,41是高字节,00是低字节。因为STM32是小端模式,所以高字节要存放在内存中的高地址。从机把四个字节存储好之后,我再把这个存储区域的首地址强制转换为float指针类型,这样就可以提取出这个浮点数了。
另外一种方式就是定义一个float变量,然后定义u8类型指针数组指向float变量地址,Modbus协议解析的时候只管向地址指向的存储单元填充数据,需要用浮点数的时候直接拿过来用就可以了。
这段过程可以在VS中模拟,主要分了两步实现。
仿真代码:
结果图:
注:在整个项目过程中可能查阅了很多资料,在整理本次文档的过程中,也有部分图片和内容是引用的其他作者或者一下文献的,如遇到侵权等问题,请联系本人修改或删除,本文仅作为个人开发经验总结,不含有任何商业价值。
modbus的使用说明——个人使用心得相关推荐
- modbus slave和modbus poll使用说明
modbus slave和modbus poll使用说明 1.使用环境: win7/win10 32/64位系统 Virtual Serial Port Driver 9.0 虚拟com端口工具 ...
- 电力-RTU终端ModBus规约(C程序)
目录: 一.Modbus slave和Modbus poll使用说明 二.Modbus协议C程序样例 ------------------------------------------------- ...
- modbus的c语言程序,电力-RTU终端MODBUS规约(C程序)
目录: 一.Modbus slave和Modbus poll使用说明 二.Modbus协议C程序样例 ------------------------------------------------- ...
- activiti使用心得(4) 请假申请单流程启动,任务列表、审批
相关文章 activiti使用心得(1) spring 集成activiti activiti使用心得(2) activiti的web应用 请假审批为例,bpmn文件的定义 activiti使用心得( ...
- modbus主站从站实现
作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 modbus 图文并茂,讲解M ...
- 初探 ModBus4j -简单使用指南
目录 前言 开发环境 工具准备 具体实现 下载Modbus4j 解决空指针异常 解决数组越界 测试 测试环境准备 正式测试 前言 之前提到过 由于项目需求,需要封装 ModBus协议,ModBus协议 ...
- 基于51单片机的蓝牙温度检测器(附完整代码,网盘链接)
目录 一.绪论 (一).设计目的 (二).设计要求 (三).设计方法 (四).设计过程 (五).实现功能 二.设计内容 (一).总体方案设计 (二).子模块设计 (三).总原理框图 (四).程序流程图 ...
- 摄影师选图脚本(根据快照文件的存在与否整理原文件)
文章目录 引言 来自图片处理的需求: 解决方案: 脚本使用方法: 1.安装python 3 2.新建一个TXT文件,拷入下面代码后保存,并将后缀名改为".py" 3.按使用说明运行 ...
- 静态优先权调度算法C语言实现6,静态优先权优先算法的进程调度程序文件.doc
. . . .. . 学习好帮手 静态优先权优先算法的进程调度程序 学 院 专 业 学 生 姓 名 学 号 指导教师姓名 21014年 3 月 19 日 目 录 TOC \o "1-3&qu ...
最新文章
- ValueError: Classification metrics can‘t handle a mix of multiclass and unknown targets
- Docker入门 一 安装Docker
- Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator
- php ajax 分页phpapi,ajax分页_php ajax分页代码
- 关于mysql出现大量locked进程
- 人到不惑,程序员是否该认命?
- android+祖玛游戏源码,Flash祖玛游戏源代码
- python plt引用_先引用matplotlib.pyplot再引用tensorflow报错问题
- Linux系统移植概述
- Unity基础组件及介绍
- 黑苹果卡在白苹果不动_从黑苹果到“白苹果”这一年我经历了什么
- 轻松掌握计算机视觉三维重建的几何基础:坐标系与关键矩阵(基础矩阵、本质矩阵、单应矩阵)
- 推荐系统:AB测试(AB Test)
- CentOS 7 升级内核
- 【算法学习】四 二分法查找(折半法或者折半查找)
- node-red教程3.3 file控件介绍
- linux 内存条DDR几,DDR、DDR2、DDR3、SDRAM等内存的简要区别
- 2022年YouTube营销:5个推荐的数据分析工具
- 基于注入式木马病毒(浏览器绑架)实现及防御方法的研究
- jyh.project
热门文章
- 版本管理工具和as的一些配置
- 无线网卡芯片类型及与linux-wlan-ng的兼容性
- 关于BCM61650IFB1G
- 计算机打印东西怎么横向打印机,打印怎么设置横向打印(打印机怎么调整打印方向)...
- vue生成app二维码,并扫码下载app
- Elasticsearch镜像打包记录
- 线上软测培训机构柠檬班与iTEST.AI平台赋能测试行业共同发展、共绽异彩
- mac如何升级python,Mac更新Python
- contiki之list(1)
- Ext中TextField的 label和feild的间距的设定