modbus RTU协议
Modbus串行链路协议是一个主从模式(主机和从机),半双工的数据传输协议,485标准通常需要两条线,在某一个确定时刻,有一个主机和从机进行通讯。
主从模式:通常总线上有一个主机和多个从机,每个从机有唯一的ID,主机通过ID进行寻址从机,然后进行数据传输;
半双工传输:相对应半双工的是全双工,全双工运行发送数据和接收数据同时发生,所以半双工就不难理解了,同一时刻只能进行发送数据,或者只能接收数据;
地址域:可以理解成 具体和谁说话;
功能码:可以理解成 具体动作,比如 去做,来拿,去吃 等等;
数据:可以理解成 具体内容,比如 面,饭 等等,也可以是其他,这里配合上下文,所以是吃的东西;
差错校验:可以理解成,说出来的话必须可以让人理解,不然别人听不懂啊;实际上在协议中通常使用CRC或LRC保证传输的数据没有错误;
地址域
地址域占用一个字节,所以一般来说寻址范围是0~255,一般在系统中用1~147,其他地址暂时保留,另外,同一个总线上的从机,每个地址必须唯一。
其中0是广播地址;
下面是Freemodbus的一个从机初始化代码,0x02就是这个从机的地址
eMBInit(MB_RTU, 0x02, 3, 115200, MB_PAR_NONE);
功能码
功能码占一个字节,所以范围是 0~255,协议中规定了功能码分为三类:公共功能码,用户自定义功能码,保留功能码。整体如下所示;
由上表可知,公共功能码分为四种,分别是:
-
离散量输入:只读类型,单位:bit;
-
线圈:读写类型,单位:bit;
-
输入寄存器:只读类型,单位:字节;
-
保持寄存器:读写类型,单位:字节;
//输入寄存器量
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
//保持寄存器量
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
//线圈数量
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
//离散输入数量
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
底层如何传输
我们先看一下最底层modbus数据是如何发送的,没错,看到RS485和232,那我们自然想到了串口。
所以最根本的数据格式可以参考一下串口数据的定义,也就是我们说的起始位,数据位,校验位,数据位;具体如下所示;
modbus协议说明
Modbus协议是一个master/slave架构的协议。有一个节点是master节点,其他使用Modbus协议参与通信的节点是slave节点。每一个slave设备都有一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令(在以太网上,任何一个设备都能发送一个Modbus命令,但是通常也只有一个主节点设备启动指令)。
一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令(地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会运行,不过不回应指令)。所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。
有许多modems和网关支持Modbus协议,因为Modbus协议很简单而且容易复制。它们当中一些为这个协议特别设计的。有使用有线、无线通信甚至短消息和GPRS的不同实现。不过设计者需要克服一些包括高延迟和时序的问题。