一、Modbus协议
ModBus官网是Modicon(Modicon被施耐德收购)公司为其PLC通讯而开发的一种通讯协议。
Q1-什么是PLC?
A1- 在工业生产过程中,大量的开关量顺序控制,它按照逻辑条件进行顺序动作,并按照逻辑关系进行连锁保护动作的控制,及大量离散量的数据采集。传统上,这些功能是通过气动或电气控制系统来实现的。 1968年美国GM(通用汽车)公司提出取代继电气控制装置的要求,第二年,美国数字公司研制出了基于集成电路和电子技术的控制装置,首次采用程序化的手段应用于电气控制,这就是第一代可编程序控制器,称Programmable Controller(PC)。
个人计算机(简称PC)发展起来后,为了方便,也为了反映可编程控制器的功能特点,可编程序控制器定名为Programmable Logic Controller(PLC)
PLC是个可编程序的控制器,是一个设备产品是一个实物。
Q2-通讯协议
A2- 协议是一种规范和约定,是一种通讯的语言。规定了通讯双方能够识别并使用的消息结构和数据格式。
modbus是工业上常用的通讯协议,和普通的软件开发中的通讯协议差不多。
总结: Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。可以理解你的PLC设备和我的PLC设备想通讯聊天,我们就得遵循这个协议来交流。
Modbus协议支持RTU、ASCII、TCP三种常见传输模式
上面三种模式,根据常用传输介质,Modbus可使用串口和网口(含光纤)方式进行传输,RTU、ASCII是属于串口通讯,TCP属于网口(以太网通讯)。
串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。
想仔细了解串口可以看看这个文章 读懂com/串口。
在一个Modbus网络上的所有设备都必须选择相同的传输模式和串口参数。
这里出现了一个 串口参数也就是设置合适的通讯参数,串口参数详细请看:
学习串口参数详解:波特率,数据位,停止位,奇偶校验位 (360doc.com)
波特率:串口通讯时候得速率
数据位:衡量通信中实际数据位的参数
停止位:用于表示单个包的最后一位
校验位:串口通信中一种简单的验错方式。4种:偶奇高低
在正式开始使用Modbus模拟器前,还需要了解一些概念:
1. C,C++规定,16进制数必须以 0x开头。比如 0x1表示一个16进制数
2. 主从模式和对等模式
控制器通信使用主—从技术,即仅一设备(主设备)能初始化传输(查询)。其它设备(从设备)根据主设备查询提供的数据作出相应反应。典型的主设备:主机和可编程仪表。典型的从设备:可编程控制器。
主设备可单独和从设备通信,也能以广播方式和所有从设备通信。如果单独通信,从设备返回一消息作为回应,如果是以广播方式查询的,则不作任何回应。Modbus协议建立了主设备查询的格式:设备(或广播)地址、功能代码、所有要发送的数据、一错误检测域。
从设备回应消息也由Modbus协议构成,包括确认要行动的域、任何要返回的数据、和一错误检测域。如果在消息接收过程中发生一错误,或从设备不能执行其命令,从设备将建立一错误消息并把它作为回应发送出去。
在其它网络上,控制器使用对等技术通信,故任何控制都能初始和其它控制器的通信。这样在单独的通信过程中,控制器既可作为主设备也可作为从设备。提供的多个内部通道可允许同时发生的传输进程。
在消息位,Modbus协议仍提供了主—从原则,尽管网络通信方法是“对等”。如果一控制器发送一消息,它只是作为主设备,并期望从从设备得到回应。同样,当控制器接收到一消息,它将建立一从设备回应格式并返回给发送的控制器。
我们要和控制器通讯,首先要求协议一样,串口参数一样。传输模式一样。
这里说说Mdobus三种传输模式:
通信帧被称为应用数据单元(Application Data Unit,ADU),它包含通信地址段、功能代码段、数据段和校验段。
其中,功能代码段和数据段组合称为协议数据单元(Protocol Data Unit,PDU)。
通信地址段:每个设备或者说从机都有个地址识别,我理解是MAC地址。唯一的。等于说主机发消息说hello 张三,那一堆从机收到消息。得和自身匹配才行。不然你不是张三,你应答个啥。
ADU = 地址域+PDU+校验
PDU = 功能码+数据
功能码:决定这一帧数据主要是干嘛的,就是我有个编码比如说数字1,表示我喊你把灯打开,数字2,告诉我灯的状态等等。类似于一个字典。占用一个字节,取值范围(1-255),其中128-255为保留,用于异常消息应答报文。1到127为功能代码编号,其中65到72和100到110为用户自定义编码。
数据:可有可没有,根据需求来
校验段:就是一种检验数据的手段,比如你给我说的我爱你,而我收到的信息是我恨你,这不就乱套了么。所以得校验你的数据是不是你要传的数据。
Modbus的功能码
串行通信中规定ADU的最大长度为256个字节,通信地址占用1个字节。校验2个字节,所以PDU的字节253 ,256-1-2=253字节。
以太网通信的TCP,因为要增加一个7个字节的MBAP(MODBUS Application Protocol)的报文头,所以他的ADU的长度=253+7=260 字节。tcp不需要校验。因为底层做了这份工作。底层的数据链路层已经做了冲突检测的工作,自然就可以同时传输不担心数据撞车。
RTU模式
对于上图,就是发送的消息要有间隔时间。不然你一股脑的发过来,谁分辨的清楚。
8bit包含的是2个4bit的十六进制。
ASCII模式
在该模式下,传输的帧中的数据的每一位只能是ascii码的0-9 a-f,因为rtu模式下一字节一个数据,也就是1字节0x00-0xff,所以在ascii模式下为了传送相同的数据,必须两个字节标识一个有效数据,也就是如下:
可以看到,找ascii模式下,不是依靠时间间隔判定帧起始了,而是依靠特定字符判断,结束也是按照特定字符判断,起始的判断是’:’字符,结束的判断是windows下的回车换行,数据的最大长度被扩容到了2*252,这样,两种传输模式能传输相同的数据量,但是ascii传输的更慢了。
TCP模式
TCP的报文帧 = MBAP+PDU
MBAP为报文头,长度为7字节,组成如下:
MBAP报文头
其中MBAP报文头的组成为:
由上表可知,报文头为 7 个字节长。
PDU报文体
PDU的组成为功能码(一个字节)和数据(n个字节),其中功能码为一个字节,modbus定义的功能码有:
01 读线圈(coils)状态,读取单个或多个
02 读离散输入(discreteinputs)状态,读取单个或多个
03 读保持寄存器(holdingregisters),读取单个或多个
04 读输入寄存器(inputregisters),读取单个或多个
05 写单个线圈(coils)状态,单个写入
06 写单个保持寄存器(holdingregisters),单个写入
15 写多个线圈(coils),多个写入
16 写多个保持寄存器(holdingregisters),多个写入
另外,当响应报文的功能码最高位为1时(即:(function & 0x80) != 0),表示为异常响应,这时数据为一个字节的异常码,具体的异常码定义有:
01 功能码不能被从机识别
02 从机的单元标识符不正确
03 值不被从机接受
04 当从机试图执行请求的操作时,发生了不可恢复的错误。
05 从机已接受请求并正在处理,但需要很长时间。返回此响应是为了防止在主机中发生超时错误。主站可以在下一个轮询程序中发出一个完整的消息,以确定处理是否完成。
06 从站正在处理长时间命令。Master应该稍后重试。
07 从站不能执行程序功能。主站应该向从站请求诊断或错误信息。
08 从站在内存中检测到奇偶校验错误。主设备可以重试请求,但从设备上可能需要服务。
10 专门用于Modbus网关。表示配置错误的网关。
11 专用于Modbus网关的响应。当从站无法响应时发送。
PDU报文详情
1、读线圈
请求报文:
正常响应报文:
异常响应报文:
2、读离散输入
请求报文:
正常响应报文:
异常响应报文:
3、读保持寄存器
请求报文:
正常响应报文:
异常响应报文:
4、读输入寄存器
请求报文:
正常响应报文:
异常响应报文:
5、写单个线圈
请求报文:
正常响应报文:
异常响应报文:
6、写单个保持寄存器
请求报文:
正常响应报文:
异常响应报文:
7、写多个线圈
请求报文:
正常响应报文:
异常响应报文:
8、写多个保持寄存器
请求报文:
正常响应报文:
异常响应报文:
练习题1:
请在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位 解析: 00 01 00 00 00 06 01 01 00 02 00 08
req格式: MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
对应下图:
这里都是16进制表示。为啥是16进制。1byte不是等于8bit么。计算机在进制转换的时候4bit和16进制转换简单。至于16进制前缀0x,不用过多言语了。
高八位和低八位:内存里,一个单元是一个字节,也就是8位。如果是16位的指令,就是同时操作连续的2个内存地址,将这连续的2个内存地址当成一个单位,所以就有高8位和低8位之分。
00 01 :2字节事务处理标识符。理解为序列号
00 00 :2字节协议标识符。TCP就是00 00
00 06 :2字节。表示后面的数据长度。后面不就是6个么
01: 设备地址。就是这题的0x01
01:功能码读线圈。没啥可说的。不熟悉就对照那个功能码去看。
00 02: 00是高位 02是低位。这里就是表示0x0002的线圈位置
00 08: 00是高位 08是低位。这里读0x0008位
针对这个req,对应做出res
解析res: 00 01 00 00 00 04 01 01 01 01
res格式:MBAP 功能码 数据长度 数据(一个地址的数据为1位)(共12字节)
对应下图:
前面基本一样,长度变成04.然后主要看数据。
数据01 01: 数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF
练习题2:
将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF
req格式:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)。
如:将地址为0x0003的线圈设为ON
00 01 00 00 00 06 01 05 00 03 FF 00
二、Modbus Poll/Slave 模拟器使用
poll和slave概述
官网地址tools
poll:是非常流行的 Modbus 主站模拟器,用于测试和调试您的从站设备。支持 Modbus RTU/ASCII 和 Modbus TCP/IP(来自官网翻译)
slave:是一个从站模拟器,用于模拟 32 个从设备/地址区域。OLE 自动化支持,可轻松连接到 Excel 电子表格。
下载安装:首先我们需要下载这2个软件,官网即可下载。下载安装都很简单,软件属于收费软件。如果有条件请支持正版。因为我只是学习下,注册码可以移步:
(538条消息) Modbus模拟器亲测可用-其它文档类资源-CSDN文库
这里安装好会就会看见这2个图标了。
主从模拟器有了以后,这里我们还需要下载一个工具。
Virtual Serial Port Driver虚拟com端口工具,不下载后面玩不了,会给报错说端口没有定义的。
这个工具有个虚拟com端口的。软件使用也是傻瓜教程,直接add。
添加好虚拟端口以后。win10可以点击此电脑-属性-设备管理器
打开软件之后主界面如下,出现红色No connection说明此时没有连接任何从设备。上面一行字代表当前通讯状态统计,Tx 代表发送帧数,Err代表错误帧,ID表示从站的ID号,F代表功能码,SR代表轮询周期,右下角显示IP地址和端口号。
点击Connection->Connect… 弹出注册码输入框,可以输入注册码,没有的话点击Regster later可以试用30天。
输入完注册码后,弹出Connection配置。
支持5种连接形式:
1 串行: 通过串行线路。RS232或RS485。可以使用USB串行转换器。
2 TCP/IP:如果要与TCP/IP网络通信,选择TCP/IP。在这种情况下,从站ID与TCP/IP中使用的单元ID相同。 端口号默认为502。如果连接失败,则尝试是否可以在命令提示符下ping设备。如果ping命令失败,轮询也将失败。
3 UDP/IP: 如果要与UDP/IP网络通信,请选择UDP/IP。这与TCP/IP相同,但改用连接较少的UDP协议。
通过TCP/IP的RTU/ASCII: 这是通过TCP/IP网络而不是串行线路发送的RTU或ASCII消息。 通过UDP/IP的RTU/ASCII: 这是通过UDP/IP网络而不是串行线路发送的RTU或ASCII消息。 连接类型3-5不是http://www.modbus.org指定的标准,是为了一些特殊情况下的应用。
连接成功connection时界面如下(需要使用从站仿真器或者真实设备)。
模拟串口通讯-RTU
演示用的版本poll(),slave(7.3.0),选择串口后可以配置串口信息。
串口配置一般默认就好,除非有特殊的要求,Mode处可以选择RTU和 ASCII类型。右侧可以设置响应超时时间,和轮训间隔。对于轮训间隔,一般设置为20ms,如果将此值设置为小于20毫秒,则不能保证响应和新请求之间的3.5个字符的时间间隔。这是因为Windows进程调度为每10到20毫秒切换一次任务。 如果在串行RS485网络中轮询多个从站,则不应将该值设置为低于20ms。这是为了确保3.5个字符的时间间隔。 在TCP/IP网络中,小于20毫秒是可以的。
点击高级Advanced...可以看到高级设置,这里一般不用去管这里稍微介绍一下
RTS切换 :RTS切换指定如果字节可用于传输,则RTS线将为高。发送所有缓冲的字节后,RTS线将变为低电平。 如果你的232/485转换器带自动方向切换功能,则可以使用它来切换方向。 尽量,应避免使用RTS控制的RS232/RS485转换器。在非实时操作系统(例如Windows和Linux)下,很难确定关闭变送器的确切时间。如果关闭它,字符可能仍位于FIFO或UART的发送寄存器中,尚未发送出去,这会导致数据丢失,但如果关闭时间太晚,则从站的消息将被破坏,主站将无法识别该消息。
DSR :DSR指定是否监视DSR(数据集就绪)信号以进行输出流控制。如果此成员为TRUE并且DSR关闭,则输出将被挂起,直到再次发送DSR。
CTS :CTS指定是否监视CTS(清除发送)信号以进行输出流控制。如果启用此复选框且CTS已关闭,则输出将暂停,直到再次发送CTS。
DTR:DTR指定在打开端口时是启用还是禁用DTR。
删除回显 如果你用的设备或RS232/RS485转换器会回显刚刚发送的字符,则启用该功能自动删除回显。
配置slave从机。打开软件。第一个界面。id=1表示从机地址。F=03表示协议功能码。03就是读保持寄存器。
选择工具栏的setup-slave definition(快捷键F8)。这里代表的意思已标注。配置好以后点击ok
选择工具栏的setup-Connection-connect,出现如下界面,配置好后点击ok。这里参数比较多,说明下:
connection: Serial port 表示传输方式是串行端口
Serial setting: 设置刚刚的虚拟端口
9600 Baud 波特率
8data bits 数据位
Parity 校验位
stop bit 停止位
mode :rtu
这里就是设置串口参数:
配置好以后点击ok,就会出现如下界面:
至此,从机的配置我们做完了,接着我们操作poll(主机)。同样的打开poll,出现如下界面:
tx =0 发送0次命令
err =0错误次数0,
id = 从机ID,
f = 功能号03,
sr= 轮询间隔1000ms
选择工具栏的setup-slave definition(快捷键F8).这里就是设置要通讯的从机地址1,功能码。
寄存器地址数量和轮询时间。
选择工具栏的setup-Connection-connect。串口参数和传输模式得和从机一致。
端口是com1-com2。
点击ok以后。就会发现连接成功。
为了方便调试,我们可以查看通讯数据帧。选择工具栏中的Display-Communication。
可以显示出当前发送命令和接受的数据。图下图就是收发的数据帧。
这里的数据帧含义解析:
Rx表示接收的数据帧
Tx表示发送的数据帧
000089这样的6位表示序列号
随便看一条数据
Tx:000090-01 03 00 00 00 0A C5 CD
01 从机地址
03 功能码
00 00 00 0A 数据
C5 CD 校验
我们可以在slave中配置下寄存器的值,比如我给随便配置个值68。
点击ok,我们在看看poll的数据帧,就会读到。
以太网通讯-TCP
和串口配置类似,只是多了服务器(从机)IP配置,端口号,网络连接超时设置,还可以切换IPv4和IPv6网络协议。
参数设置
点击Setup->Read/Write Definiton...可以对监视窗口监视的内容进行设置
点击之后可以设置从站地址,选择功能码,如03是读保持寄存器值,Address处填写寄存器地址,这里要注意右侧有地址寻址方法 40011->10,Quantity填写要读的寄存器数目
View 部分用于设置显示的行数,Cell中的地址显示等信息。
可配置Modbus的功能码定义如下:
常见的功能码和地址对应表:
设置假名,你可以直接双击alias列对应的单元格填写一些方便记忆的名字。
选择Setup->Excel Log ...可以设置Excel log,以方便数据处理。
选择Setup->Log … 可以设置Log的存储细节,存储速率,分割符,错误记录形式等。
测试功能:
Modbus poll 提供方便的测试辅助功能在Function菜单下,可以直接选择相应的功能发送命令给从机。
Modbus Poll还提供了文本发送调试工能,点击Functions->Test Center...进入测试中心,编辑完了命令之后可以直接点击Send发送。
显示设置
默认情况下Modbus Poll以Signed形式显示数据,这可以根据需要需要 点击Display菜单可以根据需要修改每个单元格的显示格式。
选择Communication...可以看到通信帧信息。
Modbus poll还提供了一个实时绘图页面来帮助用户观察数据接收情况,一般情况下不需要,调试时直接观察通信帧一般就够了。
Mobus Slave模拟从站(服务器),辅助主站开发调试。
打开Modbus Slave可以看到主界面。
图中ID为站号,F为响应主机的功能码。
在和主机进行连接之前先对连接进行设置点击Connection->Connection Setup,这里我选择了TCP/IP协议,串口协议类似。
对从机进行配置点击 Slave Definition...,设置好了点击OK。
然后对仿真界面进行一些设置,可以在Alias列填写容易识别的名字,双击右侧单元格会弹出寄存器编辑窗口,可以填写你需要的值,勾选Auto increment可以另每个单元自动增长。
配置好了Slave仿真器后,可以点击connection,然后利用主机连接,开始仿真调试。