一、知识点介绍
在Modbus TCP协议中,主站被称为客户端(Client),它是发起通讯的一方。主站的功能类似于RTU主站,会向从站(服务器)发起数据请求。主站通过TCP/IP协议与从站进行通讯,发送查询操作数据的请求,并接收从站返回的响应数据。主站可以同时与多个从站进行通讯,每个从站都有一个唯一的地址标识。在Modbus TCP协议中,主站可以通过IP地址和端口号来识别从站。
二、modbus tcp 主站
基于libmodbus开源库,编写modbus tcp的主站,读取bits和registers,测试代码如下:
#include <stdio.h>#include <unistd.h>#include<errno.h>#include<stdlib.h>#include<string.h>
#include<modbus.h>
#define LOOP 1#define SERVER_ID 17#define ADDRESS_START 0#define ADDRESS_END 9
intmain(void){modbus_t *ctx;int rc;int nb_fail;int nb_loop;int addr;int nb;uint8_t *tab_bits;uint8_t *tab_in_bits;uint16_t *tab_registers;uint16_t *tab_in_registers;
ctx = modbus_new_tcp("192.168.1.188", 1502); modbus_set_slave(ctx, SERVER_ID); modbus_set_debug(ctx, TRUE);
if (modbus_connect(ctx) == -1) {fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx);return-1; }
/* Allocate and initialize the different memory spaces */ nb = ADDRESS_END - ADDRESS_START;
tab_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));memset(tab_bits, 0, nb * sizeof(uint8_t));
tab_in_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));memset(tab_in_bits, 0, nb * sizeof(uint8_t));
tab_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));memset(tab_registers, 0, nb * sizeof(uint16_t));
tab_in_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));memset(tab_in_registers, 0, nb * sizeof(uint16_t));
nb_loop = nb_fail = 0;while (nb_loop++ < LOOP) {for (addr = ADDRESS_START; addr < ADDRESS_END; addr++) {int i;
nb = ADDRESS_END - addr;
/* read BIT */ rc = modbus_read_bits(ctx, addr, 1, tab_bits);if (rc != 1 ) {printf("ERROR modbus_read_bits single (%d)\n", rc);printf("address = %d\n", addr); nb_fail++; }else {printf("Address = %d, value %d (0x%X) \n", addr, tab_bits[0], tab_bits[0]); }
/* MULTIPLE BITS */ rc = modbus_read_bits(ctx, addr, nb, tab_bits);if (rc != nb) {printf("ERROR modbus_read_bits\n");printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else {for (i = 0; i < nb; i++) {printf("Address = %d, value %d (0x%X) \n", addr+i, tab_bits, tab_bits);
} }
//read input bits//modbus_read_input_bits
/* SINGLE REGISTER */ rc = modbus_read_registers(ctx, addr, 1, tab_registers);if (rc != 1) {printf("ERROR modbus_read_registers single (%d)\n", rc);printf("Address = %d\n", addr); nb_fail++; } else {printf("Address = %d, value = %d (0x%X) \n", addr, tab_registers[0], tab_registers[0]); }
/* MULTIPLE REGISTERS */ rc = modbus_read_registers(ctx, addr, nb, tab_registers);if (rc != nb) {printf("ERROR modbus_read_registers (%d)\n", rc);printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else {for ( i = 0; i < nb; i++) {printf("Address = %d, value %d (0x%X) \n", addr+i, tab_registers, tab_registers);
} }// read intput registers//modbus_read_input_registers
sleep(5); }
printf("Test: ");if (nb_fail)printf("%d FAILS\n", nb_fail);elseprintf("SUCCESS\n"); }
/* Free the memory */free(tab_bits);free(tab_in_bits);free(tab_registers);free(tab_in_registers);
/* Close the connection */ modbus_close(ctx); modbus_free(ctx);
return0;}
三、测试结果
打开modbus slave的测试软件,从站地址为0x11,配置如下:
modbus tcp主站,读取信息如下:
主站正确读取到了从站的信息。
欢迎关注公众号:嵌入式学习与实践 |