[西门子] Modbus通信(一)

[复制链接]
查看139 | 回复0 | 2024-7-10 19:42:46 | 显示全部楼层 |阅读模式
>


1、什么是Modbus协议


Modbus是20世纪70年代由Modicon(现为施耐德电气公司的一个品牌)为了配合其PLC通信使用,开发的通过串行总线在电子设备之间发送信息的方式。Modbus协议是标准开放,可以免费放心使用的协议,不需要交纳许可证费,也不会侵犯知识产权。Modbus的帧格式简单、紧凑,通俗易懂。用户使用容易,厂商开发简单。最常用Modbus协议是Modbus ASCII、 Modbus RTU、Modbus TCP。

Modbus协议在通信线上使用主从应答式连接,属于半双工通信,在通讯线上主站通过地址码寻址到终端设备(从站),然后终端设备(从站)发出应答以相反的方向传输给主站。在实际使用中如果某终端设备(从站)掉线后(如故障或关机),主站Master端可以诊断出来,当故障修复后,网络又可以自动接通。因此,Modbus协议的可靠性较好。


在一个Modbus网络中同一时刻只有一个节点是主站,其他使用Modbus协议参与通信的节点是从站节点,从站节点的最大编号为247。每一个从站都有一个唯一的地址。Modbus协议只允许主站和终端设备之间通信,不允许终端设备之间相互的数据交换。



从站在没有收到主站的请求时,不会主动给主站发送数据,从站之间也不会进行通信。主机发送,从机应答,主机不发送,总线上就没有数据通信。



Modbus通信没有处理数据繁忙机制判断,主机给从机发送命令, 从机没有收到或者正在处理其他东西,这时就不能响应主机,因为modbus总线只是传输数据,没有其他仲裁机制,所以需要通过软件的方式来判断是否正常接收。




2、Modbus协议—通信传输介质


Modbus支持在RS232、RS422、RS485、双绞线(网线)、光纤、无线电等介质上传输。数据以位1和0的序列发送。每个位都作为电压信号发送。



RS232传输抗干扰性差且只能点到点,而RS485传输抗干扰相对强。RS485有两线制和四线制,四线制只能实现点对点的通信方式,现很少采用。两线制方式为总线式拓朴结构,在同一总线段上最多可以挂32个结点(从站)。连接RS485通信链路时一般只用一对双绞线将各个接口的“A”、“B”端并联连接起来。常常忽略了信号地的连接,这种连接方式在多数场合是可以正常工作的,因为RS485接口采用差分方式传输信号,不需要相对于某个参照点来检测信号,系统只需检测两线之间的电位差就可以。但是却有可能存在共模干扰问题,因为收发器有一定的共模电压范围,RS-485收发器共模电压范围为-7到+12V。关于什么是共模干扰可以参考《共模干扰和差模干扰》一文。



3、Modbus协议—单播模式和广播模式


Modbus通信主要包含单播模式和广播模式两种形式。单播模式时,主站给指定地址的从站发送信息,此模式下,一个Modbus事务包含两个报文,一个来自主站的请求,一个来自从站的应答。从站接收主站请求处理完成后,会回送主站一个应答数据帧,以表示读取或写入数据成功。


广播模式时,主站向所有的从站发送请求,当主站发送的地址码为0时,代表广播请求,所有的从站都需要接受处理,但不需要向主站返回报文。



4、Modbus协议—通信格式


在Modbus网络上的所有设备都必须选择相同的传输模式和串口通信格式。通讯格式是为了规范发送方与接收方的传输信息规则一致,如果双方通信格式不一样,例如,接收方设置的波特率是10(一秒只接收十个)位,而发送方的波特率是20(一秒发送二十个)位,那么发送方一秒钟发送20个字符时,接收方就不可能都收到,只能接收到10个,造成通信信息出错。


通信格式:波特率,校验方式,数据位,停止位。如通讯格式是9600,E,8,1


波特率:也就是通讯速率,表示一秒钟传送多少个二进制位。例如波特率为9600,即一秒种可以传送9600个二进制位数。


校验方式:奇校验/偶校验/无校验,用来判断传输过程中是否有错误。通过判断一个字符(比如八个位或是七个位组成的一个字符)传输是否有错误。校验方式并不能完全识别数据传输中是否有错,比如偶校验时,在检验发送的八个11111111数据位时,如果到达接收方,由于信号干扰而变成了10111101,1的个数虽然还是偶数,但接收方就判断不出来传送过来的的字符已经是错误的了。但如果把双方校验方式设定不一致,就没有一个统一的标准认定传输是否有错误。


数据位:定义传输一个字符由几个位组成(7位或者8位二进制),计算机的基本单位是“位”,其值非“0”即“1”,例如传送十六进制数据“A”时,定义通讯格式为八位数据位,其传送的数据可能就是00001010。当接收方数据位设定为七位,即表示接收方接收到七个二进制位就认为是一个字符,而实际发送方设定的是八位,那么接收方认定的字符与发送方发送的字符就不一样了。


停止位:用来判断某个字符是否传输结束,以便开始接收下一个字符。



通信规范中通信格式一致是为了保证接收方正确地接收发送方传输来的每一个字符,而检验方式并不能完全保证正确,还需要靠通信规范中的其他校验和计算来验证整体传输数据的正确性。




5、Modbus协议—信息数据帧


信息帧的格式都基本相同:地址域、功能码、数据区和错误校验码。



地址域

地址域在数据帧的开始部分,由一个字节组成,取值在0到255之间,地址域由用户分配从站的地址,仅仅被主站寻址到的从站会响应包含该地址的通信请求。每个终端设备的地址必须是唯一的。


功能码功能码告诉从站需要执行什么功能。作为从站应答响应,从站返回的功能码与主站发送来的功能码一样,表明从站已响应主站进行操作。如果从站发送的功能码的最高位为1,则表明从站没有响应操作或发送出错。
数据域假设功能码告诉从站设备需要读取其一个寄存器时,数据域则指明了从哪个寄存器地址开始读取及读取多少个数据。也就是通信之间需要的数据。

错误校验有时由于电气噪声和其它干扰,一组数据从一个设备传输到另一个设备时可能会发生改变,错误校验能保证主站或者从站设备不响应传输过程中发生改变的数据,提高了系统的安全性和效率。
当数据帧到达从站设备时,通过一个简单的“端口”进入被寻址的从站设备,该从站设备去掉数据帧的“信封”(数据头),读取数据,如果没有错误,就执行数据所请求的任务,然后将生成的数据加入到取得的“信封”中,把数据帧返回给发送者。返回的响应数据中包含了从站设备地址、被执行了的命令功能、执行命令生成的被请求数据和一个校验码。发生任何错误从站都不会成功的响应,或者返回一个错误指示帧。
一个报文就是一帧数据,一个数据帧就一个报文。

6、Modbus协议—功能码

​Modbus支持的功能码:

功能码功能说明
0x01读取输出线圈
0x02读取输入线圈
0x03读取保持寄存器
0x04读取输入寄存器
0x05写入单个线圈
0x06写入单个寄存器
0x0F(15)
写入多个线圈
0x10(16)
写入多个寄存器

​在Modbus消息帧的功能码中较常使用的是01、02、03、04、06和16功能码,可实现对从站数字量和寄存器数值的读写操作。可以将线圈视为PLC的输出,将离散输入视为 PLC的输入,保持寄存器类似于PLC存储器(可读可写),输入寄存器属于只读不可写。它们是16位字,输入寄存器也是16位字。

功能码01(读取输出线圈逻辑状态)
读取线圈状态是指读取从站中的线圈寄存器的位状态,可以是单个寄存器,或者多个连续的寄存器,可以理解成读取PLC的输出位。读取采用起始地址+线圈数量的方式,1号线圈的地址为0,2号线圈的地址为1,以此类推,假设要读取1~10号线圈的值,其寄存器地址范围为0~9。

主站发送:[设备地址] [命令号01] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]  

主站发送:[11][01][00][13][00][25][CRC低][CRC高]  设备地址[11]:一个485总线上可以接多个设备,此处的设备地址表示主站想和哪一个从站设备通信。例子中是想和17号地址设备。

功能码[01]:读取数字量输出线圈状态的功能码固定为01。

起始地址高8位[00]、低8位[13]:表示要读取的开关量的起始地址0013H。十六进制13转化成十进制数为19,所以读取开关量的起始地址为19。
寄存器数高8位[00]、低8位[25]:表示从起始地址开始读多少个开关量。十六进制25转化成十进制数为37,所以读取开关量起始地址为20开始(20号线圈的起始地址是19),读取37个开关量。

从站返回:[11][01][05][CD][6B][B2][0E][1B][CRC高] [CRC低]  
设备地址[11]和命令号[01]和上面相同。

返回的字节个数[05]:表示返回数据的字节个数,也就是数据1,2...n中的n的值。 这里例子返回了5个字节数据。

数据1...n([CD][6B][B2][0E][1B]):是从站响应返回给主站要读取的开关量数据。由于每一个数据是一个8位二进制数,每一位为0表示对应的开关断开,为1表示闭合。比如例子中,十六进制CD用二进制表达为1100 1101。也就是线圈的开关闭合状态,20闭合,21断开,22闭合,23闭合,24断开,25断开,26闭合,27闭合...如果询问的开关量不是8的整倍数,例如最后一个字节1B(0001 1011)那么最后一个字节的高位部分无意义,置为0。

功能码02(读取输入状态)例如利用功能码02读取三菱PLC的X元件或者西门子PLC的I元件的输入状态等。
主站发送:
读取1号从站输入线圈,起始地址为0xC4=196,对应地址为10197(起始地址为0x0000时为10001),线圈数量为0x1D=29,即读取1号从站输入线圈,地址从10197-10225,共29个线圈的状态值。
从站返回:


返回1号从站输入线圈10197-10225,共29个线圈的状态值,返回字节数为4个,分别为CD 6B B2 05。CD=1100 1101 对应 10197-10204
6B=0110 1011 对应 10205-10212
B2=1011 0010 对应 10213-10220
05=0000 0101 对应 10221-10225

功能码03(读取保持寄存器)读取Modbus从站中的保持寄存器的数据,读保持寄存器不分读单个和读多个,当需要读单个保持寄存器时,也是使用0x03功能码指令,指定读取数量为1。

主站发送:[设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的高8位] [CRC校验的低8位]

主站发送:[11][03][00][6B][00][03][CRC高][CRC低]  设备地址[11]: 一个485总线上可以接多个设备,此处的设备地址表示主站想和哪一个从站设备通信。例子中是想和17号地址设备(十六进制11转换成十进制17)。

命令号[03]:读保持寄存器命令号固定为03。

起始地址高8位[00]、低8位[6B]:读取的保持寄存器的起始地址为006BH,也就是十进制107。
寄存器数高8位00、低8位03:从指定的起始地址开始读多少个模拟量数目指定。0003H也就是十进制3,表示读取3个保持寄存器中的数值。
从站返回:[设备地址] [命令号03] [返回的字节个数][数据1][数据2]...[数据n] [CRC校验的高8位] [CRC校验的低8位]  

返回信息:[11][03][06][02][2B][00][00][00][64][CRC高] [CRC低]

设备地址[11]和命令号[03]意思同上。

返回的字节个数[06]:表示返回数据的字节个数,也就是数据1,2...n中的n的值。例子中读取了3个保持寄存器数据,因为一个保持寄存器需要2个字节,所以6个字节是3个模拟量数据。
数据1...n[02][2B][00][00][00][64]:其中[数据1][数据2]分别是第1个模拟量的高8位和低8位,[数据3][数据4]是第2个模拟量的高8位和低8位,以此类推。所以三个保持寄存器读取到的数据为[022B]、[0000]、[0064],换算成十进制数据为555,0,100。 返回信息中一个保持寄存器返回两个字节。
主站发送:
读取1号从站保持寄存器,起始地址为0x6B=107,对应地址为40108,寄存器数量为0x02=2,即读取1号从站保持寄存器,地址从40108-40109,共2个寄存器的数值。
从站返回:

返回1号从站保持寄存器40108-40109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06。
40108对应数值为0x022B。
40109对应数值为0x0106。

功能码04(读取输入寄存器)输入寄存器为只读不可写类型。
主站发送:
读取1号从站输入寄存器,起始地址为0x6B=107,对应地址为30108,寄存器数量为0x02=2,即读取1号从站2个输入寄存器,地址从30108-30109,共2个寄存器的数值。
​从站返回:
返回1号从站输入寄存器30108-30109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06。
30108对应数值为0x022B,
30109对应数值为0x0106。

功能码05码(写入单线圈)主站发送:[设备地址] [命令号05] [需写入的寄存器地址高8位] [低8位] [写入数据的高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]  
主站发送:[11][05][00][AC][FF][00][CRC高][CRC低]  
设备地址[11]意思同上。

功能号[05]:写数字量线圈的功能号固定为05。

需写入的寄存器地址高8位[00],低8位[AC]:表明了需要写入的开关量地址为00ACH。
写入数据高8位[FF],低8位[00]:表明需要写入开关量的状态。[FF][00]表示置位,[00][00]表示断开。
主站发送:
写入1号从站单个线圈的值,线圈地址为0x00AC=172,对应地址为00173,断通标志0xFF00表示置位,0x0000表示复位,即置位1号从站输出线圈00173。
从站返回:

写入单输出线圈原样报文返回。
功能码06(写入单个保持寄存器)此命令一条只能将数据写入一个寄存器。
主站发送:[设备地址] [命令号06] [需写入的寄存器地址高8位] [低8位] [写入的数据高8位] [低8位] [CRC校验的高8位] [CRC校验的低8位]  
主站发送:[11][06][00][01][00][03] [CRC高] [CRC低]  
设备地址[11]:意思同上。
命令号[06]:写单个保持寄存器。
需写入的寄存器地址高8位[00],低8位[01]:表明了需要写入的寄存器的地址。
写入的数据高8位[00],低8位[03]:写入指定地址寄存器数据的指定。比如例子中就把1号寄存器的值设为3。
主站发送:

写入1号从站单个保持寄存器的值,寄存器地址为0x0087=135,对应地址为40136,写入值为0x039E,即写入1号从站保持寄存器地址40136值为0x039E。从站返回:
写入单保持寄存器原报文返回。

功能码16(写入多个保持寄存器)
主站发送:[设备地址] [命令号16] [需写入的寄存器地址高8位] [低8位] [数据数量高8位] [数据数量低8位] [写入的数据高8位] [低8位][……][……] [CRC校验的高8位] [CRC校验的低8位]
主站发送:[11][16][00][01][00][01][00][05] [CRC高] [CRC低]  

设备地址[11]:意义同上。
命令号[16]:写多个连续的保持寄存器命令号固定为16。
需写入寄存器的地址高8位[00],低8位[01]:表明需要写入寄存器的地址指定。
需要写入数据个数的高8位[00],低8位[01]:表明了需要写入数据的数量。

写入的数据高8位[00],低8位[05]:指定需要写入寄存器的数据。比如例子中就把1号寄存器的值设为5。
从站返回:[设备地址] [命令号16] [需写入的寄存器地址高8位] [低8位] [数据数量高8位] [数据数量低8位] [CRC校验的高8位] [CRC校验的低8位],
从站返回:[11][16][00][01][00][01] [CRC高] [CRC低]
设备地址[11]:意义同上。
命令号[16]:写多个连续的保持寄存器命令号固定为16。
写入寄存器的地址高8位[00],低8位[01]:返回写入寄存器的地址指定。
需要写入数据个数的高8位[00],低8位[01]:返回了写入数据的数量。

主站发送:
写入1号从站多个寄存器的值,寄存器地址为0x0087=135,起始地址为40136,寄存器数量为0x02=2,写入两个连续的寄存器地址,所以结束地址为40137,写入值为0x0105和0x0A10,即写入1号从站寄存器40136=0x0105,40137=0x0A10。
从站返回:
写入多个保持寄存器返回报文在原主站发送报文基础上除去字节数及具体字节后返回。



7、Modbus协议—数据类型

Modbus协议的数据模型定义了以下四种可访问的数据:

数据区块
数据类型
访问类型
线圈
布尔
读/写
离散量输入

布尔
只读
输入寄存器
无符号2字节整型
只读
保持寄存器
无符号2字节整型
读/写


线圈:开关输出信号,主要用来写入单个位的数据。输出线圈可读可写。例如三菱PLC中的Y元件或者西门子PLC中的Q元件。


离散量输入:主要用来读取单个位的数据,如IO的状态。输入线圈只读。例如三菱PLC中的X元件或者西门子PLC中的I元件。



输入寄存器:主要用来读取16位,也就是两个字节的数据。输入寄存器只读。例如模拟量输入AI信号。


保持寄存器:主要用来写入16位的数据。保持寄存器可读可写。例如三菱PLC中的D元件或者西门子PLC中的V元件以及模拟量输出AO信号。



8、Modbus协议—地址模型

在使用Modbus协议时,经常会遇到40001、30001,10001之类的地址,这些数字其实是Modbus协议的数据模型和地址模型。



存储区名称
存储区代号
输入线圈
1区
输出线圈
0区
输入寄存器3区
保持寄存器
4区


对于任意一个存储区,索引都是从0开始的,但是对应的具体模型地址,与存储区相关,例如:


输出线圈,0对应00001。
线圈模型地址范围000001~065536


输入线圈,0对应10001。
输入模型地址范围100001~165536


输入寄存器,0对应30001。
输入寄存器地址范围300001~365536


保持寄存器,0对应40001。
保持寄存器地址范围400001~465536


由于65536是比较大的数值,实际应用一般不需要这么大的存储区,因此设备厂家普遍采用的是10000以内的地址范围。即:


线圈地址范围:00001~09999


离散量输入地址范围:10001~19999


输入寄存器地址范围:30001~39999


保持寄存器地址范围:40001~49999

​例如常见到的寄存器地址40001/400001,最前面的4表明它是一个保持寄存器,后面的0001/00001都是指第一个保持存储器,并且它对应的实际物理地址是0。寄存器30004表明它是输入寄存器,地址是3。寄存器10008表明它是离散量输入,地址是7。


MODBUS做为一种标准协议,应用于各种PLC,控制器,仪表。这些仪表或是控制器应用中,元件的通讯地址肯定是不一样的,各个索引地址代表的实际用途不一定相同,在编程时还需要参考相关设备的说明书查看其地址索引用途。



9、Modbus RTU通信解析
Modbus RTU数据帧,帧长度最大为256个字节。
​从站地址:1字节(范围0-247)
功能码:1字节
数据块:0-252字节
CRC校验值:2字节(低8位在前)

注意:数据帧内的字节为十六进制数据表示。

Modbus RTU通信时,消息中的每个字节(8个二进制位)按照原值传送,不做处理,如数值“63H”,RTU将直接发送01100011。
Modbus-RTU要求两个RTU报文帧之间的隔要大于3.5个字节时间,且每个报文帧内字节间隔小于1.5个字节时间,否则会认为接收不完整。

​3.5*11(或10)=39个位(35个位),传3.5个字符需要的时间是:39/9600=4毫秒。数据位(8位)+起始位(0)+奇偶校验位(1)+停止位(2)。要保证发送字符串的连续性,中间停顿时间要超过4毫秒,接收方就认为已经发送完了这组消息,开始处理。如果发送的太连续,下一组消息与上一组消息之间的间隔时间没超过4毫秒,接收方就认为这些字符是一组消息,按一组消息去处理。所以,发送结束一组命令后,必须间隔4毫秒才能发送下一组命令. 这就是至少3.5个字符传输时间的停顿间隔时间标定消息的开始的意义。


Modbus-RTU采用循环冗余校验CRC算法对报文帧全部数据进行计算,得到的校验值附加在报文帧末尾。


8、Modbus ASCII通信解析


Modbus ASCII传输模式中,每个字节均以ASCII编码,实际报文中1个字节会以两个ASCII字符发送,因此,这种模式比Modbus RTU模式效率要低。


起始符+ 设备地址 + 功能代码 +数据 + 校验 + 结束符


ASCII模式增加了帧起始(“:”)和帧结束标志(回车&换行)。
起始符: 接收一串字符,需要知道这串字符从哪个地方开始,这就是起始符存在的作用,接收方不管以前收到多少个字符,当接收到起始符时,以前的接收到的字符就不再理它了,从起始符开始分析以后的字符。MODBUS的ASCII方式起始符是一个冒号 “:”(0x3A)。
结束符:接收到一串字符,需要知道在哪个地方结束,这就是结束符的作用,接收方不管以后还会收到多少个字符。当接收到结束符时,以后再接收的字符就算是下一轮的信息,从起始符到结束符之间的字符就是它要分析的字符。MODBUS的ASCII方式结束符是Chr$(13) + Chr$(10)。

由于报文数据每个字节在ASCII模式下需要2个字符进行编码,例如报文数据0x5B = "5" + "B" = 0X35 + 0X42。为了保证ASCII模式和RTU模式在应用级兼容,ASCII模式数据块最大长度为252x2,所以可以计算出报文帧最大长度为1+2+2+2x252+2+2=513个字符,报文帧内的字符间隔时间可以达1秒钟。



Modbus-ASCII校验方法采用纵向冗余校验LRC算法,校验内容不包括帧起始和帧结束字符。


CR(0x0D)指回车,LF(0x0A)指换行。0x0D的ASC码是13,指的是“回车” 。0x0A的ASC码是10,指的是“换行” 。



9、Modbus TCP通信解析

Modbus TCP和RTU协议非常类似,将RTU协议最后两个字节的校验码去掉,然后在RTU协议的开始加上5个0和一个6并通过TCP/IP网络协议发送出去即可。Modbus TCP占用502端口号。主机是客户端,从机是服务器端。


MODBUS TCP信息帧包含了报文头、功能码、数据3部分内容,其中报文头由四部分构成,共7个字节,与MODBUS RTU相比,MODBUS TCP中不存在CRC校验,校验部分由TCP/IP协议和以太网的链路层完成。


传输标识:标志Modbus询问/应答的传输,一般默认是00 00


协议标识:00 00 表示Modbus协议


数据长度:从单元标识符以后的数据个数


单元标识符:相当于MODBUS RTU通信中的从站站号


功能码:用于读取设备数据或者往设备中写入数据。


数据:根据读取数据长度的不同。由n个字节组成。


读取输出线圈
读取服务器1号从站输出线圈,起始地址为0x13=19,对应地址为00020,线圈数量为0x1B=27,即读取1号从站输出线圈,地址从00020-00046,共27个线圈的状态值。长度0x0006表示从单元标识符开始有6个数据长度(下同)。


返回报文格式:
返回服务器1号从站输出线圈00020-00046,共27个线圈的状态值,返回字节数为4个,分别为CD 6B B2 05。


CD=1100 1101 对应 00020-00027
6B=0110 1011 对应 00028-00035
B2=1011 0010 对应 00036-00043
05=0000 0101 对应 00044-00046
​读取输入线圈
读取服务器1号从站输入线圈,起始地址为0xC4=196,对应地址为10197,线圈数量为0x1D=29,即读取1号从站输入线圈,地址从10197-10225,共29个线圈的状态值。


返回报文格式:

返回服务器1号从站输入线圈10197-10225,共29个线圈的状态值,返回字节数为4个,分别为CD 6B B2 05。
CD=1100 1101 对应 10197-10204
6B=0110 1011 对应 10205-10212
B2=1011 0010 对应 10213-10220
05=0000 0101 对应 10221-10225
​读取保持寄存器
读取服务器1号从站保持寄存器,起始地址为0x6B=107,对应地址为40108,寄存器数量为0x02=2,即读取1号从站保持寄存器,地址从40108-40109,共2个寄存器的数值。


返回报文格式:
返回服务器1号从站保持寄存器40108-40109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06,40108对应数值为0x022B,40109对应数值为0x0106。
​读取输入寄存器
读取服务器1号从站输入寄存器,起始地址为0x6B=107,对应地址为30108,寄存器数量为0x02=2,即读取1号从站保持寄存器,地址从30108-30109,共2个寄存器的数值。


返回报文格式:

返回服务器1号从站输入寄存器30108-30109,共2个寄存器的数值,返回字节数为4个,分别为02 2B 01 06,30108对应数值为0x022B,30109对应数值为0x0106。
​写入单个线圈状态
写入服务器1号从站单个线圈的值,线圈地址为0x00AC=172,对应地址为00173,断通标志0xFF00表示置位,0x000表示复位,即置位1号从站输出线圈00173。


返回报文格式:
返回报文含义:预置单输出线圈原报文返回。
​写入单个保持寄存器值
写入服务器1号从站单个保持寄存器的值,寄存器地址为0x0087=135,对应地址为40136,写入值为0x039E,即预置1号从站保持寄存器40136值为0x039E。


返回报文格式:
写入单保持寄存器原报文返回。
​写多个输出线圈
写入服务器1号从站多个线圈的值,线圈地址为0x0013=19,对应地址为00020,线圈数为0x0A=10,写入值为0xCD00,即预置1号从站线圈
00020-00027=0xCD=1100 1101

00028-00029=0x00=0000 0000



返回报文格式:
写入多输出线圈返回报文是在原报文基础上除去字节数及具体字节后返回。
​写多个保持寄存器值
写入服务器1号从站多个寄存器的值,寄存器地址为0x0087=135,起始地址为40136,寄存器数量为0x02=2,结束地址为40137,写入值为0x0105和0x0A10,即预置1号从站寄存器40136=0x0105,40137=0x0A10。


返回报文格式:
写入多保持寄存器返回报文是在原报文基础上除去字节数及具体字节后返回。



10、Modbus RTU、Modbus ASCII、Modbus TCP对比小结

一般来说,通信数据量少且主要是文本通信时采用Modbus ASCII,通信数据量大而且是二进制数时,多采用Modbus RTU。而Modbus TCP使用以太网网络通信,其数据传输速度远高于使用串行链路的RTU。且使用Modbus协议的设备必须要有RTU协议,这是Modbus协议上规定的,且默认模式必须是RTU,ASCII作为选项。(也就是说,一般的设备只有RTU这个协议,ASCII一般很少)。


Modbus RTU:串行链路上的二进制文件。


Modbus ASCII:基于文本的串行链路,ASCII是美国标准信息交换代码。


Modbus TCP:通过 TCP/IP传输二进制文件。


当以Modbus RTU模式通信时,消息中的每个字节(8个二进制位)按照原值传送,不做处理,如数值“63H”,RTU将直接发送01100011。



当以Modbus ASCII模式通信时,消息中的每个字节(8个二进制位)作为2个ASCII字符进行传输处理,例如数值“63H”用ASCII模式时,发送两个字节,即ASCII“6"查表可知对应十六进制36(0110110)和ASCII”3“查表可知对应十六进制33(0110011),ASCII字符占用的位数有7位和8位,国际通用7位为多。

ASCII码效率低,那数据发送量大为啥还采用这种方式呢?例如要发送数据0x03,采用RTU方式(16进制发送),计算机中端设备接收到0x03后是不可以显示的,就是不能把0x03打印出来。因为可见字符的ASCII码是从32—126,不是这个范围以外的显示屏上都看不到,会出现乱码,如果是串口助手的话就会显示□□□□。如果采用ASCII方式(文本模式发送),就不会出现不可显示和乱码的情况,因为文本模式发送0x03,就是发送ASCII码0和ASCII码3,也就是0x30和0x33,是可以正常显示在计算机中端的。所以现在使用ASCII效率比较低的方式发送,只是为了方便调试显示而已。


​ASCII模式使用的字符虽是RTU模式的两倍,但ASCII数据的译码和处理更为容易一些,此外,用RTU模式时,报文字符必须以连续数据流的形式传送。ASCII模式,字符之间可产生长达1s的间隔,以适应速度较慢的机器。ASCII模式的主要优点是字符发送的时间间隔可达到1秒而不产生错误。
Modbus ASCII和RTU,使用时只能选用其中一种,混合使用是不允许的。

11、数据校验CRC和LRC


错误校验冗余循环码(CRC)包含2个字节,即16位二进制。CRC码由发送设备计算,放置于发送信息的尾部。接收信息的设备再重新计算接收到信息的 CRC码,比较计算得到的CRC码是否与接收到的相符,如果两者不相符,则表明出错。校验字符是要求两个字符,如果计算结果超过两个字符,则取后两位!



CRC校验(Modbus RTU)


1、 预置1个16位的寄存器为十六进制FFFF(即全为1),称此寄存器为CRC寄存器。


2、 把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器。


3、 把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查移出位。


4、 如果移出位为0:重复第3步(再次右移一位); 如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或。


5、 重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理。


6、 重复步骤2到步骤5,进行通讯信息帧下一个字节的处理。

7、 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器;

8、 最后得到的CRC寄存器的高、低字节进行交换即为:CRC码。


例如计算H05的CRC码:
HFFFF:1111 1111 1111 1111
  H05  :0000 0000 0000 0101
  X0R  :1111 1111 1111 1010
--------------------------
    N1-->  0111 1111 1111 1101
--------------------------
    N2-->  0011 1111 1111 1110
    A001: 1010 0000 0000 0001
    XOR : 1001 1111 1111 1111
--------------------------
     N3-->  0100 1111 1111 1111
     A001: 1010 0000 0000 0001
     XOR : 1110 1111 1111 1110
--------------------------
      N4-->  0111 0111 1111 1111
--------------------------
      N5-->  0011 1011 1111 1111
      A001: 1010 0000 0000 0001
      XOR : 1001 1011 1111 1110
--------------------------
      N6-->  0100 1101 1111 1111
--------------------------
      N7-->  0010 0110 1111 1111
      A001: 1010 0000 0000 0001
      XOR : 1000 0110 1111 1110
--------------------------
      N8-->  0100 0011 0111 1111


将上述运算结果H437F交换高低字节得到CRC校验码为:H7F43



LRC校验(Modbus ASCLL)
对应ASCII模式的LRC校验相对于CRC校验计算要简单很多。


1、在Modbus ASCII模式中,去掉开始符和结束符,将要发送的数据进行求和。

2、将求和得到的值转化成二进制并按位取反。例如求和值8转换为二进制为00001000,然后按位取反11110111,长度8位,大于8位的数据取低8位。


3、将取反后的数据加一得到LRC校验码。例如将上述取反后的数值11110111转换为16进制为:F7,然后再加1为F8



将地址码+功能码+数据求和计算:

0X01+0X05+0X00+0X0F+0XFF+0X00=H114

H114:0000  0001 0001  0100
取反: 1111  1110 1110  1011
取反结果:FEEB
取低字节:EB
对取的的一字节加1:EC


将十六进制EC进行ASCII编码得出的结果为45、43。


了解了运算原理,在科学技术不断提高的今天,可以充分利用不同的计算器来节约我们的设计编程时间。



1、浏览器中搜索CRC计算器在线
在计算器的地址栏复制输入:
01 05 00AC FF00

2、浏览器中搜索LRC计算器在线


H01+H06+H20+H00+H00+H12=H39
H39:0011 1001
取反:1100  0110
加一:1100 0111(HC7)
通过电脑工具计算如下:


所以上述Modbus ASCLL通信的数据帧的LRC校验为C7。




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则