0


Ubuntu下libmodbus的应用

写在文章最开头简单介绍一下,我这篇文字是基于什么背景而写下的,以便各位能更快速地判断本文是否符合您的需要。

文章背景:目前我自己本人是一名大四学生,由于近期在做毕业设计,需要在linux系统下读取一款压力传感器的数值,这款传感器采用了RS485转USB连接到电脑,想要读取传感器数据,就需要通过电脑向传感器发送读取指令(例如:FE 04 00 00 00 01 25 C5),传感器会返回相同格式的一串指令(地址码+功能码+数据区+校验码),由于我做的项目是一个大型项目的一个小分支,我需要读取这个数据,并且可以使用。如果仅仅是为了看到显示的数值,可以尝试使用带CRC校验的串口助手。

接下来我将进入正体和大家分享一下自己如何在ubuntu20.04上下载并应用libmodbus库读取传感器数据。

1.下载libmodbus库

安装建议参考这篇文章:

Linux编译安装libmodbus库_一只嵌入式爱好者的博客-CSDN博客_安装libmodbus

按照这个文章安装下来,至于后面的使用部分,文章写的多少有点玄学,并且有点跨度较大,难以理解,只要执行到sudo make install就可以了。至于安装上之后是否真的有用,我觉得应该作为一个环境放在系统里,虽然我没有引用下载下来的头文件,因为引用的时候,总是会在响应时间那里报错。个人建议自己重新按照CMake,将所有文件重新编译一次生成一个新的so库和头文件,特别是从站地址大于247的情况,可以通过修改modbus_rtu.c文件下的一个参数,将247修改为255就可以实现从站地址的扩充,因为libmodbus库默认的范围到247。

2.学习CMake

http://file.ncnynl.com/ros/CMake%20Practice.pdf

下载下来这篇文章,跟着里面的步骤从t1做到t4,并且自己适当扩展一下,因为后面我们所有需要用的东西都得依靠CMake。

这里是一个错误,需要将括号里的内容修改为hello ${SRC_LIST}

4.按照CMake编译一个新的libmodbus库(因为我自己的传感器从站地址是254,需要修改)

链接: https://pan.baidu.com/s/1n-sFp6sAPbZa4c-7lm6-BQ 提取码: l900

这是我自己开发所需要的文档之类的其中:

(1)有重要的头文件放在h文件夹里,下载好的libmodbus库只有四个头文件没有config.h,这个头文件是我从windows系统上安装libmodbus做测试的时候,在VS上编译生成dll库的时候,在x64文件家里找到的,抱着试试看的心理复制到了ubuntu上,发现可以使用。

(2)C和C++两个文件夹放了我自己写的两种语言版本的程序,我自己测试后都是可以直接运行的。

(3)modbus文件夹放置了修改libmodbus库所需要的c文件和h文件,编译该文件夹之后会在你学习CMake时生成libhello.so的地方生成libmodbus.so这一步一定要做,通过指令下载的libmodbus库会遇到这一段程序报错。

struct timeval t;
          t.tv_sec=0;
          t.tv_usec=1000000;        //set modbus time 1000ms
          modbus_set_response_timeout(ctx,&t);

提取出文档之后,打开modbus文档,在里面添加一个build文件夹,按照CMake的步骤执行就可以生成所需要的头文件和库文件了。生成之后,可以在/usr/include里面找到modbus文件夹,把我分享的h文件夹里的文件复制到modbus文件夹里,替换掉之前的那些文件。如果提示你不可以粘贴,就用sudo cp -i modbus.h /usr/include/modbus 这条指令挨个复制进去。

如果需要从站地址的参数,可以找到lib文件夹里的modbus-rtu.c进行修改。

static int _modbus_set_slave(modbus_t *ctx, int slave)
{
    /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
    if (slave >= 0 && slave <= 255) {
        ctx->slave = slave;
    } else {
        errno = EINVAL;
        return -1;
    }

    return 0;
}

直接修改这个数值就可以,我给的文件是我已经修改过的文件,原来安装的是247。

4.运行代码

在我分享的百度网盘链接里,我会给出C++和C两个版本,但都需要用CMake来运行,直接用编译器会出现头文件报错,因为我们的都文件声明链接都在CmakeList.txt中。编译器打开项目,需要一整个文件全放进去,我不太喜欢VS Code,所以我都直接用CMake来运行。

C文件夹里面应该有三个东西,一个是编译位置build文件夹,一个是程序所在地lib文件夹和一个声明CMakeList.txt。最重要的文件放在lib里面

main.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include "modbus.h"

 
char* getDateTime();
 
 
int main(int argc, char const *argv[])
{
  modbus_t *ctx;
  uint16_t tab_reg[64];
  int rc=0;
  int i=0;
  
ctx = modbus_new_rtu("/dev/ttyUSB0", 9600,'N',8,2);//配置端口,“”内写的是端口,Win系统下是COM*,Ubuntu是/dev/ttyusb*
modbus_set_slave(ctx,254);//设置从站地址,就是指令的前两位十六进制换算成十进制 例:FE(H)=254(D)
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

struct timeval t;
          t.tv_sec=0;
          t.tv_usec=1000000;        //set modbus time 1000ms
          modbus_set_response_timeout(ctx,&t);//设置响应时间
 

 
while (1) {
    char* nowtime = getDateTime();
    rc = modbus_read_input_registers(ctx,0,1, tab_reg);
    if (rc == -1) {
    fprintf(stderr, "%s error-test\n", modbus_strerror(errno));
    return -1;
}
    printf("%s:压力值:%d g \n十六进制显示:(0x%X)\n",nowtime, tab_reg[0], tab_reg[0]);
    usleep(10);
}
 
modbus_close(ctx);
modbus_free(ctx);
  
  return 0;
}
 
char* getDateTime()//获取当前时间
{
    static char nowtime[20];
    time_t rawtime;
    struct tm* ltime;
    time(&rawtime);
    ltime = localtime(&rawtime);
    strftime(nowtime, 20, "%Y-%m-%d %H:%M:%S", ltime);
    return nowtime;
}

CMakeList.txt

ADD_EXECUTABLE(main main.c)//编译main.c后生成可执行文件main
INCLUDE_DIRECTORIES(/usr/include/modbus)//头文件所在位置
TARGET_LINK_LIBRARIES(main libmodbus.so)//连接库

5.运行结果

C语言版本运行结果(这个需要端口真实的接传感器,Windows可以用modbus slave模拟)

C++版本

博主QQ:3122899873 有具体遇到的问题可以加QQ来问,也可以留言,看到都会尽量回复!


本文转载自: https://blog.csdn.net/Witty_Hou/article/details/123577265
版权归原作者 Witty_Hou 所有, 如有侵权,请联系我们删除。

“Ubuntu下libmodbus的应用”的评论:

还没有评论