一、了解Modbus
MODBUS 是 OSI 模型第 7 层上的应用层报文传输协议,它在连接至不同类型总线或网络的设备之间提供客户机/服务器通信。
它主要用于工业自动化设备通信。
MODBUS可以在基于串行链路和以太 TCP/IP 网络的 MODBUS 上可以进行通信,也就是说,可以使用串口线或者网线链接两端设备,双方约定使用modbus协议去通信。
二、了解Modbus协议
前面我们说了MODBUS有两种实现方式,一个是串口,一个是网口(后面称呼为TCP),那么MODBUS协议对应的也就有两个协议,但是这两个协议极为相似,后面会说明。
功能码
在了解协议之前,我们先了解一下MODBUS功能码,我们常用的功能码有01、05、03、06、16。下面我们来看什么时候使用什么功能码,线圈是其实就是开关,实际值只有0和1,所以当我们传输的值只有0和1就可以表示的话可以使用线圈,而读线圈就是客户端去读取服务端的线圈,同理写线圈就是客户端去写入新的值到服务器,这里我们可以发现,服务器是不能主动向客户端发送命令的(包括读和写);寄存器就是一个存储数据的中央处理器的部件,它可以存储的值比线圈要多,一个寄存器有16位,如果你要存储32位的整数或浮点数可以用两个连续的寄存器来存储。
串口报文
串口协议报文格式如下:(PDU包括功能码和数据)
地址域\功能码\数据\CRC校验
其中这个CRC校验为2个字节,还有这个数据长度是不固定的,根据不同的功能码有不同的数据长度。
我们先来看个传输例子:01 03 00 01 00 02 95 CB
这里我们先看功能码为03的请求报文格式:
功能码03的PDU为下图:
我们按照格式可以看出:地址域是01,功能码是03,起始地址为01(00 01),寄存器数量为02(00 02),这里起始地址和寄存器数量都是2个字节,合并之后的值为最终值。
95 CB为CRC校验,这里可以不管。
每个功能码的PDU可能会不一样,但是都是固定好的,这就好像每个功能码是一条数学公式。功能码03读寄存器,当我们读取服务端的数据,需要告诉服务端要读取的值的起始地址(这个一般由服务端定义并提供),和要读取数据的数量。
这里是客户端发送请求,读取服务器的寄存器地址,MODBUS 的每个客户端请求我们都需要响应,下面我们看响应的PDU:
当客户端发送01 03 00 01 00 02 95 CB读取寄存器时,服务端需要返回响应报文。
响应报文为:01 03 04 00 02 00 04 95 CB
我们按照格式可以看出:地址域是01,功能码是03,04是字节数,上面我们读寄存器数量是2,那么响应报文的字节数为2*2=4,00 02 00 04是返回客户端要读取的寄存器的两个值,分别是2和4,95 CB为CRC校验。
TCP报文
接下来我们看MODBUS 的TCP协议
TCP协议和串口协议类似,只是多了一个MBAP报文头和少了CRC校验,MBAP报文头包括有事务处理标识符、协议标识符、长度、单元标识符,一共为7个字节长度,这几个标识符保持和客户端发过来的一致即可,长度的值为后面发送的字节长度。
下面我们同样用功能码03来举例说明
00 01 00 02 00 06 01 03 00 01 00 02
我们按照格式可以看出:事务处理标识符是01,协议标识符02,长度是6(长度值为长度后面的字节数),功能码是03,起始地址为01(00 01),寄存器数量为02(00 02)。
以上就是MODBUS协议的两种报文方式了
这里附上所有功能码的报文PDU
01
*N=输出数量/8,如果余数不等于 0,那么
N = N+1
02
03
04
05
06
15
16
补充
对于初学者可能对这个报文不太理解,这里补充几句,首先这个modbus的报文是固定的,比如读寄存器,可以使用03功能码,读的地址是多少,读几个数量,按照modbus协议形成了一条报文。这里需要根据业务去定义自己的协议地址,这里说的协议地址就是要读的地址,比如A和B通讯,A作为服务端,接受客户端B的报文,A方提供协议地址(协议地址由服务端自定义),如地址1代表值a,地址2代表值b,那么B方就可以通过串口或网口发送读取报文到A方,同样是举例(01 03 00 01 00 02 95 CB,这里读取起始地址1是a,要读取的寄存器数量为2,也就是读取a和b两个值),这样B方通过Modbus协议便得到了A方的数据,至此完成Modbus通信。