MODBUS 通讯协议在产品中的应用框架V20Word文档下载推荐.docx
《MODBUS 通讯协议在产品中的应用框架V20Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《MODBUS 通讯协议在产品中的应用框架V20Word文档下载推荐.docx(38页珍藏版)》请在冰豆网上搜索。
表1
基本表
对象类型
访问类型
注释
离散量输入
单个位
只读
I/O系统可提供这种类型数据
线圈
读写
通过应用程序可改变这种类型数据
输入寄存器
16位字
保持寄存器
输入与输出之间以及位寻址的和字寻址的数据项之间的区别并不意味着应用特性的差别。
如果所有4个表相互覆盖是对该目标机器最自然的解释,也是完全可接收的,而且很普遍。
对于每个基本表,协议都允许单个的选择65536个数据项,而且其读写操作被设计为可以越过多个连续数据项直到数据大小规格限制,这个数据大小规格限制与事务处理功能码有关。
Modbus功能码中使用的Modbus寄存器逻辑编号是以0开始的无符号整数索引。
Modbus模型实现的实例
下列实例表示了两种在设备中组织数据的方法。
有多种组织数据的方法,在本部分中没有被全部描述。
每个设备根据其应用都有它自己的组织数据的方法。
实例1:
有4个独立块的设备
图4表示了含有数字量和模拟量、输入量和输出量的设备中的数据组织。
由于不同块中的数据不相关,每个块是独立的。
可通过不同Modbus功能码访问每个块。
图4带有独立块的Modbus数据模型
实例2:
仅有1个块的设备
图5实例中,设备仅有1个数据块。
通过几个Modbus功能码能够得到相同数据,既可通过16位访问也可通过1位访问。
图5仅带有1个块的Modbus数据模型
5.Modbus事务处理的定义
图6是状态图,描述了在服务器侧Modbus事务处理的一般处理过程。
图6Modbus事务处理的状态图
一旦处理器处理请求,使用合适的Modbus服务器事务处理建立Modbus响应。
根据处理结果,可以建立两种类型响应:
♦一个正常的Modbus响应:
响应功能码=请求功能码。
♦一个异常的Modbus响应
1)用来给客户机提供处理过程中与所发现的差错相关的信息;
2)异常功能码=请求功能码+0x80;
3)提供一个异常码来指示差错原因。
6.公共功能码定义
见表2。
表2
功能码
码
子码
(十六进制)
数
据
访
问
比特访问
物理离散量输入
读离散量输入
02
—
内部比特或物理线圈
读线圈
01
写单个线圈
05
写多个线圈
15
0F
16比特访问
读输入寄存器
04
内部存储器或物理输出存储器
读多个寄存器
03
写单个寄存器
06
写多个寄存器
16
10
读/写多个寄存器
23
17
屏蔽写寄存器
22
读FIFO队列
24
18
文件访问记录
读文件记录
20
6
14
写文件记录
21
诊断
读异常状态
07
08
00-18
获得公用事件计数器
11
0B
获得公用事件记录
12
0C
报告从站ID
读设备识别码
43
2B
其他
封装接口传输
7.功能码描述
7.1.01(0x01)读线圈
见表3~表5。
使用该功能码从一个远程设备中读1~2000个连续的线圈状态。
请求PDU指定了起始地址,即指定了第一个线圈地址和线圈数目。
在PDU中,从17(十六进制11)返回从站忙计数。
响应报文中的线圈按数据域的每位一个线圈进行打包。
状态被表示成1=ON和0=OFF。
第一个数据字节的LSB(最低有效位)包含询问中所寻址的输出。
其他线圈依次类推,一直到这个字节的高位端为止,并在后续字节中按照从低位到高位的顺序排列。
如果返回的输出数量不是8的倍数,将用零填充最后数据字节中的剩余位(一直到字节的最高位端)。
字节数量域说明了数据的全部字节数。
表3
请求
1字节
0x01
起始地址
2字节
0x0000~0xFFFF
线圈数量
1~2000(0x07D0)
表4
响应
字节计数
N*
线圈状态
n字节
n=N或N+1
*N=输出数量/8,如果余数不等于0,那么N=N+1。
表5
错误
功能码+0x80
异常码
01或02或03或04
7.2.02(0x02)读离散量输入
见表6~表8。
使用该功能从一个远程设备中读1~2000个连续的离散量输入状态。
请求PDU指定了起始地址,即指定了第一个离散量输入地址和离散量输入数目。
在PDU中,从零开始寻址离散量输入。
因此标号1~16的离散量输入寻址为0~15。
响应报文中的离散量输入按数据域的每位一个离散量输入进行打包。
状态被表示成1=ON和0=OFF。
第一个数据字节的LSB(最低有效位)包含讯问中所寻址的输入。
其他离散量输入依次类推,一直到这个字节的高位端为止,并在后续字节中按照从低位到高位的顺序排列。
表6
0x02
表7
N*×
1个字节
…
*N=输出数量/8,如果余数不等于0,那么N=N+1
表8
差错码
0x82
7.3.03(0x03)读保持寄存器
见表9~表11。
使用该功能码从远程设备中读保持寄存器连续块的内容。
请求PDU说明了起始寄存器地址和寄存器数量。
在PDU中,从零开始寻址寄存器。
因此编号1~16的寄存器寻址为0~15。
将响应报文中的寄存器数据打包成每个寄存器有两字节。
对于每个寄存器,第一个字节为高位字节,第二个字节为低位字节。
表9
0x03
寄存器数量
1~125(0x007D)
表10
字节数
2×
寄存器值
2个字节
*N=寄存器的数量
表11
0x83
7.4.04(0x04)读输入寄存器
见表12~表14。
使用该功能码从一个远程设备中读1~125个连续输入寄存器。
请求PDU说明了起始地址和寄存器数量。
因此,标号为1~16的输入寄存器寻址为0~15。
将响应报文中的寄存器数据打包成每个寄存器为两字节。
对于每个寄存器,第一个字节包括高位位,第二个字节包括低位位。
表12
0x04
输入寄存器数量
0x0001~0x007D
表13
*N=输入寄存器的数量。
表14
0x84
7.5.05(0x05)写单个线圈
见表15~表17。
使用该功能码将一个远程设备中的一个输出写ON或OFF。
请求数据域中的常数指定所请求的ON/OFF状态。
十六进制值FF00请求输出为ON。
十六进制值0000请求输出为OFF。
其他所有值均是非法的,并且对输出不起作用。
请求PDU说明了被强制的线圈地址。
从零开始寻址线圈。
因此,编号为1的线圈被寻址为0。
线圈值域的常数指定所请求的ON/OFF状态。
十六进制值0xFF00请求线圈为ON。
十六进制值0x0000请求线圈为OFF。
其他所有值均为非法的,并且对线圈不起作用。
正常的响应是请求的复制,在写入线圈状态后被返回。
表15
0x05
输出地址
输出值
0x0000或0xFF00
表16
表17
0x85
7.6.06(0x06)写单个寄存器
见表18~20。
使用该功能码在一个远程设备中写一个保持寄存器。
请求PDU指定了被写入寄存器的地址。
从零开始寻址寄存器。
因此,编号为1的寄存器被寻址为0。
正常的响应是请求的复制,在写入寄存器内容之后被返回。
表18
0x06
寄存器地址
表19
表20
0x86
7.7.07(0x07)读异常状态
见表21~23。
使用这个功能码从一个远程设备中读8个异常状态输出的内容。
因为异常码输出参量是已知的(在这个功能中不需要输出参量),该功能提供一种简单的访问这种信息的方法。
正常的响应包括8个异常状态输出的内容。
将这些输出打包成一个字节,每个输出一个位。
在该字节的最低有效位中包含最低位输出参量的状态。
表21
0x07
表22
输出数据
0x00~0xFF
表23
0x87
01或04
7.8.08(0x08)诊断
公司产品通讯协议中不使用该功能码,不进行描述。
7.9.11(0x0B)获得通信事件计数器
7.10.12(0x0C)获得通信事件记录
7.11.15(0x0F)写多个线圈
见表24~26。
该功能码将一个远程设备中的一个线圈序列的每个线圈强制为ON或OFF。
请求PDU指定了被强制的线圈编号。
请求数据域的内容指定了被请求的ON/OFF状态。
数据域中为逻辑“1”的位请求相应输出为ON。
为逻辑“0”的位请求相应输出为OFF。
正常的响应返回功能码、起始地址和被强制的线圈数量。
表24
0x0F
输出数量
0x0001~0x07B0
*N=输出数量/8,如果余数不等于0,那么,N=N+1。
表25
表26
0x8F
7.12.16(0x10)写多个寄存器
见表27~29。
使用该功能码在一个远程设备中写连续寄存器块(1~123个寄存器)。
在请求数据域中指定了请求写入的值。
将数据打包成每个寄存器两字节。
正常的响应返回功能码、起始地址和被写入寄存器的数量。
表27
0x10
0x0001~0x007B
值
*N=寄存器数量
表28
1~123(0x007B)
表29
0x90
7.13.17(0x11)报告从站ID
7.14.20/6(0x14/0x06)读文件记录
7.15.21/6(0x15/0x06)写文件记录
7.16.22(0x16)屏蔽写寄存器
7.17.23(0x17)读/写多个寄存器
7.18.24(0x18)读FIFO队列
7.19.43(0x2B)封装接口传输
7.20.43/14(0x2B/0x0E)读设备标识
见表30~33。
这个功能码允许读取与远程设备的物理和功能描述相关的标识和附加信息。
读设备识别接口由包含一组可寻址数据元素组成的地址空间构成。
数据元素被称作对象,由对象Id识别它们。
接口由3类对象组成:
——基本设备识别。
所有此类对象都是必备的:
厂商名称、产品代码和修订版本号。
——常规设备识别。
除基本数据对象以外,设备提供了附加的和可选择的识别以及数据对象描述。
本标准定义了所有类别的对象,但是它们的实现是可选的。
——扩展设备识别。
除常规数据对象以外,设备提供了附加的和可选的识别以及专用数据描述。
所有这些数据都是与设备有关的。
表30
对象Id
对象名称/描述
类型
M/O
类别
0x00
厂商名称
ASCII字符串
强制的
基本
产品代码
主要修订本
厂商网址
可选的
常规
产品名称
模式名称
用户应用名称
0x7F
保留
0x80
0xFF
可选择的定义专用对象
范围(0x80~0xFF)与产品有关
扩展
表31
0x2B
MEI类型
0x0E
ReadDevId码
01/02/03/04
表32
一致性等级
接续标识
0x00/0xFF
下一个对象Id
对象ID号
对象数量
列表
对象ID
对象长度
对象值
与对象ID有关
表33
0xAB:
Fc0x2B+0x80
第二部分天辰Modbus协议框架
Modbus协议定义了两种串行传输模式:
RTU模式和ASCII模式。
这两种模式定义了链路上串行传送报文域的位内容,确定了信息如何打包为报文域和如何解码。
Modbus要求每个设备必须实现RTU模式,ASCII模式作为可选模式。
考虑到我公司目前主流产品的协议都是基于ASCII码协议的。
因此,下面首先描述我们的ASCII实现方法,再描述RTU协议。
1.ASCII传输模式
在Modbus串行链路上通信时,用两个ASCII字符发送报文中的一个8位字节。
实例:
将字节0x5B编码为两个字符:
0x35和0x42。
ASCII模式中每个字节(10位)的格式为:
编码系统:
十六进制,ASCII字符0~9、A~F
报文中每个ASCII字符含有1个十六进制字符
每个字节的位:
1个起始位
7个数据位,首先发送最低有效位
1个奇偶校验位
1个停止位
注:
默认的校验模式是偶校验,但可以通过设置变更为无校验或奇校验。
帧校验域:
纵向冗余校验(LRC)。
通讯波特率:
可选范围为2400bps、4800bps、9600bps、19200bps。
1.1.Modbus报文ASCII帧
在ASCII模式中,用特定的字符将报文划分为帧起始和帧结束(这一点和天辰协议相同)。
一个报文必须以一个“冒号”(:
)字符(十六进制ASCII3A)起始,以“回车—换行”(CRLF)(十六进制ASCII0D和0A)结束。
图6表示了一个典型的报文帧。
图6
起始
地址
数据
LRC
结束
1个字符
2个字符
0至0x252个字符
ModbusASCII帧的最大长度为513个字符。
1.2.LRC校验
在ASCII模式中,报文包含一个差错校验域,该域是基于对全部报文内容执行的纵向冗余校验(LRC)计算结果,不包括起始“冒号”和结束CRLF对。
LRC域是一个字节,包含一个8位二进制值。
发送设备计算LRC值,将LRC值附加到报文中。
在接收报文过程中,接收设备重新计算LRC值,并将计算值与LRC域中接收到的实际值相比较。
如果两个值不相等,则产生错误。
对报文中的所有连续8位字节相加,忽略任何进位,计算LRC,然后求出其二进制补码。
根据不包括报文起始“冒号”和报文结束CRLF对的整个ASCII报文域内容进行LRC。
在ASCII模式中,LRC的结果被编码为两个字节的ASCII,并将其放置CRLF之前的ASCII模式报文帧的结尾处。
2.RTU传输模式
在Modbus串行链路上通信时,报文中每个8位字节含有两个4位十六进制字符。
RTU模式中每个字节(11位)的格式为:
每个8位字节含有两个4位十六进制字符(0~9、A~F)
8个数据位,首先发送最低有效位
循环冗余校验(CRC)。
2.1.Modbus报文RTU帧
在RTU模式中,时长至少为3.5个字符时间的空闲间隔将报文帧区分开。
这个时间称为t3.5。
图7表示了一个典型的报文帧。
图7
CRC
≥3.5字符
8位
N×
16位
必须以连续的字符流发送整个报文帧。
如果字符之间的空闲间隔大于1.5个字符时间,那么认为报文帧不完整,并且接收站应该丢弃这个报文帧。
字符间间隔
所谓1个字符的时间t,是指发送完每个11位所用的时间,计算方法为“1÷
波特率×
11”。
但是,实现RTU的定时会对系统带来大量中断管理。
在较高的通讯波特率下,这将导致CPU负担加重。
因此,当波特率等于或低于19200bit/s时,必须严格遵守这两个定时;
波特率大于19200bit/s时,两个定时器应该使用固定值:
建议字符间隔超时时间(t1.5)为750μs,帧间的超时时间(t3.5)为1.750ms。
2.2.CRC校验
RTU模式包含一个差错校验域,该域是基于冗余