曹旭辉 发表于 2024-10-2 22:03:29

编译libmodbus库及使用

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 项目结构如下:
https://i-blog.csdnimg.cn/direct/5fcc8218153240e094022292a52cebca.png
在终端窗口的项目文件夹中执行make
https://i-blog.csdnimg.cn/direct/7857a122d8634fa59ed42205b91e2529.png
编译成功,生成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,
                                 tab_bits);
            }
            


            /* 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,
                              tab_bits);


                }
            }


            //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,
                            tab_registers);
            }
            


            /* 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,
                              tab_registers);


                }
            }
            // 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.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模拟器:
https://i-blog.csdnimg.cn/direct/08bd2f4a5b144f39ba7c2701273e30f8.png
把编译结果复制到开辟板上面:
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

Waiting for a confirmation...
<00><01><00><00><00><04><11><01><01><01>
Address = 0, value 1 (0x1) 

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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 编译libmodbus库及使用