设计师自己的网站,网站做内容,下载安装注册app,网站做多少屏合适Part1前言 Modbus是一种通信协议#xff0c;用于在工业自动化领域中的电子设备之间进行通信。它最初是由Modicon在1979年创建的#xff0c;现在已经成为一种工业标准#xff0c;被广泛应用于工业控制系统、PLC#xff08;可编程逻辑控制器#xff09;和其他自动化设备。Mo… Part1前言 Modbus是一种通信协议用于在工业自动化领域中的电子设备之间进行通信。它最初是由Modicon在1979年创建的现在已经成为一种工业标准被广泛应用于工业控制系统、PLC可编程逻辑控制器和其他自动化设备。Modbus协议主要分为三种模式Modbus RTU、Modbus ASCII和Modbus TCP。其中Modbus RTU是一种串行通信模式基于二进制通信是应用最广泛的模式之一。在RTU协议中设备分为两种工作模式RTU Slave Mode和RTU Master Mode。在RTU Slave Mode下设备被动地等待RTU Master的请求并响应请求中包含的命令。在该模式下设备的主要任务是接收RTU Master发送的命令、执行这些命令并将执行结果发送回RTU Master。在RTU Slave Mode下设备通常会被编址以便RTU Master可以识别它们。在命令请求中RTU Master会指定要与哪个被编址的设备通信并提供要执行的命令和参数。设备接收到请求后会根据请求中提供的地址和命令执行相应的操作并将执行结果返回给RTU Master。在RTU Master Mode下设备主动向RTU Slave发送命令并等待响应。在该模式下设备的主要任务是发送命令、接收响应并解析响应中包含的数据。在RTU Master Mode下设备通常不需要编址因为它主动发起通信。设备向RTU Slave发送命令时会包含要执行的命令和参数以及RTU Slave的地址。RTU Slave接收到请求后会执行相应的操作并将执行结果发送回RTU Master。设备接收到响应后会解析响应中包含的数据并根据需要进行后续处理。 Part2Modbus Rtu介绍 Modbus Rtu通常由帧起始符、地址码、功能码、数据域、校验码、帧结束符组成。帧起始符和帧结束符在示例数据帧中没有显示通常由通信设备硬件电路自动添加。帧起始符Modbus RTU协议帧的起始符为一个11位长的标志位3.5个字符用于同步传输的时钟。地址码地址码表示Modbus RTU设备的从站地址或广播地址用于指定数据帧所要访问的设备或广播数据。功能码功能码用于定义数据帧所要进行的操作类型包括读取线圈状态、读取离散输入状态、读取保持寄存器、读取输入寄存器、写单个线圈、写单个保持寄存器等。数据域数据域是Modbus RTU协议帧中的核心部分用于传输数据信息。根据功能码的不同数据域可以包含读取或写入的数据信息以及校验码等。校验码校验码用于检验Modbus RTU协议帧中数据的准确性和完整性通常使用CRC校验码或LRC校验码。帧结束符帧结束符表示一个Modbus RTU协议帧的结束通常是一个长度为3.5个字符的静默时间用于指示下一帧数据的开始。 Part3python协议对接 为了能够快速的进行协议研究我们首先基于python的库进行研究。地址https://github.com/ljean/modbus-tk。 slave创建 import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus as modbus
from modbus_tk import modbus_tcp, hooks
import sysdef on_handle_write_single_register_request(args):response args[1]print(response)# 配置从站参数
server modbus_tcp.TcpServer(address127.0.0.1, port502)
# 启动从站
server.start()hooks.install_hook(modbus.Slave.handle_write_single_register_request,on_handle_write_single_register_request)
slave_1 server.add_slave(1)
slave_1.add_block(0, cst.HOLDING_REGISTERS, 0, 255)
slave_1.set_values(0, 0, 1234)# 响应主站请求
while True:name input()break# 停止从站
server.stop() slave主要功能有两点1、设置寄存器的值主站查询的时候直接会应答 示例如slave_1.set_values(0, 0, 1234)2、接收主站的请求并进行相关处理这里通过绑定一个回调函数的形式来实现。 hooks.install_hook(modbus.Slave.handle_write_single_register_request,on_handle_write_single_register_request) master创建 import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_tcp# 建立TCP连接
master modbus_tcp.TcpMaster(host127.0.0.1, port502)
master.set_timeout(5.0)# 读取保持寄存器数据
start_address 0
number_of_registers 9
values master.execute(1, cst.READ_HOLDING_REGISTERS,start_address, number_of_registers)# 打印保持寄存器数据
print(values)start_address 1
ret master.execute(1, cst.WRITE_SINGLE_REGISTER,start_address, output_value8)# 关闭连接
master.close() master主要功能也是两点1、读取子站寄存器的值通过values master.execute(1, cst.READ_HOLDING_REGISTERS, start_address, number_of_registers)2、写入子站寄存器值通过ret master.execute(1, cst.WRITE_SINGLE_REGISTER, start_address, output_value8)这里写入之后在上面的子站中就是回调函数那里进行处理。 Part4C对接 由于虚幻引擎运行时不支持python对接所以我们还需要寻找一个C的库来方便集成。这里推荐下面的库https://github.com/stephane/libmodbus 这个库支持windows编译编译步骤如下1、在src/win32目录下运行nodejs脚本cscript configure.js2、拷贝modbus-version.h文件到win32文件夹下面3、添加ws2_32.lib依赖库4、将其编译为动态库即可默认的编译会有不少函数定义的告警这里需要在预编译处理的地方增加一个dll导出的宏。示例如下 编译好之后就可以使用了。这里针对不同寄存器的操作需要调用不同的函数。这里的寄存器对应于协议里面的就是功能码。如下所示 /** modbus_read_bits 读线圈 fc1* modbus_read_input_bits 读输入线圈 fc2* modbus_read_registers 读取保持寄存器 fc3* modbus_read_input_registers 读输入寄存器 fc4* modbus_write_bit 写一位数据强置单线圈 fc5* modbus_write_register 写单寄存器预置单寄存器 fc6* modbus_write_bits 写多位数据强置多线圈 fc15* modbus_write_and_read_registers 读/写多个寄存器 fc23*/ 这里写了一个master的主站程序示例如下 #include modbus.h
#include stdio.hint main(int argc, char *argv[])
{modbus_t *ctx nullptr;uint16_t tab_reg[64];int rc 0;// 创建TCP连接的Master上下文环境ctx modbus_new_tcp(192.168.0.1, 502);if (ctx NULL){fprintf(stderr, Unable to create modbus context\n);return -1;}// 连接到Slave设备if (modbus_connect(ctx) -1){fprintf(stderr, Unable to connect to modbus server\n);modbus_free(ctx);return -1;}// 读取Slave设备上的寄存器数据rc modbus_read_registers(ctx, 0, 64, tab_reg);if (rc -1){fprintf(stderr, Unable to read registers\n);modbus_close(ctx);modbus_free(ctx);return -1;}// 输出读取到的数据for (int i 0; i 64; i){printf(reg[%d]%d\n, i, tab_reg[i]);}// 断开与Slave设备的连接modbus_close(ctx);modbus_free(ctx);return 0;
} Part5总结 本文主要介绍了基于python和C的开源库来实现modbus协议。 Part6Inveta团队 Inveta团队由研发、美术设计、建模等组成。团队介绍:https://www.inveta.cn/about.html团队开源项目https://github.com/inveta