MODBUS协议是莫迪康公司1978年发明用于电子控制器进行控制和通信的协议。不同厂商生产的符合MODBUS协议的控制设备可以连成工业网络,进行集中监控。MODBUS协议采用主从(master-slave)技术,是一种问答方式的通信协议。每次通信均由主机发出数据请求信息,从机接收到正确消息后就可以发送数据到主机以响应请求;主机也可以直接发信息修改从机的数据,实现双向读写。 在具体介绍Modbus协议之前,先向大家简单介绍一下设备中的数据如何存储。我们常把设备中存储数据的单元称为寄存器,按照存储数据的类型可以分为位寄存器和16位寄存器两种,如图1所示:
图1
位寄存器的容量为1位,16位寄存器的容量为16位,每一个存储数据的寄存器都有一个对应的寄存器地址,Modbus协议就是根据寄存器地址来查询数据或者设置数据到特定的寄存器中。如图1所示,位寄存器用来存储离散值,即开关量;16位寄存器用来存储16位整数,16位寄存器里的数据既可以独立表示一个16位整数,也可以用两个连续的16位寄存器表示32位整型或实型的数据,低地址存放低16位,高地址存放高16位。 接下来详细介绍Modbus协议。Modbus协议分为三种通信方式:Modbus RTU、Modbus ASCII以及Modbus TCP。 首先,Modbus TCP的通信格式和Modbus RTU非常相似,*的差别只是Modbus RTUzui后带两个字节的CRC校验,而Modbus TCP没有。 其次,Modbus ASCII的通信格式与Modbus RTU其实“神合貌离”,就是把Modbus RTU的每一个字节(例如:27H)高四位(2)和低四位(7)拆分为两个字节,并以ASCII码的方式表现出来(32 37),再给命令帧分别加上起始符和结束符便可以,当然Modbus RTU和Modbus ASCII的校验的方式不同,这里暂不详述,所以同一条命令用Modbus RTU方式和Modbus ASCII方式表现出来,虽然在命令长度的上有很大的区别,但其实际表达的意思却是一样。 下面就以Modbus RTU为例,详细表述世纪星组态软件是如何读取设备中的数据,并且将数据设置到设备中。
1.读数据: 上位机发送命令:02 03 00 05 00 02 D4 39 设备返回的数据:02 03 04 20 08 20 10 49 3D 之前没有接触过Modbus RTU协议的朋友们看了上面列出的数据,会稍有不解,这里为大家详细解释一下。 1)发送的命令: *个字节:02,它表示的是设备地址。在同一条485总线上,可能会接多个设备,而这个设备地址就相当于每一个设备的标识,继而决定每一个设备的设备地址在同一条总线上必须是*。 第二个字节:03,这个字节是功能码字节,作用就是告诉设备,上位机想要读取的是什么样的数据,世纪星组态软件支持的读数据的功能码有:01H、02H、03H和04H,具体含义请参照表1。
表1
第三第四个字节:00 05,表示的是一个寄存器地址,它告诉设备上位机想要读取的数据,是从寄存器地址5开始的一个或多个寄存器里的数据。 第五第六个字节:00 02,表示的是读取寄存器的个数,结合第三第四个字节,就是告诉设备,上位机想要读取的数据是从寄存器地址5开始的2个寄存器里的数据,即寄存器地址为5和6的寄存器里的数据。 第七第八个字节:D4 39,是CRC校验码,不论是读数据还是设置数据,发送和返回命令里的zui后两个字节都是CRC校验码,具体的计算方法这里暂不详述。
2)返回的数据: *个字节:02,表示设备地址,作用同发送命令中*个字节02。 第二个字节:03,表示功能码,作用同发送命令中第二个字节03。 第三个字节:04,表示返回有效数据的字节个数,这里要说明一下的是对于位寄存器(包括表1中的线圈状态和输入状态),每一个寄存器的容量只有一位,如果上位机发送的命令中要求连续读8个位寄存器(即发送命令中的第五第六个字节为00 08),设备返回的数据中的第三个字节只为1,因为一个字节的容量为8位,可以表示8个位寄存器的状态。而对于表1中的保持寄存器和输入寄存器,每一个寄存器的容量为16位,它可以表示一个16位的整型数据,或者一个32位整型或实型数据的高16位或低16位。所以设备回传一个保持寄存器或输入寄存器的数据需要两个字节,这就解释了发送命令中要求读取2个保持寄存器的数据,设备返回的有效数据为4个字节。 紧跟在第三个字节后面的4个字节的数据便是设备返回的有效数据,结合发送的命令,我们可知在寄存器地址为0005H的寄存器中存储的数据为2008H(十进制为8200),寄存器地址为0006H的寄存器中存储的数据为2010H(十进制为8208)。 第八第九个字节:49 3D,是CRC校验码。
2. 写数据 1)写位寄存器 上位机发送命令:02 05 00 05 FF 00 9C 08 设备返回的数据:02 05 00 05 FF 00 9C 08 *个字节:02,表示设备地址,这里就不做重复介绍。 第二个字节:05,为功能码字节,05号功能码的作用为强置一个位寄存器的0/1(ON/OFF)状态。 第三第四个字节:0005,表示的是上位机发送命令所强置的寄存器的地址。 第五第六个字节:FF00H,表示上位机要将地址为5的位寄存器强置为1,当强置为0时,第五第六个字节为:00 00。 第七第八个字节:9C 08,为CRC校验字节。 设备正常返回时,返回的数据与上位机发送的命令是完全一致的。
2)写单个16位寄存器 上位机发送命令:02 06 00 05 00 12 19 F5 设备返回的数据:02 06 00 05 00 12 19 F5 *个字节:02,表示设备地址。 第二个字节:06,为功能码字节,06号功能码的作用为预置单个16位寄存器。 第三第四个字节:0005,表示的是上位机发送命令所预置的寄存器的地址。 第五第六个字节:0012H,表示上位机要将地址为5的16位寄存器预置为12H(十进制为18)。 第七第八个字节:19 F5,为CRC校验字节。 设备正常返回时,返回的数据与上位机发送的命令完全一致。
3)写多个16位寄存器 上位机发送命令:02 10 00 06 00 02 04 01 02 00 00 DC FD 设备返回的数据:02 10 00 06 00 04 21 F8 发送的命令: *个字节:02,表示设备地址。 第二个字节:10H(十进制为16),为功能码字节,10H号功能码的作用为预置多个16位寄存器。 第三第四个字节:0006,表示的是上位机发送命令所预置的多个寄存器的起始地址为0006H。 第五第六个字节:0002,表示上位机要连续预置连续的两个寄存器。 第七个字节:04,表示后面跟着的4个字节数据是要预置到指定寄存器中去的。 紧跟在第七个字节后的四个字节便是要预置到指定寄存器中的数据,结合前面的信息,我们知道这条命令是要将0102H(十进制为258)预置到地址为6的寄存器中,0000H预置到地址为7的寄存器中。 zui后两个字节:9C08,为CRC校验字节。 返回的数据: *个字节:02,表示设备地址。 第二个字节:10H(十进制为16),为功能码字节。 第三第四个字节:0006,表示的是上位机发送命令所预置的多个寄存器的起始地址位0006H。 第五第六个字节:0004,表示上位机预置了连续的两个寄存器即4个字节的有效数据。 第七第八个字节:19 F5,为CRC校验字节。 无论是强制位寄存器还是预置16位寄存器,设备返回数据的作用仅仅是告诉上位机数据已经成功设置到设备寄存器中了。
关于Modbus RTU协议格式的暂时介绍到这里,希望这篇文章可以让对通信协议不了解甚至没有接触过Modbus协议的朋友们对Modbus有初步的认识。在下一期的《世纪星月刊》中,我会继续介绍世纪星组态软件对Modbus 协议的支持情况,希望会对世纪星的广大用户有所帮助。 ■