一、知识点介绍
在Modbus TCP协议中,主站被称为客户端(Client),它是发起通讯的一方。主站的功能类似于RTU主站,会向从站(服务器)发起数据请求。主站通过TCP/IP协议与从站进行通讯,发送查询操作数据的请求,并接收从站返回的响应数据。主站可以同时与多个从站进行通讯,每个从站都有一个唯一的地址标识。在Modbus TCP协议中,主站可以通过IP地址和端口号来识别从站。
二、modbus tcp 主站
基于libmodbus开源库,编写modbus tcp的主站,读取bits和registers,测试代码如下:
#include
#include
#include
#include
#include
#include
#define LOOP 1
#define SERVER_ID 17
#define ADDRESS_START 0
#define ADDRESS_END 9
int main(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[i],
tab_bits[i]);
}
}
//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[i],
tab_registers[i]);
}
}
// read intput registers
//modbus_read_input_registers
sleep(5);
}
printf("Test: ");
if (nb_fail)
printf("%d FAILS\n", nb_fail);
else
printf("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);
return 0;
}
三、测试结果
打开modbus slave的测试软件,从站地址为0x11,配置如下:
modbus tcp主站,读取信息如下:
主站正确读取到了从站的信息。
欢迎关注公众号:嵌入式学习与实践