编译libmodbus库及使用

打印 上一主题 下一主题

主题 771|帖子 771|积分 2313

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/binPATH
export LD_LIBRARY_PATH=/opt/arm-fsl-linux-gnueabi/libLD_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.编译源码:
进入源码文件夹:
  1. cd libmodbus
复制代码
运行automake  autoconfgure脚原来生成Makefile文件:
  1. ./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编译命令:
  1. make
复制代码
安装生成的库:
  1. make install
复制代码
做完上述步骤可以看见在"~/libmodbus_install"生成了头文件及库文件
dengxm2024@PC-202105142413:~/libmodbus_install$ ls
include  lib  share
3.使用上面输出的库
新建文件/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/version.c
  1. /*
  2. * Copyright © 2008-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdio.h>
  7. #include <modbus/modbus-version.h>
  8. #include <modbus/modbus.h>
  9. int main(void)
  10. {
  11.     printf("Compiled with libmodbus version %s (%06X)\n", LIBMODBUS_VERSION_STRING, LIBMODBUS_VERSION_HEX);
  12.     printf("Linked with libmodbus version %d.%d.%d\n",
  13.            LIBMODBUS_VERSION_MAJOR, LIBMODBUS_VERSION_MINOR, LIBMODBUS_VERSION_MICRO);
  14.     if (LIBMODBUS_VERSION_CHECK(2, 1, 0)) {
  15.         printf("The functions to read/write float values are available (2.1.0).\n");
  16.     }
  17.     if (LIBMODBUS_VERSION_CHECK(2, 1, 1)) {
  18.         printf("Oh gosh, brand new API (2.1.1)!\n");
  19.     }
  20.     return 0;
  21. }
复制代码
.新建/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/Makefile
  1. # 定义libmodbus库头文件的路径
  2. HEADERS_DIR := /home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/include
  3. # 添加头文件路径到编译器的搜索路径中
  4. CFLAGS += -I$(HEADERS_DIR)
  5. EXEC = ./version
  6. OBJS = version.o
  7. SRC  = version.c
  8. # 指定编译器前缀
  9. CC = $(CROSS_COMPILE)gcc
  10. LDFLAGS +=
  11. all:$(EXEC)
  12. $(EXEC):$(OBJS)
  13.         $(CC) $(LDFLAGS) -o $@ $(OBJS) -pthread
  14. %.o:%.c
  15.         $(CC) $(CFLAGS) -c $< -o $@ -pthread
  16. clean:
  17.         @rm -vf $(EXEC) *.o *~
复制代码
把库文件夹~/libmodbus_install复制到项目文件夹

  1. cp -r ~/libmodbus_install/ ~/linuxProgDir/imx280astudy/userside_code/libmodbustest
复制代码
项目结构如下:

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

编译成功,生成version可执行文件。
4.测试运行
将执行文件复制到开辟板当中测试运行。
复制version到web服务器
  1. cp version /mnt/d/imx280a_exe_folder/
复制代码
打开开辟板终端窗口,从web服务器获取version文件
  1. wget http://192.168.0.233:443/imx280a_exe_folder/version
复制代码
给version添加可执行属性
  1. chmod +x version
复制代码
执行version查看结果
  1. ./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
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <modbus/modbus.h>
  7. #include <modbus/modbus-tcp.h>
  8. #define LOOP          1
  9. #define SERVER_ID     17
  10. #define ADDRESS_START 0
  11. #define ADDRESS_END   9
  12. int main(void)
  13. {
  14.     modbus_t *ctx;
  15.     int rc;
  16.     int nb_fail;
  17.     int nb_loop;
  18.     int addr;
  19.     int nb;
  20.     uint8_t *tab_bits;
  21.     uint8_t *tab_in_bits;
  22.     uint16_t *tab_registers;
  23.     uint16_t *tab_in_registers;
  24.     ctx = modbus_new_tcp("192.168.0.233", 502);
  25.     modbus_set_slave(ctx, SERVER_ID);
  26.     modbus_set_debug(ctx, TRUE);
  27.     if (modbus_connect(ctx) == -1)
  28.     {
  29.         fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
  30.         modbus_free(ctx);
  31.         return -1;
  32.     }
  33.     /* Allocate and initialize the different memory spaces */
  34.     nb = ADDRESS_END - ADDRESS_START;
  35.     tab_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
  36.     memset(tab_bits, 0, nb * sizeof(uint8_t));
  37.     tab_in_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
  38.     memset(tab_in_bits, 0, nb * sizeof(uint8_t));
  39.     tab_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
  40.     memset(tab_registers, 0, nb * sizeof(uint16_t));
  41.     tab_in_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
  42.     memset(tab_in_registers, 0, nb * sizeof(uint16_t));
  43.     nb_loop = nb_fail = 0;
  44.     while (nb_loop++ < LOOP)
  45.     {
  46.         for (addr = ADDRESS_START; addr < ADDRESS_END; addr++)
  47.         {
  48.             int i;
  49.             nb = ADDRESS_END - addr;
  50.             /* read BIT */
  51.             
  52.             rc = modbus_read_bits(ctx, addr, 1, tab_bits);
  53.             if (rc != 1 )
  54.             {
  55.                 printf("ERROR modbus_read_bits single (%d)\n", rc);
  56.                 printf("address = %d\n", addr);
  57.                 nb_fail++;
  58.             }
  59.             else
  60.             {
  61.                 printf("Address = %d, value %d (0x%X) \n",
  62.                                    addr,
  63.                                    tab_bits[0],
  64.                                    tab_bits[0]);
  65.             }
  66.             
  67.             /* MULTIPLE BITS */
  68.             
  69.             rc = modbus_read_bits(ctx, addr, nb, tab_bits);
  70.             if (rc != nb)
  71.             {
  72.                 printf("ERROR modbus_read_bits\n");
  73.                 printf("Address = %d, nb = %d\n", addr, nb);
  74.                 nb_fail++;
  75.             }
  76.             else
  77.             {
  78.                 for (i = 0; i < nb; i++)
  79.                 {
  80.                     
  81.                         printf("Address = %d, value %d (0x%X) \n",
  82.                                 addr+i,
  83.                                 tab_bits[i],
  84.                                 tab_bits[i]);
  85.                 }
  86.             }
  87.             //read input bits
  88.             //modbus_read_input_bits
  89.             
  90.             /* SINGLE REGISTER */
  91.             rc = modbus_read_registers(ctx, addr, 1, tab_registers);
  92.             if (rc != 1)
  93.             {
  94.                 printf("ERROR modbus_read_registers single (%d)\n", rc);
  95.                 printf("Address = %d\n", addr);
  96.                 nb_fail++;
  97.             }
  98.             else
  99.             {
  100.                     printf("Address = %d, value = %d (0x%X) \n",
  101.                             addr,
  102.                             tab_registers[0],
  103.                             tab_registers[0]);
  104.             }
  105.             
  106.             /* MULTIPLE REGISTERS */
  107.             
  108.             rc = modbus_read_registers(ctx, addr, nb, tab_registers);
  109.             if (rc != nb)
  110.             {
  111.                 printf("ERROR modbus_read_registers (%d)\n", rc);
  112.                 printf("Address = %d, nb = %d\n", addr, nb);
  113.                 nb_fail++;
  114.             }
  115.             else
  116.             {
  117.                 for ( i = 0; i < nb; i++)
  118.                 {
  119.                         printf("Address = %d, value %d (0x%X) \n",
  120.                                 addr+i,
  121.                                 tab_registers[i],
  122.                                 tab_registers[i]);
  123.                 }
  124.             }
  125.             // read intput registers
  126.             //modbus_read_input_registers
  127.             sleep(5);
  128.         }
  129.         printf("Test: ");
  130.         if (nb_fail)
  131.             printf("%d FAILS\n", nb_fail);
  132.         else
  133.             printf("SUCCESS\n");
  134.     }
  135.     /* Free the memory */
  136.     free(tab_bits);
  137.     free(tab_in_bits);
  138.     free(tab_registers);
  139.     free(tab_in_registers);
  140.     /* Close the connection */
  141.     modbus_close(ctx);
  142.     modbus_free(ctx);
  143.     return 0;
  144. }
复制代码
上面的Makefile要修改一下了:
  1. # 定义libmodbus库头文件的路径
  2. HEADERS_DIR := /home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/include
  3. # 添加头文件路径到编译器的搜索路径中
  4. CFLAGS += -I$(HEADERS_DIR)
  5. #指定libmodbus库路径及库名称
  6. LDFLAGS += -L$(CURDIR)/libmodbus_install/lib -lmodbus
  7. #LDFLAGS += -L/home/dengxm2024/linuxProgDir/imx280astudy/userside_code/libmodbustest/libmodbus_install/lib -lmodbus
  8. #显式链接库
  9. #LDFLAGS += -lmodbus
  10. EXEC = ./modbustcpclient
  11. OBJS = modbustcpclient.o
  12. SRC  = modbustcpclient.c
  13. # 指定编译器前缀
  14. CC = $(CROSS_COMPILE)gcc
  15. LDFLAGS +=
  16. all:$(EXEC)
  17. $(EXEC):$(OBJS)
  18.         $(CC) $(LDFLAGS) -o $@ $(OBJS) -pthread
  19. %.o:%.c
  20.         $(CC) $(CFLAGS) -c $< -o $@ -pthread
  21. clean:
  22.         @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.a 或 libmodbus.so。
-l 后跟的参数通常是没有前导 lib 和后缀 .a 或 .so 的库名。比方,-lmodbus 实际上指向的是 libmodbus.a 或 libmodbus.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) 
已经通讯上了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表