文章目录
Modbus协议
Modbus是OSI模型第七层的应用层报文传输协议在连接到不同类型总线或网络的设备之间提供客户机/服务器通信。 Modbus协议包括ASCII、RTU、TCP物理层没有规定。该协议定义了控制器可以理解和使用的信息结构,无论它们通过什么网络。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了新闻、数据结构、命令和回答方式,采用数据通信Maser/Slave方式,Master终端发送数据请求消息,Slave端接收到正确消息后,可以发送数据Master端以响应请求;Master也可以直接发消息修改Slave实现双向读写。
Modbus特点
Modbus具有以下特点: (1)用户可以免费、放心地使用标准和开放Modbus协议不需要支付许可费或侵犯知识产权。目前,支持Modbus超过400家制造商得到支持Modbus600多种产品。 (2)Modbus可支持多种电气接口,如RS-232、RS-485等,也可以在双绞线、光纤、无线等各种介质上传输。 (3)Modbus帧格式简单,紧凑,易于理解,易于用户使用,易于制造商开发。
本文重点:ModbusRTU使用功能码(以下数据均为16进制)
1.功能码01:读1路或多路开关量线圈输出状态
例如,主机的读取地址为01,开关量DO1,DO2.输出状态。 从机(PDM)数据寄存器的地址和数据如下:
起始地址 | DO寄存器数据 | 备注 |
---|---|---|
0000 | 02 | DO输出状态为0,DO输出状态为1 |
主机发送的报纸格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 从机器发送到设备地址01 |
功能码 | 1 | 01 | 读开关量输出状态 |
起始BIT位 | 2 | 0000 | 起始BIT位地址为 0000 |
读数据长度 | 2 | 0002 | 读取2路继电器线圈输出状态位 |
CRC校验码 | 2 | BDCB | 由主机计算ModbusCRC16校验码,两个字节,低字节在前,高字节在后。 |
从机(PDM)响应返回的报文格式:
从机响应 | 字节数 | 返回的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 来自从机 01 |
功能码 | 1 | 01 | 读开关量输出状态 |
数据长度 | 1 | 01 | 1个字节(8个BIT位) |
DO状态数据 | 1 | 02 | DO寄存器内容 |
CRC校验码 | 2 | D049 | 由主机计算ModbusCRC16校验码,两个字节,低字节在前,高字节在后。 |
2.功能码02:读1路或多路开关状态输入
例如,主机的读取地址为01,开关量DI1—DI4.输入状态。 从机(PDM)数据寄存器的地址和数据如下:
起始地址 | DI寄存器数据 | 备注 |
---|---|---|
0000 | 0B | DI1/DI2/DI输入状态为1,DI3输入状态为“0” |
主机发送的报纸格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至设备地址为01的从机 |
功能码 | 1 | 02 | 读开关量输入状态 |
起始BIT位 | 2 | 0000 | 起始BIT位地址为 0000 |
读数据长度 | 2 | 0004 | 读取4路开关量输入状态 |
CRC校验码 | 2 | 79C9 | 由主机计算ModbusCRC16校验码,两个字节,低字节在前,高字节在后。 |
从机(PDM)响应返回的报文格式:
从机响应 | 字节数 | 返回的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 来自从机 01 |
功能码 | 1 | 02 | 读开关量输入状态 |
数据长度 | 1 | 01 | 1个字节(8个BIT位) |
DI状态数据 | 1 | 0B | DI寄存器内容 |
CRC校验码 | E04F | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
3、功能码03:读多路寄存器
例如:主机要读取地址为01,起始地址为0002的3个从机寄存器数据。 从机(PDM)数据寄存器的地址和数据为:
寄存器地址 | 寄存器数据 | 备注 |
---|---|---|
0002 | 1234 | 此寄存器里的数据为十进制4660 |
0003 | 1111 | 此寄存器里的数据为十进制4369 |
0004 | 2222 | 此寄存器里的数据为十进制8738 |
主机发送的报文格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至地址为01的从机 |
功能码 | 1 | 03 | 读取寄存器 |
起始地址 | 2 | 0002 | 起始地址为 0002 |
数据长度 | 3 | 0003 | 读取3个寄存器(3个字) |
CRC校验码 | 2 | A40B | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
从机(PDM)响应返回的报文格式:
从机响应 | 字节数 | 返回的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 来自从机 01 |
功能码 | 1 | 03 | 读取寄存器 |
读取字节 | 1 | 06 | 3个寄存器共6个字节 |
寄存器数据1 | 2 | 1234 | 地址为0002的寄存器的内容 |
寄存器数据2 | 2 | 1111 | 地址为0003的寄存器的内容 |
寄存器数据3 | 2 | 2222 | 地址为0004的寄存器的内容 |
CRC校验码 | 2 | 5E43 | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
4、功能码05:写1路开关量输出
例1:开关量输出点DO1,其当前状态为“分”,主机要控制该路继电器“合”。控制命令为: “FF00”为控制继电器“合”; “0000”为控制继电器“分”; 主机发送的报文格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至地址为01的从机 |
功能码 | 1 | 05 | 写开关量输出状态 |
输出BIT位 | 2 | 0000 | 对应输出继电器BIT位(DO1) |
控制命令 | 2 | FF00 | 控制该路继电器输出为“合”状态位 |
CRC校验码 | 2 | 8C3A | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。 例2:开关量输出点DO2,其当前状态为“合”,主机要控制该路继电器“分”。
主机发送的报文格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至地址为01的从机 |
功能码 | 1 | 05 | 写开关量输出状态 |
输出BIT位 | 2 | 0001 | 对应输出继电器BIT位(DO2) |
控制命令 | 2 | 0000 | 控制该路继电器输出为“分”状态位 |
CRC校验码 | 2 | 9C0A | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。
5、功能码06:写单路寄存器
例如:主机要把数据1E34保存到地址为000B的从机寄存器中(从机设备地址为01),此数据将覆盖寄存器地址里原来的存储信息。
主机发送的报文格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至地址为01的从机 |
功能码 | 1 | 06 | 写单路寄存器 |
寄存器地址 | 2 | 000B | 要写入的寄存器地址 |
写入数据 | 2 | 1E34 | 写入的新数据 |
CRC校验码 | 2 | F07F | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。
6、功能码10:写多路寄存器
主机利用这个功能码把多个数据保存到PDM表的数据存储器中去。Modbus通讯规约中的寄存器指的是16位(2个字节或1个字),并且高位在前,低位在后。这样PDM的存储器都是2个字节。由于Modbus通讯规约允许每次最多保存60个寄存器,因此PDM一次也最多允许保存60个数据寄存器。 例如:主机要把数据2D7A、42B1、15E8保存到地址为002A、002B、002C的从机寄存器中去(从机设备地址为01)。
主机发送的报文格式:
主机发送 | 字节数 | 发送的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 发送至地址为01的从机 |
功能码 | 1 | 10 | 写多路寄存器 |
寄存器地址 | 2 | 002A | 要写入的寄存器的起始地址 |
写入数据字长度 | 2 | 0003 | 写入数据的字长度(共3个字) |
字节计数 | 1 | 06 | 写入数据的字节长度(共6个字节) |
写入数据1 | 2 | 2D7A | 数据地址002A |
写入数据2 | 2 | 42B1 | 数据地址002B |
写入数据3 | 2 | 15E8 | 数据地址002C |
CRC校验码 | 2 | 52FC | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
从机(PDM)响应返回的报文格式:
从机响应 | 字节数 | 返回的信息 | 备注 |
---|---|---|---|
从机地址 | 1 | 01 | 来自从机01 |
功能码 | 1 | 10 | 写多路寄存器 |
起始地址 | 2 | 002A | 起始地址 |
数据字长度 | 2 | 0003 | 写入3个字长度 |
CRC校验码 | 2 | A1C0 | 由主机计算得到ModbusCRC16校验码,此校验码为2个字节,低字节在前,高字节在后 |
附:ModbusCRC16校验算法
/* ********************************************************************************************************* * 函 数 名: ModbusCRC16 * 功能说明: 标准ModBusCRC16校验计算 * 形 参:buf:需要校验的数据 len:需要校验的数据长度 * 返 回 值: 校验码 ********************************************************************************************************* */
unsigned short ModbusCRC16( unsigned char * aData, unsigned int aSize )
{
unsigned short CRC_OUT=0XFFFF;
unsigned int i,j;
unsigned char crc_low,crc_high;
for(i=0;i<aSize;i++)
{
CRC_OUT^=aData[i];
for(j=0;j<8;j++)
{
if( (CRC_OUT&0x01)==0x01)
{
CRC_OUT>>=1;
CRC_OUT^=0XA001;
}
else
{
CRC_OUT>>=1;
}
}
}
//exchange high and low 8 bit
crc_low=(unsigned char)CRC_OUT;
crc_high=(unsigned char)(CRC_OUT>>8);
CRC_OUT=(unsigned int)((crc_low<<8)+crc_high);
return CRC_OUT;
}
当然,我们也可以使用查表法来计算CRC校验码。