写在前面

之前的项目上使用了Pythonminimalmodbus库,但是我感觉如果从站多了之后,性能会有所下降,所以一直想使用C语言来编写与传感器通信的程序,看看是否比Python更高效

libmodbus

官网libmodbus支持ModBus RTUModBus TCP模式,并且是开源软件。

目前有3.0.83.1.6两个版本,前者从2013年之后就没有更新过,推荐使用后者。

更多详情请参阅官方文档

编译安装libmodbus

根据其Github上的介绍,首先安装编译环境

apt-get install automake autoconf libtool gcc git -y
git clone https://github.com/stephane/libmodbus.git
cd libmodbus
./autogen.sh
./configure && make install

# 等待编译安装完成
# 测试
# 新建两个终端,分别运行tests目录下的
./unit-test-server
./unit-test-client
# 等待测试完成

创建ModBus RTU环境

使用modbus_new_rtu来创建libmodbus rtu环境。函数详情:

modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);
# 参数详情
# *device 通信端口
# baud 波特率
# parity 奇偶校验参数
# data_bit 数据位
# stop_bit 停止位

当初始化完成,你需要使用 modbus_set_slave来设置从站id,使用modbus_connect来连接串口,以下是示例:

modbus_t *ctx;

ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}

modbus_set_slave(ctx, YOUR_DEVICE_ID);

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);    // modbus_free - free a libmodbus context 释放 libmodbus 环境
    return -1;
}

读取寄存器 modbus_read_registers

这里我用了一个温湿度传感器来做测试,之前的使用Python通过ModBus RTU 协议读取传感器数据也是一样。因为温湿度传感器自带显示界面,方便对比。

/*一个使用libmodbus库的测试程序*/
#include <stdio.h>
#include <modbus.h>
#include <errno.h>

int main(void)
{
    modbus_t *ctx;    // 创建一个指针
    uint16_t tab_reg[32];    // 创建一个数组
    int rc;
    int i;
    
    /*新建一个ModBus RTU 环境*/
    ctx = modbus_new_rtu("/dev/ttyUSB0",9600,'N',8,1);
    if(ctx == NULL)
    {
        fprintf(stderr, "Unable to create the libmodbus context\n");
        return -1;
    }

    /*设置从站地址*/
    modbus_set_slave(ctx, 1);

    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /*读取一个寄存器地址*/
    rc = modbus_read_registers(ctx,1,1,tab_reg);
    if(rc == -1)
    {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
    }

    for (i = 0; i < rc; i++)
    {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }

    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

保存为modbus_rtc.c,如果直接使用gcc编译会出现modbus.c:(.text+0x5c): undefined reference错误,相关链接:
gcc compile fail: undefined reference to `modbus_new_tcp'
libmodbus: how to compile application including libmodbus library?
解决方法在第二个链接里面:
/etc/ld.so.conf.d/里面创建一个modbus.conf文件,写入/usr/local/lib,然后运行ldconfig -v。最后在编译的时候使用gcc <name>.c -o <name> -I /usr/local/include/modbus/ -lmodbus

这里我实际使用的是gcc modbus_rtu.c -o test -I /usr/local/include/modbus/ -lmodbus,然后运行./test

1.png

2.png

202表示现在温度是20.2度(我这里还没有做计算,因为传感器返回的就是202)。

接下来

接下来要做的就是将得到的数据写入到数据库里面。先到此为止吧。


参考资料:
https://github.com/stephane/libmodbus
https://libmodbus.org/
https://stackoverflow.com/questions/63142337/libmodbus-how-to-compile-application-including-libmodbus-library
https://github.com/stephane/libmodbus/issues/123
https://techoverflow.net/2019/06/20/how-to-fix-c-error-errno-undeclared/

标签: none

评论已关闭