编译libmodbus库及使用
创始人
2024-09-25 07:23:39
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   *  * SPDX-License-Identifier: BSD-3-Clause  */  #include  #include  #include   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  #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.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><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) 

已经通讯上了。

相关内容

热门资讯

安卓系统可以分享视频吗,安卓系... 你有没有想过,手机里的视频怎么才能和朋友一起分享呢?尤其是当你发现了一个超级搞笑的短视频,或者是一部...
安卓系统上安装pc软件,跨平台... 你是不是也和我一样,对安卓系统上的那些PC软件垂涎欲滴呢?想象在手机上就能享受到电脑上的强大功能,是...
安卓原生系统怎么折腾,深度定制... 你有没有想过,你的安卓手机其实就像一个等待你发挥创意的画布呢?没错,就是那个安卓原生系统,它可是隐藏...
安卓作业系统耗电,深度解析耗电... 手机电量告急,是不是你也和我一样,对安卓作业系统的耗电问题头疼不已?别急,今天就来聊聊这个让人又爱又...
宝宝浙江游戏安卓系统,乐享童年 最近有没有发现你家的小宝贝对手机上的游戏越来越感兴趣了呢?尤其是那些在浙江地区特别受欢迎的安卓系统游...
安卓系统程序放在那,安卓系统程... 你有没有发现,手机里的安卓系统程序总是乱糟糟的,有时候找起来就像大海捞针一样?别急,今天就来给你揭秘...
手表怎么装上安卓系统,轻松安装... 你有没有想过,你的安卓手机那么智能,那你的手表呢?是不是也想给它来个升级,让它也能玩转各种应用,变身...
碧蓝航线在安卓系统,安卓平台上... 你知道吗?最近在安卓系统上,有一款游戏可是火得一塌糊涂,那就是《碧蓝航线》!这款游戏不仅画面精美,剧...
安卓系统设置分辨率,解锁屏幕显... 亲爱的手机控们,你是不是也和我一样,对手机屏幕的分辨率有着超乎寻常的执着呢?分辨率,这个看似简单的数...
安卓超市收银系统下载,高效便捷... 你有没有想过,逛超市的时候,收银员那熟练的操作是不是让你也跃跃欲试呢?现在,机会来了!安卓超市收银系...
安卓系统升级清理,深度清理与性... 亲爱的手机控们,你是不是也和我一样,对安卓系统的升级清理充满了好奇和期待呢?每次系统更新,都仿佛是给...
安卓如何绕过系统安装,深度解析... 你是不是也和我一样,对安卓系统的安装限制感到有些头疼?有时候,我们可能需要安装一些特殊的软件或者游戏...
安卓系统跟linux系统怎么样... 你有没有想过,你的手机里那个默默无闻的安卓系统,和电脑上那个稳如泰山的Linux系统,它们之间到底有...
凤凰系统用安卓软件很卡,凤凰系... 最近是不是发现你的凤凰系统用安卓软件时总是卡得要命?别急,让我来给你细细道来,看看这其中的原因和解决...
安卓系统怎么玩脸书,脸书应用攻... 你有没有想过,在安卓系统上怎么玩转脸书呢?这个全球最大的社交平台,可是让很多人沉迷其中哦!别急,今天...
虚拟机系统安卓11,虚拟机系统... 你有没有想过,手机里的安卓系统竟然也能变成电脑上的虚拟机?没错,就是那个我们每天不离手的安卓11系统...
钻石vip微信安卓系统,畅享无... 你知道吗?在微信这个庞大的社交世界里,钻石VIP可是个让人羡慕的身份呢!尤其是对于那些安卓系统的用户...
安装安卓系统后蓝屏,安卓系统安... 你刚刚升级了安卓系统,是不是觉得自己的手机焕然一新,充满了科技感?就在你沉浸在新系统的美好体验中时,...
安卓系统如何调出返回键,安卓系... 你是不是也和我一样,有时候在使用安卓手机时,突然发现那个神秘的返回键怎么就消失了?别急,今天就来手把...
荣耀8安装原生安卓系统,体验纯... 你有没有想过,让你的荣耀8手机焕发新生?别再让它被那些臃肿的第三方系统拖累啦!今天,就让我带你一起探...