欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【嵌入式】Libmodbus源码分析(二)-常用接口函数分析

程序员文章站 2022-07-02 08:30:32
...

00. 目录

01. modbus常用接口函数概述

libmodbus开发库提供的所有接口API函数,其主要对象文件包括modbus.hmodbus.c,接口函数大致可以分为3类。

02. modbus辅助接口函数

modbus.c文件中辅助接口函数

//设置从站地址
MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave);
//获取从站地址
MODBUS_API int modbus_get_slave(modbus_t* ctx);
//设置错误恢复模式
MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);
//设置当前socket或者串口句柄
MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);
//获取当前socket或者窗口句柄
MODBUS_API int modbus_get_socket(modbus_t *ctx);

//获取响应超时
MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
//设置响应超时
MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
//获取连续字节之间的超时时间
MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
//设置连续字节之间的超时时间
MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);

//获取服务端等待客户端请求超时时间
MODBUS_API int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
//设置服务端等待客户端请求超时时间
MODBUS_API int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
//获取报文头长度
MODBUS_API int modbus_get_header_length(modbus_t *ctx);
//用于主站设备与从站设备建立连接
MODBUS_API int modbus_connect(modbus_t *ctx);
//关闭连接
MODBUS_API void modbus_close(modbus_t *ctx);
//释放内存
MODBUS_API void modbus_free(modbus_t *ctx);
//刷新缓冲区
MODBUS_API int modbus_flush(modbus_t *ctx);
//是否设置为debug模式
MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag);
//获取当前错误信息
MODBUS_API const char *modbus_strerror(int errnum);

03. modbus功能接口函数

modbus.c文件中功能接口函数

//读取线圈或者离散量输出状态(功能码 0x1)
MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
//读取离散量输入值(功能码 0x2)
MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
//读取保持寄存器(功能码 0x3)
MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
//读取输入寄存器(功能码 0x4)
MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
//写单个线圈或者单个离散量(功能码 0x5)
MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
//写单个保持寄存器(功能码 0x6)
MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);
//写多个线圈(功能码 0xF)
MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
//写多个保持寄存器(功能码 0x10)
MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
                                               const uint16_t *src, int read_addr, int read_nb,
                                               uint16_t *dest);
//报告从站ID(功能码 0x11)
MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);

04. modbus数据处理

在libmodbus开发库中,为了方便数据处理,在modbus.h文件中定义了一系列数据处理宏。

/**
 * UTILS FUNCTIONS
 **/
//获取高字节
#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF)
//获取低字节
#define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF)
#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \
    (((int64_t)tab_int16[(index)    ] << 48) | \
     ((int64_t)tab_int16[(index) + 1] << 32) | \
     ((int64_t)tab_int16[(index) + 2] << 16) | \
      (int64_t)tab_int16[(index) + 3])
#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) \
    (((int32_t)tab_int16[(index)    ] << 16) | \
      (int32_t)tab_int16[(index) + 1])
#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) \
    (((int16_t)tab_int8[(index)    ] << 8) | \
      (int16_t)tab_int8[(index) + 1])
#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \
    do { \
        ((int8_t*)(tab_int8))[(index)    ] = (int8_t)((value) >> 8);  \
        ((int8_t*)(tab_int8))[(index) + 1] = (int8_t)(value); \
    } while (0)
#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \
    do { \
        ((int16_t*)(tab_int16))[(index)    ] = (int16_t)((value) >> 16); \
        ((int16_t*)(tab_int16))[(index) + 1] = (int16_t)(value); \
    } while (0)
#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \
    do { \
        ((int16_t*)(tab_int16))[(index)    ] = (int16_t)((value) >> 48); \
        ((int16_t*)(tab_int16))[(index) + 1] = (int16_t)((value) >> 32); \
        ((int16_t*)(tab_int16))[(index) + 2] = (int16_t)((value) >> 16); \
        ((int16_t*)(tab_int16))[(index) + 3] = (int16_t)(value); \
    } while (0)

对于浮点数等多字节数据而言,由于存在字节序和大小端处理等问题,所有辅助定义了一些特殊函数


MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value);
MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
                                       const uint8_t *tab_byte);
MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
MODBUS_API float modbus_get_float(const uint16_t *src);
MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
MODBUS_API float modbus_get_float_dcba(const uint16_t *src);
MODBUS_API float modbus_get_float_badc(const uint16_t *src);
MODBUS_API float modbus_get_float_cdab(const uint16_t *src);

MODBUS_API void modbus_set_float(float f, uint16_t *dest);
MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);
MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);
MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);
MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);

05. 附录

libmodbus源码下载:https://github.com/stephane/libmodbus