zoukankan      html  css  js  c++  java
  • Modbus串行通信

    一、Modbus通信协议简介

    1. Modbus协议      

           Modbus 是一个请求/应答协议,并且提供功能码规定的服务。Modbu协议是 OSI 模型第 7 层上的应用层报文传输协议。

           MODBUS协议支持传统的RS-232、RS-422、RS-485和以太网设备。

    Modbus 协议定义了一个与基础通信层无关的简单协议数据单元(PDU)。特定总线或网络上的 Modbus 协议映射能够在应用数据单元(ADU)上引入一些附加域。

          Modbus的数据包格式为:

    2. 串行Modbus协议

           在物理层,Modbus 串行链路系统可以使用不同的物理接口(RS485、RS232)。支持RS485两线制与四线制接口,当只需要短距离的点到点通信时,RS232 串行接口也可以使用。

    串行通信栈对应与OSI七层协议的关系:

    2.1 Modbus主站/从站协议

             Modbus 串行链路协议是一个主-从协议。 在同一时刻,只有一个主节点连接于总线,一个或多个子节点 (最大编号为 247 ) 连接于同一个串行总线。子节点之间从不会互相通信。

    主节点有两种方式与子节点发出请求:

          (1) 单播模式 :点对点发送,主节点发送请求,子节点回应。

          (2) 广播模式 :广播发送,主节点发送,子节点不回应。

    Modbus串行链路PDU构成如下:

     

    二、 Modbus( 串行)开源库代码学习

    1. Modbus主节点与子节点的状态

    1.1主节点状态

     

    1.2 子节点状态

     

    2. Modbus协议源代码简介

    2.1 关于modbus中的常见两种寄存器区别

            保持寄存器:指可以通过通信命令读或者写的寄存器;通常是一些功能控制寄存器或者输出寄存器等。不同的设计中,有些保持寄存器是掉电保持;有些则不然。

            输入寄存器:指只能读不能写的寄存器,通常是状态寄存器或者是输入结果寄存器等。

            线圈寄存器,可以类比为开关量,每一个bit都对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。

            离散输入寄存器:相当于线圈寄存器的只读模式,每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,无法写入。

    2.2  Modbus开源库常用配置接口

    1)modbus_t* modbus_new_rtu(const char *device,

                             int baud, char parity, int data_bit,

                             int stop_bit)

    modbus_new_rtu函数用于生成Modbus的句柄,在本函数中可以设置通

    信协议中的波特率、校验位、数据长度以及停止位,其返回值为通过设置后生成的句柄,用于在读写数据时使用,每个句柄可以执行一个modbus指令。如果这些配置参数有误,就会返回一个空指针。

    2)static int _modbus_rtu_connect(modbus_t *ctx)

           本函数主要功能是将通信串口设置为rtu模式。

    3)int modbus_set_slave(modbus_t *ctx, int slave)

            本函数设置本句柄的从机号。

    2.3 Modbus主机通信常用接口

    1)int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)

            本函数为将数组中的数据写入到远端设备(从机)的寄存器中,写入的地址位addr,长度为nb个寄存器。

    2)int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)

            本函数将远端设备(从机)保持寄存器中的数据复制到数组dest中。

    3)int modbus_read_input_registers(modbus_t *ctx, int addr, int nb,

                                    uint16_t *dest)

             本函数读取远端设备(从机)地址为addr输入寄存器中的数据,数据长度为nb。

    2.4 Modbus从机通信主要接口

    1)int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)

            本函数可以用于处理来自主机的请求,返回接受到的字符的数量,如果成功,则返回uint8_t数组中的消息(即主机发送的命令),否则返回-1。

    2)int modbus_reply(modbus_t *ctx, const uint8_t *req,

                     int req_length, modbus_mapping_t *mb_mapping)

           本函数负责在接受到请求后,分析请求并生成响应消息,并且发送到主机。如果请求属性为广播,那么不发送响应消息。

    三、 调试问题分享

      在调试中,从机的Server进程会经常出现崩溃,最后发现在Server经常每次处理配置变更时,都会重新new出新的modbus句柄,但却不释放原有句柄,这种处理会导致多次修改Modbus通信配置时,从机Server进程崩溃。

             解决方案:在程序中判断,当modbus句柄已经存在时,此时更新配置后,不再new出新的句柄,而是调用接口 modbus_close(), modbus_free()释放句柄中的配置,然后用更新后的配置重新设置句柄参数。

  • 相关阅读:
    react 性能优化
    JS获取当前网页大小以及屏幕分辨率等
    创建对象的6种方式总结
    版本号规则
    JS事件模型
    浅谈虚拟DOM
    浏览器的回流与重绘
    JavaScript预编译
    canvas学习笔记
    java、tomcat安装
  • 原文地址:https://www.cnblogs.com/yuemw/p/9955131.html
Copyright © 2011-2022 走看看