说明:
OX[20] 代表是输出线圈(),用功能码 0x01,0x05,0x0F 访问, 开头地址是 0 (这个后续说明)
IX[20] 代表是输入线圈(Coil),用功能码 0x02 访问,开头地址是 1 (这个后续说明)
另外两个一样的道理。
注意:所谓的“线圈”“寄存器”就是“位变量”“16位变量”。之所以称“线圈”因为Modbus最初是施耐德公司为其PLC制定的一种通讯协议很自然Modbus协议中的很多术语是和PLC中的术语相关的。

报文模型

  1. 01 06 00 01 00 17 98 04 <br /> 从机地址 功能号 数据地址 数据 CRC校验<br />![image.png](https://cdn.nlark.com/yuque/0/2021/jpeg/12390257/1639405209256-081ac744-76c1-4177-967d-3aa02edf7bd0.jpeg#clientId=u2fb63f63-d1d6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u81728c04&margin=%5Bobject%20Object%5D&name=image.png&originHeight=144&originWidth=565&originalType=url&ratio=1&rotation=0&showTitle=false&size=38006&status=done&style=none&taskId=uacf97e87-2486-4f6d-8ed9-a9879c1d64b&title=)<br />ADU: 应用数据单元<br />PDU: 协议数据单元

操作

1、主机对从机写数据操作

如果单片机接收到一个报文那么就对报文进行解析执行相应的处理,如上面报文:
01 06 00 01 00 17 98 04
从机地址 功能号 数据地址 数据 CRC校验

假如本机地址是 1 ,那么单片机接收到这串数据根据数据计算CRC校验判断数据是否正确,如果判断数据无误,则结果是:
HoldDataReg[1] = 0x0017;
MODBUS主机就完成了一次对从机数据的写操作,实现了通讯。

2、主机对从机读数据操作

主机进行读HoldDataReg[1] 操作,则报文是:
01 03 00 01 00 01 D5 CA
从机地址 功能号 数据地址 读取数据个数 CRC校验
那么单片机接收到这串数据根据数据计算CRC校验判断数据是否正确,如果判断数据无误,则结果是:返回信息给主机,返回的信息也是有格式的:
返回内容:
01 03 02 0017 F8 4A
从机地址 功能号 数据字节个数 两个字节数据 CRC校验
MODBUS主机就完成了一次对从机数据的读操作,实现了通讯。

数据类型

Coil:大小只有1位,ON或OFF,可读可写,既可以是一个输出量输出点,也可以是数字量输入点,有效的地址范围是1-9999。
Input Status:大小只有1位,ON或OFF,只读,即数字量输出点,有效地址范围是10001-19999。
Input Register:16位的寄存器,只读,可以用作模拟量或16位打包输入点,有效地址范围是30001-39999。
Holding Register:16位的寄存器,可读可写,既可以是一个模拟量或16位打包输入点,也可以是模拟量或16位打包输出点,有效地址范围是40001-49999。
image.png
在PLC或DCS上用点名标记不同的变量,在Modbus则以数据地址来标记每个点。以上所说的地址都是参考地址,而不是实际的物理地址。上述的地址是在设备中的地址,按照PLC的习惯从1开始递增,而Modbus报文中是从0开始递增。例如地址偏移为4、5、6的Holding Register,其实是指参考地址是40005、40006、40007的寄存器。

Modbus TCP、Modbus RTU和Modbus ASCII的区别

对于不同类型的网络,Modbus的第7层实现是一样的,区别在于下层的实现方式,常见的有TCP/IP和串行通讯两种。
Modbus TCP基于以太网和TCP/IP协议,Modbus RTU和Modbus ASCII则是使用异步串行传输(通常是RS-232/422/485)。
image.png
图2
对于Modbus TCP而言,主站通常称为Client,从站称为Server;而对于Modbus RTU和Modbus ASCII来说,主站是Master,从站是Slave。
如图2所示,串行传输的物理层是RS-485或RS-232,数据链路层是Modbus的串行传输协议;Modbus TCP的1、2、3、4层实现和日常所见的以太网、因特网一样。Modbus默认采用的TCP端口号是502。

Modbus TCP

image.png
图3
图3说明了Modbus TCP的改动:

  1. 取消了校验位。数据链路层上就进行了CRC-32的校验,TCP/IP是面向连接的可靠性的协议,因此没必要再加上校验位。
  2. Slave地址换成了Unit Identifier。当网络里的设备全是使用TCP/IP,这个地址是没有意义的,因为IP就能进行路由寻址。如果网络里还有串行通讯的设备,则需要网关来实现Modbus TCP到Modbus RTU或ASCII之间的协议转换,这时用Unit Identifier来标识网关后面的每个串行通讯设备。
  3. Length是指后面的字节总数。实际上数据区的长度是能确定的,有的功能码就可以确定数据区的长度,有的功能码虽不能确定数据区长度,但是数据区有字节计数,参见上文举的从站应答的例子。表头增加的Length是为了应对有些情况下TCP/IP协议会将应用层的数据拆包传输。
  4. Transaction Identifier和Protocol Identifier由Client生成,Server的响应将复制这些参数。

    RTU和ASCII的区别

    RTU模式下,一个字节的数据,传输的就是一个字节。ASCII模式下,同样一个字节数据用了两个字节来传输。
    例如,要传输数字0x5B,RTU传输的是0101 1011(二进制),而ASCII传输的是00110101和01000010。可见,ASCII传输的速率是RTU的一半。
    ASCII模式采用LRC校验,RTU模式采用16位CRC校验。