Modbus RTU协议各知识点入门 + 实例

您所在的位置:网站首页 modbusrtu协议 Modbus RTU协议各知识点入门 + 实例

Modbus RTU协议各知识点入门 + 实例

2023-08-12 04:08| 来源: 网络整理| 查看: 265

文章目录 1. 起因2. 几个重点2.1 一些难懂的概念2.2 CRC的高低位2.3 其他 3. 介绍3.1 起源3.2 分类 4. 格式4.1 串口协议4.2 帧格式 5. 数据类型6. 功能码7. CRC16(modbus)8. 实例8.1 功能码18.2 功能码28.3 功能码38.4 功能码48.5 功能码58.6 功能码68.7 功能码158.8 功能码16 9. 实现思路9.1 我的实现思路9.2 别人的实现思路(一些开源库) 10. 参考

1. 起因

最近在做一个项目,我们的设备使用485作为从机与主机PLC通信,用到了modbus,因此整理了一份modbus的资料。 其实modbus还是很简单的,虽然有些名词初看不知道是啥,看懂之后发现就是绕人用的,换个名词就很清晰易懂的(对于我这种不做PLC的人)。

2. 几个重点 2.1 一些难懂的概念 线圈 就是“位变量” 离散输入 就是 只读 的 1位变量线圈 就是 可读写 的 1位变量 寄存器就是“16位变量” 输入寄存器 就是 只读 的 16位变量保持寄存器 就是 可读写 的 16位变量

具体可以见5章节,阅读的时候把这几个名词直接替换就好。

2.2 CRC的高低位

Modbus协议的CRC校验码是高位在前还是低位在前的问题。 有些资料说高位在前,有些资料是说低位在前。 其实是因为CRC生成函数,有些在内部已经做了高低位的转换,所以看起来像是高位在前。 实际上,CRC是低位在前发送。详细见第7节。

2.3 其他 不管任何时候,从机都不能主动向主机发送数据从站的地址是1~247(注意没有0!! 0是广播!都不回复,都会收到!)数字编码大端序,高字节在前CRC校验位低字节在前modbus的寄存器都是16位的,但是在其他地方(比如MCGS)也见过一些变种,比如32位的,比如float的。有些是把32位按照标准的modbus,拆分成了2个寄存器。有些就是按1个4字节的寄存器来算的。 3. 介绍 3.1 起源

modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。 1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbusTCP。

3.2 分类

Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。ASCII是明文的,但是实际效率低,用的比较普遍的就是RTU格式。 这里我也是只用了RTU,就只记录RTU的协议。

4. 格式 4.1 串口协议 串口波特率串口设置 4.2 帧格式 起始位地址码功能码数据区错误校验码3.5字符时间1字节1字节0~252字节CRC16校验码1~247见3.5节CRC低位 CRC高位注意这里,多字节的数据,是高位在前,低位在后。但是CRC是低位在前,高位在后。根据不同的功能码,数据区各不相同,具体可以看第8部分实例来分析。 5. 数据类型 数据类型简写读功能码写功能码对象地址范围离散输入DI02只读的 1位变量00001~0FFFF线圈DO0105,15可读写的 1位变量10001~1FFFF输入寄存器AI04只读的 16位变量30001~3FFFF保存寄存器AO0306,16可读写的 16位变量40001~4FFFF DI: 数字输入,离散输入,一个地址一个数据位,用户只能读取它的状态,不能修改。比如面板上的按键、开关状态,电机的故障状态。DO: 数字输出,线圈输出,一个地址一个数据位,用户可以置位、复位,可以回读状态,比如继电器输出,电机的启停控制信号。AI: 模拟输入,输入寄存器,一个地址16位数据,用户只能读,不能修改,比如一个电压值的读数。AO: 模拟输出,保持寄存器,一个地址16位数据,用户可以写,也可以回读,比如一个控制变频器的电流值。 6. 功能码

功能码很多,用的比较多的就是以下8个:

功能码功能码16进制中文名称操作位操作寄存器数量010x1读线圈1位单个或多个020x2读离散输入1位单个或多个030x3读保存寄存器16位单个或多个040x4读输入寄存器16位单个或多个050x5写单个线圈1位单个060x6写单个保存寄存器16位单个150xF写多个线圈1位多个160x10写多个保持寄存器16位多个

最主要的就是1、2、3、4、5、6、15、16 这8个功能码。 个人翻译一下 01:读一个或多个可读写的 bit 变量 02:读一个或多个只能读的 bit 变量 03:读一个或多个可读写的 short 变量 (或其他2字节变量) 04:读一个或多个只能读的 short 变量 (或其他2字节变量) 05:写一个可读写的 bit 变量 06:写一个可读写的 short 变量 15:写多个可读写的 bit 变量 16:写多个可读写的 short变量 (可以拼凑成int 、long 、long long、float等变量)

读的时候,都是可以选择读“一个或多个”。 写的时候,按数量分功能码进行操作。

7. CRC16(modbus)

在CRC计算时只用8个数据位,起始位及停止位,如有奇偶校验位也包括奇偶校验位,都不参与CRC计算。 CRC计算方法是:

加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器。把第一个8位二进制数据(即通讯信息帧的第一个字节)与16位的CRC寄存器的相异或,异或的结果仍存放于该CRC寄存器中。把CRC寄存器的内容右移一位,用0填补最高位,并检测移出位是0还是1。如果移出位为零,则重复第三步(再次右移一位);如果移出位为1,CRC寄存器与0XA001进行异或。重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理。重复步骤2和5,进行通讯信息帧下一个字节的处理。将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换最后得到的CRC寄存器内容即为:CRC校验码。

注意!这个 高低字节交换 之后的,才是算出来的modbus的CRC校验码。 然后把这个交换后的校验码,按照 先低位,后高位 的 顺序加载到发送队列里。

8. 实例

从网上随便截取了一些别人的例子,部分来自示例

8.1 功能码1

在这里插入图片描述

8.2 功能码2

在这里插入图片描述

8.3 功能码3

在这里插入图片描述

8.4 功能码4

在这里插入图片描述 主机要读取从0x400地址的2个16位寄存器的值。 从机回复了4个字节。

8.5 功能码5

在这里插入图片描述 在这里插入图片描述

8.6 功能码6

在这里插入图片描述

8.7 功能码15

在这里插入图片描述

8.8 功能码16

在这里插入图片描述

9. 实现思路 9.1 我的实现思路

我这边实现思路比较简单, 利用串口中断判断收到的报文,如果满足报头(设备地址),就进行报文连续接收,收满一帧就放入处理队列。另一个线程收到这个数据会取出来解包处理。 寄存器方面就是申请一块连续buf(数组或其结构体),和寄存器地址一一对应上,要改值或者要读值都是根据这个buf的数据来做。

9.2 别人的实现思路(一些开源库)

用的比较广的是FreeModbus和LibModbus。

10. 参考 modbus官网modbus的CRC高低位问题CRC在线计算器modbus介绍-很多相关链接modbus介绍2-很多相关链接小工匠系列,感觉系列没写完FreeModbus移植工程FreeModbus移植笔记


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3