modbus属于应用层协议,它的链路层协议可以是基于TCP也可以基于串口协议,物理层协议可以是TIA-232(RS232)、TIA-485(RS485)、Ethrnet(网口)。根据链路上传输的数据帧格式不同又可以分为
Modbus-RTU
Modbus-ASII
Modebus-TCP
平常见的最多的就是基于RS485接口的modbus协议,
以下内容都是基于RS232/RS485的Modbus-RTU协议作为讲解(标准协议版本为V1.1b3)
modbus网络采用master/slaver模式,一个总线上只能存在一个master,可以存在多个slaver,数据传输采用请求/应答模式,只有master才能发起请求,slaver应答。每个slaver采用一个字节作为其地址。
其中0为广播地址,1-247作为slaver设备地址,248-255地址保留未使用。
Adiitional address(1Byte): slaver地址,0-247
Function code(1Byte): 功能码,用来表明这个请求/应答帧的功能
Data(nByte): 请求/应答数据
Error check(2Bytes): CRC校验码
modbus的data一共有四种类型
Discreates Input 离散输入
Coils 线圈
Input Registers 输入寄存器
Holding Registers 保持寄存器
你要问为啥起这么奇怪的名字,这个可能是因为最早的modbus协议是用于PLC控制的,并且在上个世纪70年代就有了,很多名称都是老古董了。
其中,Discreates Input和Coils这两类数据只能按bit访问,也就是数据范围是0-1;Input Registers和Holding Registers只能按双字节访问,也就是数据访问为0-65535;另外,Discreates Input和Input Registers只能读,不能写,而Coils和Holding Registers可读可写。
每一类数据中的理论上最大可以包含65536个元素,给每一个元素分配一个地址(可理解为寄存器地址),理论上,可以分配如下如下
对于线圈型数据来说,其地址范围为:000001~065536
类似的,
离散量输入,其地址范围为:100001~165536;
输入寄存器,其地址范围为:300001~365536;
保持寄存器,其地址范围为:400001~465536;
由于65536是比较大的数值,实际应用一般不需要这么大的存储区,因此PLC厂家普遍采用的是10000以内的地址范围,即:
线圈地址范围:00001~09999;
离散量输入地址范围:10001~19999;
输入寄存器地址范围:30001~39999;
保持寄存器地址范围:40001~49999;
可以用下图去理解
因为,保持寄存器可存储的数据范围大(双字节),并且可读可写,所以市面上的slaver设备参数大多使用“保持寄存器”存储。
有了上面数据模型的理解基础,对Function code就比较好理解了。Function code是对前面的四种数据类型的操作方法。
可以这么去理解,一共有四种数据类型,每种数据类型包含一种或者两种读写权限,其中Discreates Input和Input Registers只能读,这里就是2种操作方法,分别对应read Discreates Input和 read Input Registers; 而Coils和Holding Registers可读可写,排列组合就有4中操作方法,这里就一共有6个function了,还有其他的如读取单个还是多个寄存器等其他操作,就组成了下面的组合。
1.向01地址设备的40001(0x9c41,类型为Holding Registers),写单个寄存器(功能码为06)数据0x0190
主机发送: 01 06 9c 41 01 90 F6 72
从机回复: 01 06 9c 41 01 90 F6 72
2.向01地址设备的40001(0x9c41,类型为Holding Registers),读一个寄存器(功能码为03)数据
主机发送: 01 03 9c 41 00 01 fa 4e
其中,00 01表示需要读取的寄存器个数(这里要注意每个寄存器是2Bytes)
从机回复:01 03 02 aa bb 86 97
齐总02表示数据长度,aa bb表示读取到的数据