简介
Modbus是一种串行通信协议,通常运用在电子设备之间的通信上。modbus原本是针对PLC通信问题设计的,目前该协议主要用在串口、以太网和其他互联网协议的网络。常采用TCP或485串口通信。
modbus是一个master/slave(server/client)架构的协议,即主从结构。有且只有一个主机,每一个从机都有一个唯一的设备地址。
协议版本
- modbus ASCII
是一种人类可读的,冗长的表达方式,使用串行通信方式,采用纵向冗余校验的校验和(LRC)。 - modbus RTU
是一种紧凑的,采用二进制表示数据的方式,使用串行通信方式,采用循环冗余校验的校验和(CRC校验) - modbus TCP
对于通过TCP/IP(例如以太网)的连接,存在多个modbus/TCP变种,这种方式不需要校验和计算,目前使用较为广泛。
寄存器
modbus有四种寄存器:线圈状态寄存器、离散输入状态寄存器、保持寄存器、输入寄存器。
modbus给每个分区都划分了地址范围,主机向从机获取数据时,只需要告诉从机数据的起始地址和要获取的字节数,从机就可以发送数给主机。
modbus数据模型规定了具体的地址范围,每个从机都有实际的物理存储,跟modbus的存储区相对应,主机读写从机的存储区,实际上就是对从机设备对应的实际存储空间进行读写。
类别 | 区号 | 读写 | 寄存器地址 |
线圈状态 | 0区 | 可读写布尔量 | 0000H-FFFFH |
离散输入状态 | 1区 | 只读布尔量 | 0000H-FFFFH |
输入寄存器 | 3区 | 只读寄存器 | 0000H-FFFFH |
保持寄存器 | 4区 | 可读写寄存器 | 0000H-FFFFH |
- 线圈状态寄存器:类比于开关量(继电器状态),每一个bit对应一个信号的开关状态。所以一个byte就可以同时控制8路信号。线圈状态寄存器可以读,也可以写,写在功能吗中又分为写单个线圈和写多个线圈。
- 离散输入寄存器:离散输入寄存器相当于线圈状态寄存器的只读模式,每一个bit表示一个开关量,而他的开关量只能读取,不能写入。例如读取外部按键是按下状态还是松开状态。
- 保持寄存器:这个寄存器的单位不在是bit,而是2个byte,可以存放具体的数据量,可读写,一般对应参数设置,比如设置时间的年月日。
- 输入寄存器:和保持寄存器类似,但是只能读取,一般是读取各种实时数据。一个寄存器也是占据2个byte空间。例如读取AD采集值。
数据帧格式
RTU帧格式
RTU是常用的一种协议,一个报文就是一帧数据,实际上就是一串有组织的数据串。RUT帧格式如下:
从机地址 | 功能码 | 数据域 | 校验位 |
1字节 | 1字节 | n字节 | 2字节(CRC) |
- 从机地址:从机设备地址(每个从机都有唯一设备地址),0~255,0为广播地址,所有从机都接收,但是不回复。
- 功能码:指令功能,
- 数据域:发送或接收的数据
- 校验:2字节的CRC校验,计算范围为从机地址到数据域最后一个字节。
TCP帧格式
事务处理标识符 | 协议标识符 | 长度 | 单元标识 | 功能码 | 数据 |
2字节 | 2字节 | 2字节 | 1字节 | 1字节 | n字节 |
- 事务处理标识符:类似于心爱序列号,确认发出和收到的信息属于同一序列,每次通信后加1
- 协议标识符:用于系统内的多路复用,当值为0(00 00),表示使用modbus协议
- 长度:用于说明此字节之后还有多少个字节的数量
- 单元标识符:即设备地址,在slave中对应其ID
- 功能码:和RTU相似
- 数据:和RTU相似
功能码
modbus常用功能码:
功能码 | 功能说明 |
01H | 读取输出线圈 |
02H | 读取输入线圈 |
03H | 读取保持寄存器 |
04H | 读取输入寄存器 |
05H | 写单个线圈 |
06H | 写单个寄存器 |
0FH | 写多线圈 |
10H | 写多个寄存器 |
错误信息
当主机传送的报文不符合格式或从机不支持此功能 等问题时,从机会回复主机一个错误信息,错误信息帧格式:
从机地址 | 功能码 | 异常码 | CRC校验 |
1字节 | 1字节 | 1字节 | 2字节 |
错误功能码
功能码 | 名称 | 说明 |
01 | ILLEGAL FUNCTION | 不支持的功能 |
02 | ILLEGAL DATA ADDRESS | 不合法的地址 |
03 | ILLEGAL DATA VALUE | 不合法的数值 |
04 | SLAVE DEVICE FAILURE Slave | 失效 |
05 | ACKNOWLEDGE | 命令执行中 |
06 | SLAVE DEVICE BUSY Slave | 忙碌 |