工作项目中,机器人要完成一个电源管理的功能,自带可充电触点接触充电的电池,具体参数不表,代码要完成通过无线网络与西门子的PLC通信,从而控制充电房的开门与关门,以及控制充电处的继电器的开启与关闭,协议是modbus-tcp
。因此在网上找来好用的开源库——libmodbus
。记录下简单使用过程。
下载地址:
download 选择v3.0.6长期稳定版
本文分为以下部分:
下载完压缩包放至/home
目录下,解压:
tar -zxvf libmodbus-3.0.6.tar.gz
进入libmodbus-3.0.6
目录:
cd libmodbus-3.0.6
配置:
./configure
编译与安装:
make && make install
demo:
modbus_t *mb;
uint16_t tab_reg[32];
mb = modbus_new_tcp("127.0.0.1", 1502);
modbus_connect(mb);
/* Read 5 registers from the address 0 */
modbus_read_registers(mb, 0, 5, tab_reg);
modbus_close(mb);
modbus_free(mb);
测试modbus-tcp协议通信,代码里使用本地回环地址,端口1502:
进入tests目录打开一个终端,启动server程序:
./unit-test-server tcp
在目录打开另一个终端,启动client程序:
./unit-test-client tcp
启动会打印出很多信息。
而自己使用也需要精简例子代码,并按实际需要更改ip和端口:
在libmodbus-3.0.6
目录下新建一个mytest目录。
mkdir mytest
将所需头文件拷入,头文件均位于目录src
中:
cp modbus.h modbus-rtu.h modbus-tcp.h ../mytest
进入该目录:
cd mytest
创建自己代码main.c
如下:
#include
#include
#include
#include
#include
#include
#include
const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x1;
const uint16_t UT_BITS_ADDRESS = 0x04;
const uint16_t UT_INPUT_REGISTERS_NB = 0xA;
const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A };
int main(int argc, char const *argv[])
{
int nb = 0x25;
int rc = 0;
modbus_t *ctx;
uint8_t *tab_rp_bits;
tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
ctx = modbus_new_tcp("192.168.1.120", 502);
if(ctx == NULL)
{
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}
if(modbus_connect(ctx) == -1)
{
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
while(1)
{
rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, 1);
if (rc != 1)
{
printf("FAILED (nb points %d)\n", rc);
}
rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
printf("modbus_read_bits 1 \n modbus_read_bits: \n");
if (rc != 1)
{
printf("FAILED (nb points %d)\n", rc);
}
printf("tab_rp_bits [0] is %d\n",tab_rp_bits[0]);
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
sleep(1);
rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, 0);
if (rc != 1)
{
printf("FAILED (nb points %d)\n", rc);
}
rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
printf("modbus_read_bits 0 \n modbus_read_bits: \n");
if (rc != 1)
{
printf("FAILED (nb points %d)\n", rc);
}
printf("tab_rp_bits [0] is %d\n",tab_rp_bits[0]);
sleep(1);
}
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
ip 192.168.1.120
端口 502
上述代码功能是:控制读写地址为0x04位的coil status
状态,使其不停的反转,在PLC上表现就是指示灯的闪烁。
编译:
cc -o main main.c -lmodbus -I ./
如果链接不过,报错缺so文件,就找到相关的so文件,并复制到/usr/local/lib
目录下,并运行ldonfig
。
运行:
./main