openwrt --对接modbus传感器


前言

这篇文章主要讲讲如何在linux下使用libmodbus函数库,对接传感器。


提示:以下是本篇文章正文内容,下面案例可供参考

一、libmodbus是什么?

libmodbus是一个modbus的函数库,在openwrt上面,要去make menuconfig中配置。在ubuntu下面执行apt-get install libmodbus-dev安装即可。

二、使用步骤

1.demo

关于modbus的一个小demo,需要有点基础

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <modbus.h>
#include <modbus-rtu.h>
#include <errno.h>

#define LOG(format, argument...) printf("\033[1;32m[ %s ](line %d) -> " format "\r\n\033[0m", __FUNCTION__, __LINE__, ##argument)

typedef struct modbus_serial_s
{
    char name[10];      // 名称,最大长度为10个字符
    int serial_type;    // 串口类型,例如RS232, RS485等
    int speed;          // 波特率,例如9600, 115200等
    int data_bits;      // 数据位数,例如8, 7等
    int stop_bits;      // 停止位数,例如1, 2等
    char check_bits[2]; // 校验位,通常为'N'(无校验),'E'(偶校验),'O'(奇校验)
    modbus_t *ctx;      // 指向Modbus上下文的指针,用于Modbus通信
} modbus_serial_t;

modbus_serial_t rtuctl;

// 定义一个静态函数,用于Modbus RTU定时轮询
static void modbus_rtu_timed_polling()
{
    int regs = 0;           // 读取到的寄存器数量
    uint16_t buf[50] = {0}; // 存储读取寄存器数据的缓冲区,初始化为0

    // 读取Modbus寄存器
    // 参数1:Modbus上下文(ctx)
    // 参数2:起始寄存器地址(0x01)
    // 参数3:读取寄存器的数量(0x03)
    // 参数4:用于存储读取数据的缓冲区(buf)
    regs = modbus_read_registers(rtuctl.ctx, 0x01, 0x03, buf);
    if (regs == -1) // 如果读取失败,返回-1
    {
        LOG("%s\n", modbus_strerror(errno)); // 打印错误信息
        return;                              // 退出函数
    }

    // 遍历读取到的寄存器数据,并打印每个寄存器的值
    for (char i = 0; i < regs; ++i)
    {
        LOG("<%#x> \n", buf[i]); // 打印寄存器值,以十六进制格式
    }

    sleep(1);
}

// 定义一个静态函数,用于注册Modbus串口
static int modbus_serial_registers(modbus_serial_t *node)
{
    int i = 0;          // 循环计数器
    char port_name[32]; // 串口名称缓冲区

    // 打印调试信息
    LOG("************** modbus_serial_registers start\n");
    LOG("name:%s \n", node->name);               // 打印串口名称
    LOG("serial_type:%d \n", node->serial_type); // 打印串口类型
    LOG("speed:%d \n", node->speed);             // 打印波特率
    LOG("data_bits:%d \n", node->data_bits);     // 打印数据位
    LOG("stop_bits:%d \n", node->stop_bits);     // 打印停止位
    LOG("check_bits:%s \n", node->check_bits);   // 打印校验位

    // 初始化串口名称缓冲区为0
    memset(port_name, 0, 32);
    if (!strlen(node->name))
    {
        LOG("name:%s  disenale open\n", port_name); // 打印错误信息
        return -1;                                  // 返回错误
    }

    // 构建完整的串口设备路径
    sprintf(port_name, "/dev/%s", node->name);
    LOG("name:%s \n", port_name); // 打印完整的串口设备路径

    // 打开Modbus RTU端口
    // 参数1:串口设备路径
    // 参数2:波特率
    // 参数3:校验位('N'、'E'、'O')
    // 参数4:数据位
    // 参数5:停止位
    node->ctx = modbus_new_rtu(port_name, node->speed, (char)node->check_bits[0], node->data_bits, node->stop_bits);
    if (node->ctx == NULL) // 如果打开失败
    {
        LOG("Connexion failed: %s\n", modbus_strerror(errno)); // 打印错误信息
        return -1;                                             // 返回错误
    }

    // 设置Modbus调试模式
    modbus_set_debug(node->ctx, TRUE);
    // 设置从设备地址为1
    modbus_set_slave(node->ctx, 1);

    // 设置串口模式
    // 串口类型为1时,设置为RS232
    if (node->serial_type == 1)
    {
        modbus_rtu_set_serial_mode(node->ctx, MODBUS_RTU_RS232);
    }
    else // 否则,设置为RS485
    {
        modbus_rtu_set_serial_mode(node->ctx, MODBUS_RTU_RS485);
    }

    // 设置RTS(可选)
    modbus_rtu_set_rts(node->ctx, MODBUS_RTU_RTS_UP);

    // 建立Modbus连接
    if (modbus_connect(node->ctx) == -1) // 如果连接失败
    {
        LOG("Connexion failed: %s\n", modbus_strerror(errno)); // 打印错误信息
        modbus_free(node->ctx);                                // 释放Modbus上下文
        return -1;                                             // 返回错误
    }

    // 设置应答延时(可选)
    // 参数1:秒
    // 参数2:微秒
    modbus_set_response_timeout(node->ctx, 3, 0);

    LOG("************** modbus_serial_registers end\n"); // 打印调试信息,表示函数结束

    return 0; // 成功返回0
}

int main(int argc, char *argv[])
{
    memcpy(rtuctl.name, "ttyS1", 11);
    memcpy(rtuctl.check_bits, "N", 11);

    rtuctl.serial_type = 2;
    rtuctl.speed = 9600;
    rtuctl.data_bits = 8;
    rtuctl.stop_bits = 0;

    modbus_serial_registers(&rtuctl);
    while (1)
    {
        modbus_rtu_timed_polling();
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值