Modbus通讯协议
第1章 输入和输出信号
数据类型 | 用途 | 备注 |
模拟输出(Analog Output,AO) | 用于控制例如调节电机转速、温度等设备的工作状态 | 遥调 |
模拟输入(Analog Input,AI) | 用于测量例如温度、压力、流量等物理量 | 遥测 |
数字输出(Digital Output,DO) | 用于控制开关、继电器、LED等数字设备 | 遥控 |
数字输入(Digital Input,DI) | 用于检测开关的状态、传感器的触发等 | 遥信 |
注:
AO:通常使用 DAC(数字到模拟转换器)将数字信号转换为模拟信号输出。
AI:模拟信号通过 ADC(模拟到数字转换器)转换为数字信号,以便在计算机或控制系统中进行处理。
第2章 传输时间
- 波特率:信号变化频率,单位是 Baud(或Hz)。
- 比特率:数据传输速率,单位是 比特/秒(bps)。
2.1 每个字节传输的时间
假定是115200 Baud。
2.1.1 计算每个比特的时间
2.1.2 计算每个字节的时间
2.2 每个字符传输的时间
- 为了使软件更容易判断一帧数据包是否结束,Modbus规定两帧数据包之间至少有3.5 个字符时间的空闲间隔,叫做3.5T:
-
当串口波特率大于19200时,那么3.5T固定为1750us;
要计算字符传输时间,我们需要知道以下几个因素:
- 波特率(Baud Rate):115200 波特。
- 字符的位数:一个标准的字符通常由 8 位(1 字节)组成,通常还会有起始位和停止位。
假设:
- 1 字符 = 1 字节(8 位)
- 起始位和停止位:通常,串口传输使用 1 个起始位 和 1 或 2 个停止位。我们假设使用 1 个停止位 和 1 个起始位。
计算步骤:
- 每个字符传输的总位数 = 1 个起始位 + 8 个数据位 + 1 个停止位 = 10 位。
- 波特率 = 115200 波特,即每秒传输 115200 个信号变化。
- 每个字符的传输时间 = 总位数波特率\frac{\text{总位数}}{\text{波特率}}波特率总位数
计算:
每个字符的传输时间大约是 86.8 微秒。
第3章 Modbus协议栈模型
第4章 Modbus的通信机制
主机和从机之间,必须由主机先主动发生请求报文,从机才能再发送响应报文。
也就是从机不能主动上发报文。
第5章 Modbus寄存器种类
助记:两个状态,两个寄存器。状态肯定是数字量,寄存器肯定是模拟量。
第6章 寄存器的地址分配
注意:PLC的地址是从1开始,NCU的地址是从0开始
第7章 Modbus 消息帧格式
7.1 ModbusRTU消息帧格式
7.1.1 ModbusRTU的消息帧
7.2 Modbus ASCII消息帧格式
7.3 ModbusTCP消息帧格式
7.3.1 ModbusTCP的MBAP
第8章 Modbus 功能码
第9章 Modbus交互示例
9.1 读取线圈状态报文(0x01)
注:每个线圈的状态就是一个寄存器。
从0x0013地址开始读取线圈状态,需要读取0x0025个寄存器(线圈)的状态。
9.2 响应报文
注:
ON:表示一个寄存器的状态,可以是0xFF00;
OFF: 表示的还是一个寄存器(线圈状态),可以是0x0000
地址范围 | 取值 | 字节值 | |||||||
0x0013~0x001B | ON | ON | OFF | OFF | ON | OFF | ON | OFF | 0x53 |
1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0x53 | |
低地址空间 | 高地址空间 |
所以0x0101 0011 总共有8个数据位,每个位为一个线圈状态,共计8个线圈的状态。
第10章 Modbus异常功码
代码 | 名称 | 含义 | |
0x00 | 成功码 | 成功响应 | |
0x01 | 非法功能 | 从机不支持此功能码 | |
0x02 | 非法地址 | 指定的地址在从机中不存在 | |
0x03 | 非法数据值 | 指定的数据超过范围或者不允许使用 | |
0x04 | 从机故障 | 从机处理响应的过程中,出现未知错误等 |
/* 异常信息编码 */
#define ExeptionCode_0_success 0 /* 成功 */
#define ExeptionCode_1_Validatefunctioncode 1 /* 功能码错误 */
#define ExeptionCode_2_ValidatedataAddress 2 /* 地址错误 */
#define ExeptionCode_3_ValidateDataValue 3 /* 数据错误 */
#define ExeptionCode_4_ExecuteError 4 /* 功能执行错误 */