使用RS485实现Modbus协议通信

基于RS485的Modbus协议

1. RS485总线

  RS485使用差分电平表示逻辑0或1,线A与B的电压差为+2v ~ +6v 时表示逻辑1,-2v ~ -6v时表示逻辑0。通信节点通过A、B两根线接入总线,总线结构如图1.1所示。

图1.1 RS485总线结构

2. 主/从协议

  基于RS485的Modbus协议是一个主/从协议,总线上有一台主机,一台或多台从机,通信总是由主机发起,从机没有收到来自主机的请求时不会发送数据,从机之间不能相互通信。
主机以两种方式向从机发送Modbus请求:
(1)单播模式
  在单播模式中,主机以特定的地址访问某个从机,该从机接收并处理完请求后,向主机返回一个应答。一个Modbus事务包含2个报文:一个来自主机的请求报文,一个来自从机的应答报文。每个从机有唯一的地址(1 ~ 247),这样才能区别于其它从机被独立的寻址。
(2)广播模式
  在广播模式中,主机以广播地址向所有从机发送请求,从机不会向主机返回应答,地址0为广播地址。

  主机的状态转换如图2.1所示,开始时主机处于“空闲”状态,主机发送一个请求报文后离开“空闲”状态,并且不能同时发送第二个请求报文。

图2.1 主机状态转换图

  主机发送一个单播请求报文后进入“等待应答”状态,同时启动一个超时定时器,避免主机一直处于“等待”状态,应答超时的时间取决于具体应用。
  当收到一个应答报文时,主机判断应答报文是否来自期望的节点,如果是非期望节点的应答报文(应答报文的地址与请求报文的地址不一致),超时定时器继续计时。
  如果是期望节点的应答报文(应答报文的地址与请求报文的地址一致),主机检测应答报文,如果检测到应答报文帧有错误,进入“出错处理”状态,出错处理结束后返回“空闲”状态,可以执行一个重试,重新发送之前的请求报文。
  如果等待应答出现超时,则产生一个错误,主机进入“出错处理”状态,出错处理结束后返回“空闲”状态,并执行一个重试,重试的最大次数取决于主机的设置。主机的应答超时时间必须设置足够大以便从机可以处理完请求并返回应答。
  当主机发送广播请求报文时,从机不会应答。主机需要延迟,以便所有从机处理完请求并可以接收新的请求,这个延迟称为转换延迟。

  从机的状态转换如图2.2所示,开始时从机处于“空闲”状态,当接收到一个请求报文后离开“空闲”状态,进入“检查请求”状态。

图2.2 从机状态转换图

  从机对请求报文进行检查,如果请求报文帧有错误或请求报文不是发给该从机,返回“空闲”状态;如果请求数据有错误,比如请求非法的操作,格式化异常应答并发送异常应答报文后,返回“空闲”状态。
  如果请求报文检查OK,进入“处理请求”状态。如果是广播请求,处理结束后直接返回“空闲”状态,如果是单播请求,处理结束后格式化正常应答并发送正常应答报文,返回“空闲”状态。如果单播请求处理时出错,格式化异常应答并发送异常应答报文后返回“空闲”状态。

3. 串行传输模式

  基于RS485的Modbus协议定义了两种串行传输模式:RTU模式和ASCII模式。总线上所有节点必须使用相同的串行传输模式。

3.1 RTU模式

3.1.1 字符帧

  RTU模式的字符帧格式如图3.1所示,1位起始位、8位数据位、1位校验位、1位停止位。校验位默认为偶校验,配置为无校验时要求有两个停止位。总线上所有节点必须使用相同的串行通信参数,包括字符帧格式和波特率。

图3.1 字符帧格式(RTU模式)

3.1.2 报文帧

  主机通过向从机发送请求报文,指示从机执行功能码定义的操作。请求报文帧格式如表3.1所示,如果是广播请求报文,地址为0,如果是单播请求报文,地址为从机的地址,功能码指示从机执行哪种操作,从机使用数据所提供的信息执行功能码定义的操作,CRC是报文内容的循环冗余校验值。

表3.1 主机的请求报文(RTU模式)


  从机根据请求报文执行操作,如果无差错,向主机返回一个正常应答,正常应答报文格式与请求报文格式相同,如表3.1所示,地址为从机自身的地址,功能码与请求报文的功能码相同,数据为从机的应答数据。

表3.2 从机的正常应答报文(RTU模式)


  如果出现某种差错,从机返回一个异常应答,异常应答报文如表3.3所示,地址为从机自身地址,功能码的最高有效位置1作为差错码(差错码 = 功能码 | 0x80),异常码指示差错的具体原因。

表3.3 从机的异常应答报文(RTU模式)

3.2 ASCII 传输模式

3.2.1 字符帧

  ASCII模式的字符帧格式如图3.2所示,1位起始位、7位数据位、1位校验位、1位停止位。校验位默认为偶校验,配置为无校验时要求有两个停止位。总线上所有节点必须使用相同的串行通信参数,包括字符帧格式和波特率。

图3.2 字符帧格式(ASCII模式)

3.2.2 报文帧

  ASCII模式下,主机的请求报文帧格式如表3.4所示,一个报文以冒号(´:´)字符开始,以回车(CR)、换行(LF)两个字符结束,´:´字符的16进制ASCII值为0x3A,回车和换行字符的16进制ASCII值分别为0x0D、0x0A。

表3.4 主机的请求报文(ASCII模式)

  报文中地址、功能码、数据、LRC的每个字节使用两个字符进行编码,例如地址的十六进制表示为0x5B,编码成´5´和´B´两个字符进行传输,从机接收报文后使用相同的规则进行解码。
  LRC是报文内容的纵向冗余校验值,一个字节长度,例如LRC的十六进制表示为0x18,编码成´1´和´8´两个字符进行传输。
从机的正常应答报文格式与请求报文格式相同,如表3.5所示,地址为从机自身的地址,功能码与请求报文的功能码相同,数据为从机的应答数据。

表3.5 从机的正常应答报文(ASCII模式)

  从机的异常应答报文如表3.6所示,功能码最高有效为置1作为差错码,异常码指示差错的具体原因。

表3.6 从机的异常应答报文(ASCII模式)

4. 常用功能码

 &esmp;介绍RTU模式下常用功能码对应的请求报文和应答报文。

4.1 读线圈寄存器

  使用功能码0x01读从机的线圈寄存器(离散量输出寄存器),主机的请求报文如表4.1所示。从给定的起始地址开始,连续读取一个或多个线圈寄存器,寄存器数量指示读取线圈寄存器的个数。

表4.1 读线圈寄存器的请求报文

  从机的应答报文如表4.2所示,字节数指示寄存器值所占的字节数,线圈寄存器是1位寄存器,寄存器值中的每一位对应一个线圈寄存器的值(0或1),寄存器值所占的字节数N = ⌈寄存器数量 / 8⌉,⌈ ⌉表示向上取整,当线圈寄存器的数量不是8的整数倍时,寄存器值的最后一个字节的剩余位用0填充。

表4.2 读线圈寄存器的正常应答报文

4.2 写单个线圈寄存器

  使用功能码0x05写从机的单个线圈寄存器(离散量输出寄存器),主机的请求报文如表4.3所示,常量值只能是0xFF00或0x0000,其它所有值均是非法的,常量值为0xFF00,表示线圈寄存器写1,常量值为0x0000,表示线圈寄存器写0。

表4.3 写单个线圈寄存器的请求报文

  从机的正常应答报文和主机的请求报文内容相同。

4.3 写多个线圈寄存器

  使用功能码0x0F写从机的多个线圈寄存器(离散量输出寄存器),主机的请求报文如表4.4所示,从给定的起始地址开始,连续写一个或多个线圈寄存器,寄存器数量指示写线圈寄存器的个数,字节数指示寄存器值所占的字节数,寄存器值中的每一位对应一个线圈寄存器的值,寄存器值所占的字节数N = ⌈寄存器数量 / 8⌉,⌈ ⌉表示向上取整,当线圈寄存器的数量不是8的整数倍时,用0填充寄存器值最后一个字节的未使用比特位。

表4.4 写多个线圈寄存器的请求报文

  从机应答报文如表4.5所示,地址、功能码、起始地址、寄存器数量字段的值与请求报文相同。

表4.5 写多个线圈寄存器的应答报文

4.4 读离散量输入寄存器

  使用功能码0x02读从机的离散量输入寄存器,离散量输入寄存器是1位寄存器,读离散量输入寄存器和读线圈寄存器的请求报文、应答报文格式相同。离散量输入寄存器是只读寄存器,主机只能读不能写。

4.5 读保持寄存器

  使用功能码0x03读从机的保持寄存器,请求报文如表4.6所示。从给定的起始地址开始,连续读取一个或多个保持寄存器,寄存器数量指示读取保持寄存器的个数。

表4.6 读保持寄存器的请求报文

  从机的正常应答报文如表4.7所示,字节数指示寄存器值所占的字节数,N为寄存器的数量,保持寄存器为16位寄存器,寄存器值中的每两个字节对应一个寄存器。

表4.7 读保持寄存器的正常应答报文

4.6 写单个保持寄存器

  使用功能码0x06写从机的单个保持寄存器,主机的请求报文如表4.8所示。

表4.8 写单个保持寄存器的请求报文

  从机的正常应答报文和主机的请求报文内容相同。

4.7 写多个保持寄存器

  使用功能码0x10写从机的多个保持寄存器,主机的请求报文如表4.9所示,N为寄存器的数量,寄存器值中的每两个字节对应一个寄存器。

表4.9 写多个保持寄存器的请求报文

4.8 读输入寄存器

  使用功能码0x04读从机的输入寄存器,输入寄存器是16位寄存器,读输入寄存器和读保持寄存器的请求报文、应答报文格式相同。输入寄存器是只读寄存器,主机只能读不能写。

物联沃分享整理
物联沃-IOTWORD物联网 » 使用RS485实现Modbus协议通信

发表评论