编译libmodbus库及使用

avatar
作者
筋斗云
阅读量:0

1.下载源码

cd ~

git clone https://gitee.com/changser/libmodbus

2.设置编译环境:

打开“~/.bashrc"文件,在最后行添加,以便导入编译器常用的环境变量

export KERNELDIR=/home/dengxm2024/linuxProgDir/linuxkerneldir/linux-2.6.35.3
export CROSS_COMPILE=arm-fsl-linux-gnueabi-
export ARCH=arm
export PATH=/opt/arm-fsl-linux-gnueabi/bin:$PATH
export LD_LIBRARY_PATH=/opt/arm-fsl-linux-gnueabi/lib:$LD_LIBRARY_PATH
export CC=arm-fsl-linux-gnueabi-gcc
export CXX=arm-fsl-linux-gnueabi-g++
export AR=arm-fsl-linux-gnueabi-ar
export RANLIB=arm-fsl-linux-gnueabi-ranlib
export NM=arm-fsl-linux-gnueabi-nm
export LD=arm-fsl-linux-gnueabi-ld
export STRIP=arm-fsl-linux-gnueabi-strip

2.编译源码:

进入源码文件夹:

cd libmodbus

运行automake  autoconfgure脚本来生成Makefile文件:

./configure --host=arm-fsl-linux-gnueabi --enable-static --prefix=/home/dengxm2024/libmodbus_install/

--host=arm-fsl-linux-gnueabi   指定交叉编译器的前缀

--enable-static  静态编译

prefix=/home/dengxm2024/libmodbus_install/  指定库编译完成后的编译结果存放的路径

运行CMAKE编译命令:

make

安装生成的库:

make install

做完上述步骤可以看见在"~/libmodbus_install"生成了头文件及库文件

dengxm2024@PC-202105142413:~/libmodbus_install$ ls
include  lib  share

3.使用上面输出的库

新建文件/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/version.c

/*  * Copyright © 2008-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>  *  * SPDX-License-Identifier: BSD-3-Clause  */  #include <stdio.h> #include <modbus/modbus-version.h> #include <modbus/modbus.h>  int main(void) {     printf("Compiled with libmodbus version %s (%06X)\n", LIBMODBUS_VERSION_STRING, LIBMODBUS_VERSION_HEX);     printf("Linked with libmodbus version %d.%d.%d\n",            LIBMODBUS_VERSION_MAJOR, LIBMODBUS_VERSION_MINOR, LIBMODBUS_VERSION_MICRO);      if (LIBMODBUS_VERSION_CHECK(2, 1, 0)) {         printf("The functions to read/write float values are available (2.1.0).\n");     }      if (LIBMODBUS_VERSION_CHECK(2, 1, 1)) {         printf("Oh gosh, brand new API (2.1.1)!\n");     }      return 0; } 

.新建/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/Makefile

# 定义libmodbus库头文件的路径 HEADERS_DIR := /home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/include  # 添加头文件路径到编译器的搜索路径中 CFLAGS += -I$(HEADERS_DIR)  EXEC = ./version  OBJS = version.o SRC  = version.c # 指定编译器前缀 CC = $(CROSS_COMPILE)gcc  LDFLAGS +=   all:$(EXEC)  $(EXEC):$(OBJS) 	$(CC) $(LDFLAGS) -o $@ $(OBJS) -pthread  %.o:%.c 	$(CC) $(CFLAGS) -c $< -o $@ -pthread  clean: 	@rm -vf $(EXEC) *.o *~

把库文件夹~/libmodbus_install复制到项目文件夹

cp -r ~/libmodbus_install/ ~/linuxProgDir/imx280astudy/userside_code/libmodbustest

项目结构如下:

在终端窗口的项目文件夹中执行make

编译成功,生成version可执行文件。

4.测试运行

将执行文件复制到开发板当中测试运行。

复制version到web服务器

cp version /mnt/d/imx280a_exe_folder/

打开开发板终端窗口,从web服务器获取version文件

wget http://192.168.0.233:443/imx280a_exe_folder/version

给version添加可执行属性

chmod +x version

执行version查看结果

./version

root@EasyARM-iMX28x ~# ./version
Compiled with libmodbus version 3.1.4 (030104)
Linked with libmodbus version 3.1.4
The functions to read/write float values are available (2.1.0).
Oh gosh, brand new API (2.1.1)!

至此,使用libmodbus库进行开发的初步步骤就完成了。

测试modbus主站代码:

/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/modbustcpclient.c

#include <stdio.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <string.h>     #include <modbus/modbus.h> #include <modbus/modbus-tcp.h>   #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.0.233", 502);     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; }

上面的Makefile要修改一下了:

# 定义libmodbus库头文件的路径 HEADERS_DIR := /home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/include  # 添加头文件路径到编译器的搜索路径中 CFLAGS += -I$(HEADERS_DIR)   #指定libmodbus库路径及库名称 LDFLAGS += -L$(CURDIR)/libmodbus_install/lib -lmodbus #LDFLAGS += -L/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/lib -lmodbus #显式链接库 #LDFLAGS += -lmodbus EXEC = ./modbustcpclient OBJS = modbustcpclient.o SRC  = modbustcpclient.c # 指定编译器前缀 CC = $(CROSS_COMPILE)gcc  LDFLAGS +=   all:$(EXEC)  $(EXEC):$(OBJS) 	$(CC) $(LDFLAGS) -o $@ $(OBJS) -pthread  %.o:%.c 	$(CC) $(CFLAGS) -c $< -o $@ -pthread  clean: 	@rm -vf $(EXEC) *.o *~

#指定libmodbus库路径及库名称
LDFLAGS += -L$(CURDIR)/libmodbus_install/lib -lmodbus

这步很重要。

$(CURDIR)是Makefile文件所在路径。

在使用 GCC(GNU Compiler Collection)或类似的编译器进行链接时,-l 选项用于指定要链接的库。具体来说,-lmodbus 告诉链接器要链接名为 libmodbus 的库。

当你使用 -l 选项时,编译器会查找一个名为 lib[库名].a 的静态库或 lib[库名].so 的共享库(取决于你的系统配置和库的类型)。在你给出的例子中,-lmodbus 将查找 libmodbus.alibmodbus.so

-l 后跟的参数通常是没有前导 lib 和后缀 .a.so 的库名。例如,-lmodbus 实际上指向的是 libmodbus.alibmodbus.so

此外,-L 选项用于指定链接器搜索库的附加目录。在你的例子中,-L/path/to/libmodbus/lib 告诉链接器在 /path/to/libmodbus/lib 目录下查找库文件。如果省略 -L 选项,链接器将只在标准系统库目录中搜索。

因此,arm-linux-gnueabihf-gcc -o myapp myapp.c -L/path/to/libmodbus/lib -lmodbus 这条命令的意思是:

  • 使用 arm-linux-gnueabihf-gcc 编译器(一个针对 ARM 架构的交叉编译器)。
  • 将 myapp.c 源文件编译并链接成一个可执行文件,输出文件名为 myapp
  • 在链接阶段,链接器会额外搜索 /path/to/libmodbus/lib 目录。
  • 链接名为 modbus 的库(即 libmodbus.a 或 libmodbus.so)。

确保 -L-l 选项正确使用,是确保程序可以正确链接到所需库的关键。如果链接器找不到指定的库,你将收到类似 "undefined reference" 的链接错误。

编译测试:

modbus模拟器:

把编译结果复制到开发板上面:

libmodbus.a         libmodbus.so        libmodbus.so.5.1.0
libmodbus.la        libmodbus.so.5      pkgconfig

把库文件的动态链接库复制到开发板/usr/lib里面,运行时需要调用

root@EasyARM-iMX28x ~# ./modbustcpclient 
Connecting to 192.168.0.233:502
[00][01][00][00][00][06][11][01][00][00][00][01]
Waiting for a confirmation...
<00><01><00><00><00><04><11><01><01><01>
Address = 0, value 1 (0x1) 
[00][02][00][00][00][06][11][01][00][00][00][09]
Waiting for a confirmation...
<00><02><00><00><00><05><11><01><02><DF><01>
Address = 0, value 1 (0x1) 
Address = 1, value 1 (0x1) 
Address = 2, value 1 (0x1) 
Address = 3, value 1 (0x1) 
Address = 4, value 1 (0x1) 
Address = 5, value 0 (0x0) 
Address = 6, value 1 (0x1) 
Address = 7, value 1 (0x1) 
Address = 8, value 1 (0x1) 

已经通讯上了。

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!