modbus tcp协议中可以实现双向通讯嘛?

在使用modbus tcp的通讯协议中,主站与从站之间是否可以双向通讯,主可以读写从的数据,从站也可以读取主的数据?这样可以实现吗?

modbus不支持从站读写主站哦!只有主站读写从站哦!

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7633005
  • 你也可以参考下这篇文章:modbus tcp数据报文结构
  • 除此之外, 这篇博客: 组态王如何获取modbus TCP数据?中的 3、新建一个画面 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    在这里插入图片描述

  • 您还可以看一下 许孝刚老师的Modbus协议讲解及实现课程中的 Modbus TCP协议实战1小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    根据参考资料,可以得知modbus tcp协议在读写寄存器和线圈数据时都采用功能码,而从站只能响应主站的请求,不能主动向主站发送数据。因此,在modbus tcp协议中,实现主站与从站之间的双向通讯需要主站和从站分别实现对方所需的请求和响应。具体步骤如下:

    1. 主站向从站发送请求,请求从站读取或写入数据。
    2. 从站接收到主站的请求后,根据请求的功能码和寄存器地址,读取或写入相应的数据,并将读取的数据或写入是否成功的结果发送给主站。
    3. 主站接收到从站发送的响应后,根据响应的结果进行相应的操作,如读取数据并展示,或者重新发送请求。

    具体实现可以参考以下代码:

    # 主站代码:
    
    import socket
    
    # 主站可写寄存器的地址和数据
    write_addr = 0x0000
    write_data = 0x1234
    
    # 连接从站
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('从站IP', 502))
    
    # 向从站发送写寄存器的请求,功能码为0x10
    request = bytearray([0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, write_addr >> 8, write_addr & 0xFF, 0x02, write_data >> 8, write_data & 0xFF])
    client.send(request)
    
    # 接收从站的响应,响应的前7个字节与请求的相同
    response = client.recv(1024)
    if response[7] == 0x10:  # 判断响应的功能码是否为0x10
        if response[8:10] == bytearray([write_addr >> 8, write_addr & 0xFF]):  # 判断写入寄存器的地址是否正确
            if response[-2:] == bytearray([0x00, 0x00]):  # 判断写入是否成功
                print("写入成功")
            else:
                print("写入失败")
        else:
            print("寄存器地址错误")
    else:
        print("响应功能码错误")
    
    # 向从站发送读寄存器的请求,功能码为0x03
    request = bytearray([0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, write_addr >> 8, write_addr & 0xFF])
    client.send(request)
    
    # 接收从站的响应,响应的前7个字节与请求的相同
    response = client.recv(1024)
    if response[7] == 0x03:  # 判断响应的功能码是否为0x03
        data = (response[-2] << 8) + response[-1]  # 读取寄存器的数据
        print("读取到的数据为:", data)
    else:
        print("响应功能码错误")
    
    # 断开与从站的连接
    client.close()
    
    # 从站代码:
    
    from pyModbusTCP.server import ModbusServer, DataBank
    
    # 从站读写寄存器的地址和数据
    write_addr = 0x0000
    write_data = 0x5678
    
    # 初始化寄存器
    DataBank.set_words(write_addr, [0x0000])
    
    # 定义从站处理请求的回调函数
    def on_modbus_request(mb_request):
        global write_addr, write_data
        function_code = mb_request[7]
        start_addr = (mb_request[8] << 8) + mb_request[9]
        register_num = (mb_request[10] << 8) + mb_request[11]
        if function_code == 0x03:  # 读取保持寄存器
            data = DataBank.get_words(start_addr, register_num)
            return bytearray([0x00, mb_request[1], 0x00, 0x00, len(data) * 2 + 2, mb_request[6], mb_request[7], len(data) * 2] + data)
        elif function_code == 0x10:  # 写入多个寄存器
            if start_addr == write_addr and register_num == 1:  # 判断写入的地址和寄存器数量是否正确
                write_data = (mb_request[-4] << 8) + mb_request[-3]
                DataBank.set_words(write_addr, [write_data])
                return bytearray([0x00, mb_request[1], 0x00, 0x00, 0x00, mb_request[6], mb_request[7], 0x00])
            else:
                return bytearray([0x80 + function_code, mb_request[1]])
        else:
            return bytearray([0x80 + function_code, mb_request[1]])
    
    # 启动从站并监听端口
    server = ModbusServer('从站IP', 502, on_modbus_request)
    server.start()
    

    在以上代码中,主站先向从站发送一个写寄存器的请求,将数据0x1234写入寄存器0x0000中,并根据从站的响应结果判断写入是否成功。随后向从站发送一个读寄存器的请求,读取寄存器0x0000的数据,并将数据展示出来。从站接收到请求后,根据请求中的功能码和寄存器地址,读取或写入相应的数据,并将结果发送给主站。

    需要注意的是,在实际应用中,需要自行修改代码中的IP地址和寄存器地址,以适配具体的硬件设备。另外,使用软件模拟时,可以使用nodbus-TCP client Tester来模拟更多的线圈或者寄存器,来测试程序的正确性。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^