您的位置:首页 > 理论基础 > 计算机网络

Modbus 网络通讯协议

2014-05-15 16:35 260 查看
开发人员编码注意:

在使用Modbus通讯协议,一定要编写Modbus通讯协议和CRC校验。

在远距离数据通信中,为确保高效而无差错地传送数据,防止数据被破坏或者篡改,必须对数据进行CRC校验。

尽管CRC在错误检测中非常有用,但CRC并不能可靠地校验数据完整性,这是因为CRC多项式是线性结构,可以非常容易地通过改变数据方式达到CRC碰撞,这里给一个更加通俗的解释,假设一串带有CRC校验的代码在传输中,如果连续出现差错,当出错次数达到一定次数时,那么几乎可以肯定会出现一次碰撞(值不对但CRC结果正确),但随着CRC数据位增加,碰撞几率会显著降低,比如CRC32比CRC16具有更可靠的验证性,CRC64又会比CRC32更可靠,当然这都是按照ITU规范标准条件下。)

如果你发送指定的指令,其中的CRC校验直接使用提供的CRC低位字节表和CRC高位字节表中的字节数据,那就不需要编写CRC校验。

如今在工业现场总线中,常采用串口实现一些要求不太高的通讯控制,modbus协议更是最常用的传输数据的协议,而在整个通讯过程中,CRC校验码计算是一个注意点。
Moldbus没有规定物理层用什么接口实现。只要半双工以上就可以。所以232口没问题。
如果你的PLC用的是Modbus,那你一定要实现CRC校验。否则接收端如果收不到CRC校验包或者CRC校验包不对,就会认为收到的数据包错误,不做任何响应。


modbus通信协议是应用层协议(第七层),它目前可以用于3种通信网络:
1)用于串行口通信网络,传输模式为modbusRTU和modbusASCII;
2)用于以太网口通信网络,传输模式为modbusTCP;
3)用于高速链路网络,传输模式为modbusPLUS。

包括modbus协议在内,有很多种通信协议都可以用于现场总线。modbusPLUS就是一种现场总线,而modbusRTU/ASCII、modbusTCP只是低速的普通通信网络。
========================
通讯传送分为独立的信息头,和发送的编码数据


编码8位二进制
起始位1位
数据位8位
奇偶校验位1位(偶校验位)
停止位1位
错误校检CRC(冗余循环码)
初始结构=≥4字节的时间

(传送的数据帧结构组成如下)


地址码=1字节
功能码=1字节
数据区=N字节
错误校检=16位CRC码
结束结构=≥4字节的时间

地址码:地址码为通讯传送的第一个字节。这个字节表明由用户设定地址码的从机将接收由主机发送来的信息。并且每个从机都有具有唯一的地址码,并且响应回送均以各自的地址码开始。主机发送的地址码表明将发送到的从机地址,而从机发送的地址码表明回送的从机地址。地址码在温湿度传感器上电启动后,可以显示屏上看得到,且读取地址码发送的命令中必须跟该地址码一致。否则接收过来的响应会是错误的信号。
功能码:通讯传送的第二个字节。ModBus通讯规约定义功能号为1到127。本仪表只利用其中的一部分功能码。作为主机请求发送,通过功能码告诉从机执行什么动作。作为从机响应,从机发送的功能码与从主机发送来的功能码一样,并表明从机已响应主机进行操作。如果从机发送的功能码的最高位为1(比如功能码大与此同时127),则表明从机没有响应操作或发送出错。
数据区:数据区是根据不同的功能码而不同。数据区可以是实际数值、设置点、主机发送给从机或从机发送给主机的地址。
CRC码:二字节的错误检测码。


传输格式

(1)命令报文格式

读数据:

地址
功能码
数据起始地址高位
数据起始地址低位
数据个数高位
数据个数低位
CRC
16位校验
xx
04
00
00
00
02
xxxx低位在前
返回:

地址
功能码
字节长度
数据1输入
数据2输入

CRC
16位校验
xx
04
04
xx高位在前
xx高位在前
xx
xxxx低位在前
(2)、异常应答返回

非法功能:



从站地址
功能码
异常码
CRC16校验
xx
80H+原功能码
01
xxxx低位在前
非法数据地址:



从站地址
功能码
异常码
CRC16校验
xx
80H+原功能码
02
xxxx低位在前
非法数据值:



从站地址
功能码
异常码
CRC16校验
xx
80H+原功能码
03
xxxx低位在前
(3)、变送器地址设置:

命令报文格式:

命令代码高位

命令代码地位
地址数据
CRC
16位校验
FF
A5
xx
xxxx低位在前
返回:

命令代码高位

命令代码地位
地址数据
CRC
16位校验
FF
A5
xx
xxxx低位在前
//RTU协议CRC校验码的计算

//*pushMsg为需要校验的数组指针变量,usDataLen为需要校验的数据个数变量

voidCRC16(BYTE*pushMsg,unsignedshortusDataLen)
{
	BYTEuchCRCHi=0xFF;
	BYTEuchCRCLo=0xFF;

	unsignedintuIndex;
	while(usDataLen--)
	{
		uIndex=uchCRCHi^*pushMsg++;	//计算CRC
		uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
		uchCRCLo=auchCRCLo[uIndex];
	}

	*pushMsg++=uchCRCHi;	//校验数据高位在后
	*pushMsg=uchCRCLo;	//校验数据低位在前

}




地址为1时,读取温湿度值:(CRC校验低位在前)

上位机发送:01030002000265CB(读从数据起始地址为0000H开始的1个模拟量)

变送器返回:01030400B401EA3BBD
即显示屏上显示的温湿度数据:

T:17.9

H:49.0

读取地址码值(即获取设备的型号ID):(CRC校验低位在前)

上位机发送:00030000000185DB(读从数据起始地址为0000H开始的1个模拟量)

变送器返回:00030200,地址L,CRC_L,CRC_H

从机返回的温湿度数据分别用两个字节表示,高位在前,低位在后;
返回的数据范围-32768~32767,实际温湿度数据需要将返回值除以10;
例如:
返回湿度16进制数据:0x0311,对应10进制785,表示湿度为78.5%RH
返回温度16进制数据:0x00FF,对应10进制255,表示温度为25.5℃
返回温度16进制数据:0x8064,最高位为1表示附属对应10进制785,表示湿度为78.5%RH

为变送器设置新地址码,如“2”:(CRC校验低位在前)
上位机发送:FFA502BB61
变送器返回:FFA502BB61

如设置新地址码“6”:(CRC校验低位在前)
上位机发送:FFA506BAA2
变送器返回:FFA506BAA2

(若需要同时与多台设备Modbus协议通讯时,也可以自己去设置地址码)

Modbus网络通信其实就是串行通信,物理层和RS232/485等都是一样的,
二进制从做到右传输.一般来说,标准MODBUS是:1:地址码2:功能码3:数据区4:校验码(常用CRC校验)最多255位.它是一主多从,主机发出命令,只能是地址相对的从机回应,从机和从机之间无法通信.

========================

Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
当在一Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。
1、在Modbus网络上转输
标准的Modbus口是使用一RS-232C兼容串行接口,它定义了连接口的针脚、电缆、信号位、传输波特率、奇偶校验。控制器能直接或经由Modem组网。
控制器通信使用主—从技术,即仅一设备(主设备)能初始化传输(查询)。其它设备(从设备)根据主设备查询提供的数据作出相应反应。典型的主设备:主机和可编程仪表。典型的从设备:可编程控制器。



Modbus支持的功能码:


下表是Modbus支持的功能码:

功能码
名称
作用

01
读取线圈状态
取得一组逻辑线圈的当前状态(ON/OFF)

02
读取输入状态
取得一组开关输入的当前状态(ON/OFF)

03
读取保持寄存器
在一个或多个保持寄存器中取得当前的二进制值

04
读取输入寄存器
在一个或多个输入寄存器中取得当前的二进制值

05
强置单线圈
强置一个逻辑线圈的通断状态

06
预置单寄存器
把具体二进值装入一个保持寄存器

07
读取异常状态
取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定

08
回送诊断校验
把诊断校验报文送从机,以对通信处理进行评鉴

09
编程(只用于484)
使主机模拟编程器作用,修改PC从机逻辑

10
控询(只用于484)
可使主机与一台正在执行长程序任务从机通信,探询该从机是否已完成其操作任务,仅在含有功能码9的报文发送后,本功能码才发送

11
读取事件计数
可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时

12
读取通信事件记录
可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成,记录会给出有关错误

13
编程(184/384484584)
可使主机模拟编程器功能修改PC从机逻辑

14
探询(184/384484584)
可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送

15
强置多线圈
强置一串连续逻辑线圈的通断

16
预置多寄存器
把具体的二进制值装入一串连续的保持寄存器

17
报告从机标识
可使主机判断编址从机的类型及该从机运行指示灯的状态

18
(884和MICRO84)
可使主机模拟编程功能,修改PC状态逻辑

19
重置通信链路
发生非可修改错误后,是从机复位于已知状态,可重置顺序字节

20
读取通用参数(584L)
显示扩展存储器文件中的数据信息

21
写入通用参数(584L)
把通用参数写入扩展存储文件,或修改之

22~64
保留作扩展功能备用

65~72
保留以备用户功能所用
留作用户功能的扩展编码

73~119
非法功能

120~127
保留
留作内部作用

128~255
保留
用于异常应答

在这些功能码中较长使用的是1、2、3、4、5、6号功能码,使用它们即可实现对下位机的数字量和模拟量的读写操作。

1、读可读写数字量寄存器(线圈状态):

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

例:[11][01][00][13][00][25][CRC低][CRC高]

意义如下:

<1>设备地址:在一个485总线上可以挂接多个设备,此处的设备地址表示想和哪一个设备通讯。例子中为想和17号(十进制的17是十六进制的11)通讯。

<2>命令号01:读取数字量的命令号固定为01。

<3>起始地址高8位、低8位:表示想读取的开关量的起始地址(起始地址为0)。比如例子中的起始地址为19。

<4>寄存器数高8位、低8位:表示从起始地址开始读多少个开关量。例子中为37个开关量。

<5>CRC校验:是从开头一直校验到此之前。在此协议的最后再作介绍。此处需要注意,CRC校验在命令中的高低字节的顺序和其他的相反。

设备响应:[设备地址][命令号01][返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位][CRC校验的高8位]

例:[11][01][05][CD][6B][B2][0E][1B][CRC低][CRC高]

意义如下:

<1>设备地址和命令号和上面的相同。

<2>返回的字节个数:表示数据的字节个数,也就是数据1,2...n中的n的值。

<3>数据1...n:由于每一个数据是一个8位的数,所以每一个数据表示8个开关量的值,每一位为0表示对应的开关断开,为1表示闭合。比如例子中,表示20号(索引号为19)开关闭合,21号断开,22闭合,23闭合,24断开,25断开,26闭合,27闭合...如果询问的开关量不是8的整倍数,那么最后一个字节的高位部分无意义,置为0。

<4>CRC校验同上。

2、读只可读数字量寄存器(输入状态):

和读取线圈状态类似,只是第二个字节的命令号不再是1而是2。

3、写数字量(线圈状态):

计算机发送命令:[设备地址][命令号05][需下置的寄存器地址高8位][低8位][下置的数据高8位][低8位][CRC校验的低8位][CRC校验的高8位]

例:[11][05][00][AC][FF][00][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:写数字量的命令号固定为05。

<3>需下置的寄存器地址高8位,低8位:表明了需要下置的开关的地址。

<4>下置的数据高8位,低8位:表明需要下置的开关量的状态。例子中为把该开关闭合。注意,此处只可以是[FF][00]表示闭合[00][00]表示断开,其他数值非法。

<5>注意此命令一条只能下置一个开关量的状态。

设备响应:如果成功把计算机发送的命令原样返回,否则不响应。

4、读可读写模拟量寄存器(保持寄存器):

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

例:[11][03][00][6B][00][03][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:读模拟量的命令号固定为03。

<3>起始地址高8位、低8位:表示想读取的模拟量的起始地址(起始地址为0)。比如例子中的起始地址为107。

<4>寄存器数高8位、低8位:表示从起始地址开始读多少个模拟量。例子中为3个模拟量。注意,在返回的信息中一个模拟量需要返回两个字节。

设备响应:[设备地址][命令号03][返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位][CRC校验的高8位]

例:[11][03][06][02][2B][00][00][00][64][CRC低][CRC高]

意义如下:

<1>设备地址和命令号和上面的相同。

<2>返回的字节个数:表示数据的字节个数,也就是数据1,2...n中的n的值。例子中返回了3个模拟量的数据,因为一个模拟量需要2个字节所以共6个字节。

<3>数据1...n:其中[数据1][数据2]分别是第1个模拟量的高8位和低8位,[数据3][数据4]是第2个模拟量的高8位和低8位,以此类推。例子中返回的值分别是555,0,100。

<4>CRC校验同上。

5、读只可读模拟量寄存器(输入寄存器):

和读取保存寄存器类似,只是第二个字节的命令号不再是2而是4。

6、写单个模拟量寄存器(保持寄存器):

计算机发送命令:[设备地址][命令号06][需下置的寄存器地址高8位][低8位][下置的数据高8位][低8位][CRC校验的低8位][CRC校验的高8位]

例:[11][06][00][01][00][03][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:写模拟量的命令号固定为06。

<3>需下置的寄存器地址高8位,低8位:表明了需要下置的模拟量寄存器的地址。

<4>下置的数据高8位,低8位:表明需要下置的模拟量数据。比如例子中就把1号寄存器的值设为3。

<5>注意此命令一条只能下置一个模拟量的状态。

设备响应:如果成功把计算机发送的命令原样返回,否则不响应。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: