Modbus协议
总体上来说,发送命令格式如下:模块号(1字节)功能码 起始地址(2字节) 数据(X字节) CRC(2位)
模块号(1字节)功能码(要读取的寄存器,读 01,设置05,Coil Status/Input Status,1字节)起始地址(2字节,H->L) 数据 CRC校验
响应格式
模块号(1字节)功能码(1字节)字节数 数据(H->L) CRC校验
功能码:01 读取线圈状态,取得一组逻辑线圈的当前状态(ON/OFF)
模块号(1字节)功能码 起始地址(2字节,H->L) 读取位数(2字节) CRC(2位)
响应格式:
模块号(1字节)功能码(1字节)字节数 数据(L) 数据(H) CRC校验
02 01 00 10 00 08 3C 3A
返回(DO-0亮)
02 01 01 01 90 0C
返回(DO-0 不亮)
02 01 01 00 51 CC
获得00开始,连续16个通道的值
02,01,00,00,00,10,3D,F5
返回(只有DI-1有输入值)
02,01,02,02,00,FC,9C
Device ID:2,Address:0001,Length:8
02 01 00 00 00 08 3D FF
02 01 01 00 51 CC
02 01 01 02 51 CC(DI 1 亮的时候的返回)
Device ID:2,Address:0002,Length:8
02 01 00 01 00 08 6C 3F
02 01 01 01 90 0C
功能码:05 强制单路开出,给PLC写数据
注:写0xFF00表示ON,写0x0000表示OFF,线圈地址比地址少小1
注:返回帧与主站相同
模块号(1字节)功能码 起始地址(2字节) 数据(2字节) CRC(2位)
响应格式:返回帧与主站相同
设置DO-0(地址17)亮
02 05 00 10 FF 00 8D CC
返回
02 05 00 10 FF 00 8D CC
设置DO-0 不亮
02 05 00 10 00 00 CC 3C
返回
02 05 00 10 00 00 CC 3C
同时设置多个输出格式(功能码:15)
模块号(1字节)功能码(15)起始地址(2字节) 设置个数(2字节)数据的字节数(1字节)数据(H->L) CRC校验
响应格式
模块号(1字节)功能码(1字节)起始地址(2字节) 设置个数(2字节) CRC校验
eg:
(设置17站开始的8个站,为输出):
02,0F,00,10,00,08,01,FF,3F,03
响应:
02,0F,00,10,00,08,55,FB
(设置17站开始的8个站,全灭):
00,10,00,08,01,00,7F,43
响应:
02,0F,00,10,00,08,55,FB
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下是更详细的说明,摘自http://blog.sina.com.cn/s/blog_5d4d58a90100rkxf.html
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
基于串口的Modbus软件开发
----------------------八股--------------------
1、已经有好多个测试软件了,但是没有开源。如modbusscan 7.0(ModScan32.exe),Modbus Poll version, 4.3.1, Modbustester.exe,ModLink,ModbusSimulator
2、协议比较老了,但是很管用。
主从方式,主站初始化传输。从站根据主设备查询提供的数据作出反应。
主站查询格式:站(或广播)地址、功能代码、要发送的数据、错误检测域。
从站回应格式:确认要行动的域、返回的数据、错误检测域。如果在消息接收过程中发生错误,或从站不能执行其命令,从站将建立错误消息并把它作为回应发送出去。
从站地址是0...247,0为广播地址
ASCII模式
|
: |
地址 |
功能代码 |
数据数量 |
数据1 |
... |
数据n |
LRC高字节 |
LRC低字节 |
回车 |
换行 |
代码系统:
十六进制,ASCII字符0...9,A...F
消息中的每个ASCII字符都是一个十六进制字符组成
每个字节的位:
1个起始位
7个数据位,最小的有效位先发送
1个奇偶校验位,无校验则无
1个停止位(有校验时),2个Bit(无校验时)
错误检测域
LRC(纵向冗长检测)
使用ASCII模式,消息以冒号(:)字符(ASCII码 3AH)开始,以回车换行符结束(ASCII码 0DH,0AH)。
其它域可以使用的传输字符是十六进制的0...9,A...F。网络上的设备不断侦测“:”字符,当有一个冒号接收到时,每个设备都解码下个域(地址域)来判断是否发给自己的。
消息中字符间发送的时间间隔最长不能超过1秒,否则接收的设备将认为传输错误。
RTU模式
|
地址 |
功能代码 |
数据数量 |
数据1 |
... |
数据n |
CRC低字节 |
CRC高字节 |
代码系统:
8位二进制,十六进制数0...9,A...F
消息中的每个8位域都是一个两个十六进制字符组成
每个字节的位:
1个起始位
8个数据位,最小的有效位先发送
1个奇偶校验位,无校验则无
1个停止位(有校验时),2个Bit(无校验时)
错误检测域
CRC(循环冗长检测)
深入理解ModBus功能码
Modbus主要功能码
|
功能码 |
名称 |
注释 |
|
|
01 |
Read Coil Status |
(线圈状态0x)(读PLC的开出状态) |
bit 读位 ,与5对应, 可读可写DO |
|
02 |
Read Input Status |
(输入状态1x) (读PLC的开入状态) |
bit 读位,只读DI |
|
03 |
Read Holding Register |
(保持寄存器4x HR) (读模出状态) |
读整形、状态字、浮点型、字符型,与16对应 |
|
04 |
Read Input Register |
(输入寄存器3x AR) (读PLC模入状态) |
读整形、状态字、浮点型 只读AI |
|
05 |
Write Single Coil |
(强制单路开出,给PLC写数据) |
写单个位 可读可写DO |
|
06 |
Write Single Register |
(强制单路模出,给PLC写数据) |
写单个整形、状态字、浮点型、字符型,写HR4x的地址区 |
|
15 |
Write Multiple Coil |
(强制多路开出,给PLC写数据) |
写多个位 |
|
16(0x10H) |
Write Multiple Register |
(强制多路模出,给PLC写数据) |
写多个整形、状态字、浮点型、字符型 |
15和16可能是用于一次写一串数据的,不允许单个写。如时间的世纪、年、月、日、时、分、秒要一次写下去
|
设备和Modbus 地址范围对应表 |
||||
|
设备地址 |
Modbus地址 |
描述 |
功能 |
R/W |
|
1...10000* |
address - 1 |
Coils (outputs) |
0 |
Read/Write |
|
10001...20000* |
address - 10001 |
Discrete Inputs |
01 |
Read |
|
40001...50000* |
address - 40001 |
Holding Registers |
03 |
Read/Write |
|
30001...40000* |
address - 30001 |
Input Registers |
04 |
Read |
*最大值与设备相关
注:设备地址是从1开始的,所以Modbus写入地址要在设备地址上减1。
协议格式
功能码:01 (线圈状态0x)(读开出状态)
例:从4站读10…22(Coil 11…23),从A开始,共D(13)个数据
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H Coils |
L Coils |
CRC |
|
|
04 |
01 |
00 |
0A |
00 |
0D |
DD |
98 |
主站
|
从站地址 |
功能码 |
字节数 |
Coils 7..10 |
Coils 27..20 |
CRC |
|
|
04 |
01 |
02 |
0A |
11 |
50 |
B3 |
从站
功能码:02 (输入状态1x) (读开入状态)
例:从4站读10…22(Input 10011…10023),从A开始,共D(13)个数据
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H Input |
L Input |
CRC |
|
|
04 |
02 |
00 |
0A |
00 |
0D |
99 |
98 |
主站
|
从站地址 |
功能码 |
字节数 |
Input 7..10 |
Input 27..20 |
CRC |
|
|
04 |
02 |
02 |
0A |
11 |
14 |
B3 |
从站
功能码:03 (保持寄存器4x HR) (读模出状态)
例:从1站读0…1(寄存器 40001…40002),共2个数据
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H 数据 |
L 数据 |
CRC |
|
|
01 |
03 |
00 |
00 |
00 |
02 |
C4 |
0B |
主站
|
从站地址 |
功能码 |
字节数 |
H数据 |
L数据 |
H数据 |
L数据 |
CRC |
|
|
01 |
03 |
04 |
00 |
06 |
00 |
05 |
DA |
31 |
从站
功能码:04 (输入寄存器3x AR) (读模入状态)
例:从1站读0…1(寄存器 30001…30002),共2个数据
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H 数据 |
L 数据 |
CRC |
|
|
01 |
04 |
00 |
00 |
00 |
02 |
71 |
CB |
主站
|
从站地址 |
功能码 |
字节数 |
H数据 |
L数据 |
H数据 |
L数据 |
CRC |
|
|
01 |
04 |
04 |
00 |
06 |
00 |
05 |
DB |
86 |
从站
功能码:05 强制单路开出,给PLC写数据
例:给17站173单线圈写ON
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H 数据 |
L 数据 |
CRC |
|
|
11 |
05 |
00 |
AC |
FF |
00 |
4E |
8B |
主站
注:写0xFF00表示ON,写0x0000表示OFF
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H数据 |
L数据 |
CRC |
|
|
11 |
05 |
00 |
AC |
FF |
00 |
4E |
8B |
从站
注:返回帧与主站相同
功能码:06 强制单路模出,给PLC写数据
例:给17站40002变量写0x00 03H。帧的地址是0x0001H
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H 数据 |
L 数据 |
CRC |
|
|
11 |
06 |
00 |
01 |
00 |
03 |
9A |
9B |
主站
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H数据 |
L数据 |
CRC |
|
|
11 |
06 |
00 |
01 |
00 |
03 |
9A |
9B |
从站
注:返回帧与主站相同
功能码:15 强制多路开出,给PLC写数据
例:给17站从20号线圈开始的10个单线圈写ON,MB地址:20-1=19=0x13H
数据:
|
帧中位 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
|
位置 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
|
本例位置 |
27 |
26 |
25 |
24 |
23 |
22 |
21 |
20 |
- |
- |
- |
- |
- |
- |
29 |
28 |
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H线圈数量 |
L线圈数量 |
字节数 |
H数据 |
L数据 |
CRC |
|
|
11 |
0F |
00 |
13 |
00 |
0A |
02 |
CD |
01 |
BF |
0B |
主站
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H线圈数量 |
L线圈数量 |
CRC |
|
|
11 |
05 |
00 |
13 |
00 |
0A |
4E |
8B |
从站
注:变量写的从站反馈没有数据
功能码:16 强制多路模出到保持寄存器,给PLC写数据
每个寄存器的数据为2个字节。
例:给17站从40002HR开始的2个寄存器,数据为000A和0102,MB地址:40002-1=40001=MB1
|
从站地址 |
功能码 |
H地址 |
L地址 |
H模入数量 |
L模入数量 |
字节数 |
H |
L |
H |
L |
CRC |
|
|
11 |
10 |
00 |
01 |
00 |
02 |
04 |
00 |
0A |
01 |
02 |
C6 |
F0 |
主站
|
从站地址 |
功能码 |
H 地址 |
L 地址 |
H线圈数量 |
L线圈数量 |
CRC |
|
|
11 |
10 |
00 |
01 |
00 |
02 |
12 |
98 |
从站
注:变量写的从站反馈没有数据
秦批:Modbus的从站反馈数据没有数据帧的编号(不像TCP协议那样),所以不会显示这个反馈数据是主站的哪次请求的。若主站一次发送N个数据,从站而没有及时反馈,这样就乱了,主站就不知道从站发过来的数据是哪次命令的。
单变量与多变量:读可以读单读多,命令不分读几个。但是写要区分写一个还是写多个,所以写命令有写单线圈和写多线圈。
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/384 484 584) |
可使主机模拟编程器功能修改PC从机逻辑 |
|
14 |
探询(184/384 484 584) |
可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送 |
|
15 |
强置多线圈 |
强置一串连续逻辑线圈的通断 |
|
16 |
预置多寄存器 |
把具体的二进制值装入一串连续的保持寄存器 |
|
17 |
报告从机标识 |
可使主机判断编址从机的类型及该从机运行指示灯的状态 |
|
18 |
(884和MICRO 84) |
可使主机模拟编程功能,修改PC状态逻辑 |
|
19 |
重置通信链路 |
发生非可修改错误后,是从机复位于已知状态,可重置顺序字节 |
|
20 |
读取通用参数(584L) |
显示扩展存储器文件中的数据信息 |
|
21 |
写入通用参数(584L) |
把通用参数写入扩展存储文件,或修改之 |
|
22~64 |
保留作扩展功能备用 |
|
|
65~72 |
保留以备用户功能所用 |
留作用户功能的扩展编码 |
|
73~119 |
非法功能 |
|
|
120~127 |
保留 |
留作内部作用 |
|
128~255 |
保留 |
用于异常应答 |
ModBus功能码与数据类型对应表
|
代码 |
功能 |
数据类型 |
|
01 |
读 |
位 |
|
02 |
读 |
位 |
|
03 |
读 |
整型、字符型、状态字、浮点型 |
|
04 |
读 |
整型、状态字、浮点型 |
|
05 |
写 |
位 |
|
06 |
写 |
整型、字符型、状态字、浮点型 |
|
08 |
N/A |
重复“回路反馈”信息 |
|
15 |
写 |
位 |
|
16 |
写 |
整型、字符型、状态字、浮点型 |
|
17 |
读 |
字符型 |
Modbus变量地址
|
映射地址 |
功能 |
地址类型 |
存取方式 |
描述 |
|
0xxxx |
01,05,15 |
Coil |
读写 |
|
|
1xxxx |
02 |
离散输入 |
只读 |
|
|
2xxxx |
03,04,06,16 |
浮点寄存器 |
读写 |
两个连续16位寄存器表示一个浮点数(ieee754格式32位) |
|
3xxxx |
04 |
输入寄存器 |
只读 |
每个寄存器表示一个16位无符号整数(0~65535)同上 |
|
4xxxx |
03,06,16 |
保持寄存器 |
读写 |
|
|
5xxxx |
03,04,06,16 |
ascii字符 |
读写 |
每个寄存器表示两个ascii字符 |
FAQ0:ABB组态软件有功能块读线圈-1,读线圈-8,读寄存器-1,读寄存器-8的原因是什么?
因为Modbus功能码的读操作可以指定数据长度。如果从站的地址连续,则可以用一次读八个变量的操作。如果不连续,可以一次读一个。读八个的效率要高一些。
FAQ1 :MB地址的问题:MB经常用30001,40001这样的地址,WHY?给个理由。
ANS1 :地址以3开头,如IFIX的mb1中地址用30001、3001、300001表示的是功能码4的操作,即读输入寄存器。同理, 地址以4开头表示的是功能码3的操作,即对指的是对输出寄存器/内部寄存器进行的操作。虽然Modbus有两个字节表示地址0xFFFF,共64K,但是一般用不了那么多的。
例:高安屯垃圾电厂DCS Modbus通讯点表
|
DCS-TAG_№ |
DESCRIPTION |
Type |
Data |
Addr. |
|
XA 0FG10-1 |
ACTIVATED CARBON STORAGE SILO VENTING FILTER FAN FAULT |
DI |
BOOL |
00407 |
|
HC #RC10-O |
No.# INLET DAMPER FOR NID SYSTEM A IN SERVICE COMMAND |
DO |
BOOL |
10001 |
|
ATO #FG03-S |
No.# SET POINT SO2 EMISSION |
AO |
INT |
30002 |
|
AI #RC01 |
No.# REACTOR INLET GAS SO2 ANALYZER |
AI |
INT |
40001 |
注:地址以2开头表示浮点数,以0,1,3,4开头表示整数。
FAQ2 : Modbus功能码的名称来源是什么?
ANS2: 因为Modbus主要用于与PLC通讯,所以Modbus的地址空间命名也服从PLC的方式。我一起在弄DCS,没玩过PLC。所以没明白这个道理之前,根本搞不明白Modbus的功能码要那么叫,经过两天多的研究研究研究,终于大彻大悟了。
|
功能码 |
名称 |
注释 |
|
|
01 |
Read Coil Status |
读PLC的开出状态,可能是内部量 |
可读可写 |
|
02 |
Read Input Status |
读PLC的开入DI点状态 |
只读DI,通道来 |
|
03 |
Read Holding Register |
读PLC内部模拟量 |
|
|
04 |
Read Input Register |
读PLC的模入AI状态 |
只读AI,通道来 |
|
05 |
Write Single Coil |
给PLC写开关量数据 |
写单个位 |
|
06 |
Write Single Register |
给PLC写模拟量数据 |
写模拟量 |
|
15 |
Write Multiple Coil |
给PLC写多个开关量数据 |
写多个位 |
|
16(0x10H) |
Write Multiple Register |
给PLC写多个模拟量数据 |
写多个模拟量 |
Modbus协议的更多相关文章
- modbus协议讲义
Modbus 一个工业上常用的通讯协议.一种通讯约定.Modbus协议包括RTU.ASCII.TCP.其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现.虽然RTU比较简单,但是看 ...
- 模拟Modbus协议问题
问题: 在嵌入式系统开发中,Modbus协议是工业控制系统中广泛应用的一种协议.本题用来简单模拟Modbus协议,只需根据条件生成符合该协议的数据帧,并解析所获取的数据.假设设备使用的协议发送数据格式 ...
- 各种非标232,485协议,自定义协议转modbus协议模块定制开发,各种流量计协议转modbus,
工业现场经常会碰到通过485或者232采集各类仪表数据,但是很多早期的仪表和设备不支持标准modbus协议,而是采用自定义的协议,这些协议数据由plc或者dcs系统来实现采集,不仅费时麻烦,而且不方便 ...
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...
- 基于AVR128单纯Modbus协议实施
Modbus通信协议Modicon公司1979在发展中,适用于工业现场总线协议控制.Modbus通信系统包含芯片的节点,并与组合物可编程控制的公共传输线,它的目的是收集和监视多个节点的数据.Modbu ...
- MODBUS协议详解
MODBUS是一个工业上通信常用的通讯协议,一般在PLC上面用的比较多,主要是定义了一种数据传输的规范,比如数据发给谁,数据是干嘛的,数据错没错,接收到数据的从机告诉我数据有没有接受到等. 传输的方式 ...
- C# MODBUS协议 上位机(转)
源:C# MODBUS协议 上位机 C#写了一款上位机监控软件,基于MODBUS_RTU协议. 软件的基本结构: 采用定时器(Timer控件)为时间片. 串口采用serialPort1_DataRec ...
- 串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧
串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧 本例程中用51单片机作为Modbus从机,从机的设备地址为2,从机有4个寄存器, ...
- 认识Modbus协议
1.什么是Modbus? Modbus协议是应用于电子控制器上的一种通用语言.通过此协议,控制器相互之间,控制器经由网络(例如以太网)和其它设备之间可以通信.Modbus协议定义了一个控制器能认识使用 ...
- 《ServerSuperIO Designer IDE使用教程》-3.Modbus协议,读取多个寄存器,实现多种数据类型解析。发布:v4.2.2版本
更新内容,v4.2.2版本:1.增加Modbus协议读取多个寄存器,并且按多种数据类型解析数据.2.Modbus Serial和Modbus TCP两个驱动合并成一个驱动.3.修改数据库结构,保存配置 ...
随机推荐
- include指令和include标签的区别
区别 类别 语法 发生作用时间 包含的内容 转化成Servlet 编译时间 运行时间 include指令 <%@ include file="" %> 页面交换 实际内 ...
- turn.js 图书翻页效果
今天用turn.js 做图书的翻页效果遇到问题: 图片路径总是出错 调了一天,总算调出来了 我用的thinkphp,其他的不知道是不是一样 三 个地方要改动: 1.后台查出地址 注意的地方:1.地址要 ...
- Timer和TimerTask的用法
最近在做java课程设计的时候,我用到了timer,于是学习了一下timer的用法. java实现多线程比较常用的两种方法,一种是直接继承Thread类,另一种则是实现Runnable接口.Timer ...
- ATMEL处理器自带USB CDC的Win7驱动问题
[背景] 很久以前使用ATMEL的处理器开发了一款设备,通过处理器本身的功能,借助USB在PC端虚拟一个串口出来,实现和上位机软件的通信,和基本的参数设置和数据读取功能. 这个功能就是ATMEL官网上 ...
- java 生成8位数字作为UID
java 生成8位数字作为UUID: /*** * 生成uid 8位数字 */public static String generateUID(){ Random random = new Rando ...
- Eclipse *下载
简单了解,Eclipse是绿色软件,下载下来是个压缩包,只需要解压,加上jdk就可以运行了. 相比MyEclipse而言,它是免费的,后者是收费的.各有侧重吧 有很多人用Eclipse,也有很多人用M ...
- mysql按照中文名称排序
mysql按照中文名称排序 Sql代码 www.2cto.com /* Navicat MySQL Data Transfer Source Server : ...
- ADF_Controller系列1_绑定TasksFlow、Region和Routers(Part1)
2015-02-14 Created By BaoXinjian
- vim 学习日志(4):多窗口使用技巧
原文地址: http://blog.csdn.net/devil_2009/article/details/7006113 vim多窗口使用技巧 1.打开多个窗口打开多个窗口的命令以下几个:横向切割窗 ...
- 关于iscroll阻止浏览器默认动作
使用iscroll时,移动端遇到需要长按复制功能,但是iscroll屏蔽了浏览器默认事件,所以实现不了. 解决方案: myScroll = new IScroll('#wrapper',{ preve ...