一文详解Modbus协议原理、技术细节及软件辅助调试
使用技术辅助:如在线会议软件进行远程协作。 #生活技巧# #组织技巧# #会议流程设计#
Modbus 协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。 Modbus 协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为 Modbus Master,从设备方使用的协议称为 Modbus Slave。典型的主设备包括工控机和工业控制器等;典型的从设备如 PLC 可编程控制器等。有了它,不同厂商生产的控制设备就可以连接成工业网络,进行集中监控。 Modbus 协议定义了一个控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的;而且描述了控制器请求访问其他设备的过程,如何应答来自其他设备的请求,以及怎样侦测错误并记录,并制定了统一的消息域的结构和内容。 当在 Modbus 网络上通信时, Modbus 协议决定了每个控制器必须要知道它们的设备地址,识别按地址发来的消息决定要产生何种行为。如果需要回应,则控制器将生成反馈信息并通过 Modbus 协议发送。
Modbus是一种“一主一从”的点对点通信方式(主机发一帧,从机回一帧的形式),当然在连接上也可以一主多从(宏观看),但实际也是一对一通信,同一时刻只能有一个从机进行响应。
如果需要和多个从机同时通信,这里也支持使用广播,即主机发送指令,所有从机接收指令并执行,但不进行应答。当进行一主多从通信时,主机通过从机ID号来区分要通信的从机设备。从机ID范围为1 - 247,0为广播地址,248~255为用户自定义地址。
Modbus 通讯物理接口可以选用串口(包括 RS232、 RS485 和 RS422 等),也可以选择以太网口。其通信遵循以下的过程:
① 主设备向从设备发送请求
② 从设备分析并处理主设备的请求,然后向主设备发送结果
③ 如果出现任何差错,从设备将返回一个异常功能码
此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
当在 Modbus 网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus 协议发出。在其它网络上,包含了 Modbus 协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。
Modbus 的工作方式是请求/应答,每次通讯都是主站先发送指令,可以是广播,或是向特定从站的单播;从站响应指令,并按要求应答,或者报告异常。当主站不发送请求时,从站不会自己发出数据,从站和从站之间不能直接通讯。
MODBUS 是一种应用层消息传递协议,位于 OSI 模型的第 7 层。它提供连接在不同类型总线或网络上的设备之间的客户端/服务器通信。Modbus 通信栈如下:
MODBUS 协议允许在各种网络体系结构内进行简单通信,每种设备(PLC、HMI、控制面板、驱动程序、动作控制、输入/输出设备)都能使用 MODBUS协议来启动远程操作。在基于串行链路和以太 TCP/IP 网络的 MODBUS 上可以进行相同通信。一些网关允许在几种使用 MODBUS 协议的总线或网络之间进行通信。
首先从软件层面来看,如果现在有一对设备需要进行Modbus通信,那么至少需要有一个主机,一个从机,所以在应用层面上,会使用到Modbus主机和Modbus从机协议栈。
然而MCU跟MCU之间的通信,还需要借助一些外围电路来实现,以匹配不同的应用环境。最简单的是TTL,两个MCU直连。如果需要长距离传输,则需要使用232、485、422这种。如果使用TCP,则需要有以太网相关电路。
作为Modbus的一种通信形式,RTU是一种远程终端控制系统,一般是基于串口进行通信。其报文格式是十六进制的,由 Slave ID + 数据 + CRC校验 三部分组成。数据部分详见上面报文解析。剩下的就是数据校验了,这里用的是CRC校验(循环冗余校验,Cyclic Redundancy Check,简称CRC)。要注意的是,数据部分高位在前、低位在后,而CRC校验则是低位在前,高位在后。
//CRC校验的C语言实现,摘自FreeModbus static const uint8_t aucCRCHi[256] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40}; static const uint8_t aucCRCLo[256] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40}; uint16_t usMBCRC16( uint8_t * pucFrame, uint16_t usLen ) { int iIndex; uint8_t ucCRCHi = 0xFF; uint8_t ucCRCLo = 0xFF; while( usLen-- ) { iIndex = ucCRCLo ^ *( pucFrame++ ); ucCRCLo = (uint8_t)( ucCRCHi ^ aucCRCHi[iIndex] ); ucCRCHi = aucCRCLo[iIndex]; }return (uint16_t)( ucCRCHi << 8 | ucCRCLo ); }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.
国标GBT 19582-2规定:一帧中两个字符之间间隔时间不超过1.5字符,以大于3.5字符间隔时间作为一帧的结束,波特率高于19200时,间隔时间固定为1.75ms。
比如,假设串口设置的波特率为9600,1个停止位,无校验位,8个数据位(这种设置以下会简写成9600-1N8的形式),那么此设置下,断帧时间应该为:
即:35/9600 = 3.64ms。
ASCII是一种字符型的通信方式,一般也是基于串口进行通信。其报文格式是以ASCII码编码的,由 帧头(:)+Slave ID+数据+LRC校验+帧尾(/r/n)五部分组成,其中Slave ID、数据部分跟RTU完全一样,只不过是以ASCII编码形式,如Slave ID,RTU是 0x01 一个字节的时候,ASCII表示就是30 31两个字节。所以实际工业应用场合很少会用到Modbus/ASCII,因为通信效率太低。
TCP是一种网络协议,而Modbus/TCP就是基于网络协议上的一种应用层协议。其报文格式是十六进制的,由报头(2字节的帧序号+2字节的协议类型+2字节的数据长度+1字节的Slave ID)+数据 两部分组成。由于该通信方式是基于TCP/IP这种可靠协议上,所以通信不需要有额外的校验机制。
Modbus 是一个请求、 应答协议,并且提供统一的功能码用于数据传输服务。 Modbus 功能码是 Modbus 请求/应答 PDU (Protocol Data Unit,协议数据单元)的元素之一,所谓的PDU 其实就是 Modbus 协议定义的一个与基础通信层无关的简单协议数据单元。特定总线或网络上的 Modbus 协议映射能够在 ADU (Application Data UInit ,应用数据单元)上引入
一些附加域,从而实现完整而准确的数据传输。
为了寻求一种简洁的通信格式, Modbus 协议定义了 PDU 模型,即功能码+数据的格式,而为了适应多种传输模式,又在 PDU 的基础上增加了必要的前缀 (如地址域)和后缀(如差错校验) ,形成了 ADU 模型。通用 MODBUS 帧如下:
MODBUS 协议建立了客户机启动的请求格式。客户机创建 MODBUS 应用数据单元(ADU),其中包含的PDU中的功能码向服务器指示具体执行哪种操作。PDU中的数据域包括执行功能码操作需要的附加信息,例如,地址、数量以及域中的实际数据字节数等。在一些特定请求中,功能码指示的操作不需要附加信息,此时数据域可以是不存在的。
如果传输无误,且服务器能够正确响应,那么响应PDU中将使用与客户机相同的功能码加包含了请求数据的数据域。如果出现与请求 MODBUS 功能有关的差错,那么将原功能码的MSB将置1,且数据域包括一个异常码,客户机应用能够使用这个域确定下一个执行的操作。
简单记忆方法:
① 偶数类的寄存器”是可读可写的,比如“0x”和“4x”;
② “奇数类的寄存器”是只读的,比如“1x”和“3x” ;
③ “0x”和“1x”是 bit 寄存器;
④ “3x”和“4x”是 16bit 寄存器。
这是一种基于标准Modbus上的PLC应用协议,目前貌似没有一个绝对的标准,不同的PLC厂家有自己的定义,但实际通信链路层走的协议还是按标准的Modbus协议来的。
比如某PLC厂家规定,读取保持寄存器的地址是40001~49999,当PLC读取40001地址时,实际链路层读的是0000地址(就是在标准的基准地址前加上一个分段标识符,并且地址偏移1)。
Modbus Poll 是 Modbus 主站设备仿真器,用于测试和调试 Modbus 从设备便于观察Modbus 通信过程中的各种报文数据。该软件支持 ModbusRTU、 ASCII、 TCP/IP。用来帮助开发人员测试Modbus从设备,或者其它Modbus协议的测试和仿真。它支持多文档接口,即,可以同时监视多个从设备/数据域。每个窗口简单地设定从设备 ID,功能,地址,大小和轮询间隔。你可以从任意一个窗口读写寄存器和线圈。如果你想改变一个单独的寄存器,简单地双击这个值即可。或者你可以改变多个寄存器/线圈值。提供数据的多种格式方式,比如浮点、双精度、长整型(可以字节序列交换)。该软件支持 Modbus RTU、 ASCII、TCP/IP 、UDP/IP等协议模式。
Modbus 从设备仿真器,可以仿真 32 个从设备/地址域。每个接口都提供了对 EXCEL 报表的 OLE 自动化支持。主要用来模拟 Modbus 从站设备,接收主站的命令包,回送数据包。帮助 Modbus 通讯设备开发人员进行 Modbus 通讯协议的模拟和测试,用于模拟、测试、调试Modbus 通讯设备,便于观察 Modbus 通信过程中的各种报文数据;可以 32 个窗口中模拟多达 32 个 Modbus 子设备。与 Modbus Poll 的用户界面相同,支持功能 01, 02, 03, 04, 05,06, 15, 16, 22 和 23,监视串口数据。
虚拟串口工具,可以创建 2 个互联的串口(例如将COM1与COM2互联), 此时,我们可以通过 Modbus Poll 工具使用 COM1 发送数据给 COM2, Modbus Slave 从 COM2 读到数据。使用虚拟串口,就可以不使用开发板也可以体验 Modbus Poll、 Modbus Slave。
根据前面的设定我们已将知道了如何运用 Modbus 学习必备三件套,下面我们就通过三件套来进行实验,首先打开 VSPD 虚拟串口软件,设置虚拟串口,我这里就以上面设订 COM1,COM2 为例,接下来我们再来配置我们的 Modbus Poll 与 Modbus Slave;
首先,打开 Modbus Slave 端,设置连接,连接方式我们选择 Serial Port 串口连接,选择我们设置的串口 COM1,模式选择 RTU 模式;再设置参数,从机地址设定为 1(也可随意设定), Function 项选择03 Holding register(4x),地址类型选择 DEC(十进制格式), Address 首地址设置为 0,访问寄存器数量设置为 10 。
我们还可以在 Modbus Poll中,点击 Display,选择 Commuaction,查看发送的报文:TX 是我们主站发送的报文, RX 是从站返回的报文。
网址:一文详解Modbus协议原理、技术细节及软件辅助调试 https://klqsh.com/news/view/323127
相关内容
Modbus 协议版本绝地求生辅助软件使用心理分析及对策建议
wepoker辅助软件挂(透视)的技术支持如何
家电进销存软件使用方法详解,家电进销存软件怎么用?
Modbus初学者教程
如何撰写一份高效的《软件项目实施计划书》?
揭秘 Zigbee 无线通信模块:轻松调试技巧与实战指南
如何制定完美的软硬件开发计划书?5个关键步骤助你事半功倍
软件测试必读的经典书籍
突发事件应急处理预案及详细流程图解析

