【嵌入式】Libmodbus源码分析(一)-类型和结构体
发布日期:2021-06-29 20:51:59 浏览次数:2 分类:技术文章

本文共 10842 字,大约阅读时间需要 36 分钟。

00. 目录

文章目录

01. 常见类型声明

便于理解和跨平台使用。

stdint.h内容如下:

//// stdint.h////      Copyright (c) Microsoft Corporation. All rights reserved.//// The C Standard Library 
header.//#pragma once#define _STDINT#include
#if _VCRT_COMPILER_PREPROCESSOR#pragma warning(push)#pragma warning(disable: _VCRUNTIME_DISABLED_WARNINGS)typedef signed char int8_t;typedef short int16_t;typedef int int32_t;typedef long long int64_t;typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef unsigned long long uint64_t;typedef signed char int_least8_t;typedef short int_least16_t;typedef int int_least32_t;typedef long long int_least64_t;typedef unsigned char uint_least8_t;typedef unsigned short uint_least16_t;typedef unsigned int uint_least32_t;typedef unsigned long long uint_least64_t;typedef signed char int_fast8_t;typedef int int_fast16_t;typedef int int_fast32_t;typedef long long int_fast64_t;typedef unsigned char uint_fast8_t;typedef unsigned int uint_fast16_t;typedef unsigned int uint_fast32_t;typedef unsigned long long uint_fast64_t;typedef long long intmax_t;typedef unsigned long long uintmax_t;// These macros must exactly match those in the Windows SDK's intsafe.h.#define INT8_MIN (-127i8 - 1)#define INT16_MIN (-32767i16 - 1)#define INT32_MIN (-2147483647i32 - 1)#define INT64_MIN (-9223372036854775807i64 - 1)#define INT8_MAX 127i8#define INT16_MAX 32767i16#define INT32_MAX 2147483647i32#define INT64_MAX 9223372036854775807i64#define UINT8_MAX 0xffui8#define UINT16_MAX 0xffffui16#define UINT32_MAX 0xffffffffui32#define UINT64_MAX 0xffffffffffffffffui64#define INT_LEAST8_MIN INT8_MIN#define INT_LEAST16_MIN INT16_MIN#define INT_LEAST32_MIN INT32_MIN#define INT_LEAST64_MIN INT64_MIN#define INT_LEAST8_MAX INT8_MAX#define INT_LEAST16_MAX INT16_MAX#define INT_LEAST32_MAX INT32_MAX#define INT_LEAST64_MAX INT64_MAX#define UINT_LEAST8_MAX UINT8_MAX#define UINT_LEAST16_MAX UINT16_MAX#define UINT_LEAST32_MAX UINT32_MAX#define UINT_LEAST64_MAX UINT64_MAX#define INT_FAST8_MIN INT8_MIN#define INT_FAST16_MIN INT32_MIN#define INT_FAST32_MIN INT32_MIN#define INT_FAST64_MIN INT64_MIN#define INT_FAST8_MAX INT8_MAX#define INT_FAST16_MAX INT32_MAX#define INT_FAST32_MAX INT32_MAX#define INT_FAST64_MAX INT64_MAX#define UINT_FAST8_MAX UINT8_MAX#define UINT_FAST16_MAX UINT32_MAX#define UINT_FAST32_MAX UINT32_MAX#define UINT_FAST64_MAX UINT64_MAX#ifdef _WIN64 #define INTPTR_MIN INT64_MIN #define INTPTR_MAX INT64_MAX #define UINTPTR_MAX UINT64_MAX#else #define INTPTR_MIN INT32_MIN #define INTPTR_MAX INT32_MAX #define UINTPTR_MAX UINT32_MAX#endif#define INTMAX_MIN INT64_MIN#define INTMAX_MAX INT64_MAX#define UINTMAX_MAX UINT64_MAX#define PTRDIFF_MIN INTPTR_MIN#define PTRDIFF_MAX INTPTR_MAX#ifndef SIZE_MAX // SIZE_MAX definition must match exactly with limits.h for modules support. #ifdef _WIN64 #define SIZE_MAX 0xffffffffffffffffui64 #else #define SIZE_MAX 0xffffffffui32 #endif#endif#define SIG_ATOMIC_MIN INT32_MIN#define SIG_ATOMIC_MAX INT32_MAX#define WCHAR_MIN 0x0000#define WCHAR_MAX 0xffff#define WINT_MIN 0x0000#define WINT_MAX 0xffff#define INT8_C(x) (x)#define INT16_C(x) (x)#define INT32_C(x) (x)#define INT64_C(x) (x ## LL)#define UINT8_C(x) (x)#define UINT16_C(x) (x)#define UINT32_C(x) (x ## U)#define UINT64_C(x) (x ## ULL)#define INTMAX_C(x) INT64_C(x)#define UINTMAX_C(x) UINT64_C(x)#pragma warning(pop) // _VCRUNTIME_DISABLED_WARNINGS#endif // _VCRT_COMPILER_PREPROCESSOR

02. 常量声明

在modbus.h文件中,通过宏定义libmodbus库目前支持的所有Modbus功能码

/* Modbus function codes */#define MODBUS_FC_READ_COILS                0x01#define MODBUS_FC_READ_DISCRETE_INPUTS      0x02#define MODBUS_FC_READ_HOLDING_REGISTERS    0x03#define MODBUS_FC_READ_INPUT_REGISTERS      0x04#define MODBUS_FC_WRITE_SINGLE_COIL         0x05#define MODBUS_FC_WRITE_SINGLE_REGISTER     0x06#define MODBUS_FC_READ_EXCEPTION_STATUS     0x07#define MODBUS_FC_WRITE_MULTIPLE_COILS      0x0F#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS  0x10#define MODBUS_FC_REPORT_SLAVE_ID           0x11#define MODBUS_FC_MASK_WRITE_REGISTER       0x16#define MODBUS_FC_WRITE_AND_READ_REGISTERS  0x17

在modbus.h文件中定义了最大可读/可写线圈数量,最大可读/可写寄存器数量。

//广播地址#define MODBUS_BROADCAST_ADDRESS    0/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) * Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0) * (chapter 6 section 11 page 29) * Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0) */#define MODBUS_MAX_READ_BITS              2000#define MODBUS_MAX_WRITE_BITS             1968/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15) * Quantity of Registers to read (2 bytes): 1 to 125 (0x7D) * (chapter 6 section 12 page 31) * Quantity of Registers to write (2 bytes) 1 to 123 (0x7B) * (chapter 6 section 17 page 38) * Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79) */#define MODBUS_MAX_READ_REGISTERS          125#define MODBUS_MAX_WRITE_REGISTERS         123#define MODBUS_MAX_WR_WRITE_REGISTERS      121#define MODBUS_MAX_WR_READ_REGISTERS       125/* The size of the MODBUS PDU is limited by the size constraint inherited from * the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 * bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server * address (1 byte) - CRC (2 bytes) = 253 bytes. */#define MODBUS_MAX_PDU_LENGTH              253/* Consequently: * - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256 *   bytes. * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes. * so the maximum of both backend in 260 bytes. This size can used to allocate * an array of bytes to store responses and it will be compatible with the two * backends. */#define MODBUS_MAX_ADU_LENGTH              260/* Random number to avoid errno conflicts */#define MODBUS_ENOBASE 112345678

错误码常量

/* Random number to avoid errno conflicts */#define MODBUS_ENOBASE 112345678/* Protocol exceptions */enum {
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01, //非法的功能码 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, //非法的数据地址 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, //非法的数据值 MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE, //从站设备故障 MODBUS_EXCEPTION_ACKNOWLEDGE, //ACK异常 MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY, //从站设备忙 MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE, //否定应答 MODBUS_EXCEPTION_MEMORY_PARITY, //内存奇偶校验错误 MODBUS_EXCEPTION_NOT_DEFINED, //未定义 MODBUS_EXCEPTION_GATEWAY_PATH, //网关路径不可用 MODBUS_EXCEPTION_GATEWAY_TARGET, //目标设备未能回应 MODBUS_EXCEPTION_MAX};#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)/* Native libmodbus error codes */#define EMBBADCRC (EMBXGTAR + 1) //无效的CRC #define EMBBADDATA (EMBXGTAR + 2) //无效的数据#define EMBBADEXC (EMBXGTAR + 3) //无效的异常码#define EMBUNKEXC (EMBXGTAR + 4) //保留 未使用#define EMBMDATA (EMBXGTAR + 5) //数据过多#define EMBBADSLAVE (EMBXGTAR + 6) //响应与查询地址不匹配

03. _modbus结构体声明

在文件modbus-private.h中定义了_modbus结构体,具体定义如下:

struct _modbus {
/* Slave address */ int slave; //从站设备地址 /* Socket or file descriptor */ int s; //TCP模式下为套接字 RTU模式下为串口句柄 int debug; //是否启用debug模式 int error_recovery; //错误恢复模式 struct timeval response_timeout; //响应超时设置 struct timeval byte_timeout; //字节超时设置 struct timeval indication_timeout; //包含一系列通用函数指针 const modbus_backend_t *backend; void *backend_data; //TCP模式下特殊配置数据 RTU模式下特殊配置数据};

04. modbus_backend_t结构体声明

modbus_backend_t作为一个重要的结构体,包含了各种处理函数。其定义如下:

typedef struct _modbus_backend {
unsigned int backend_type; //modbus_backend_type_t类型 unsigned int header_length; //HBMP长度 unsigned int checksum_length; //错误校验字段长度 unsigned int max_adu_length; //ADU最大长度 int (*set_slave) (modbus_t *ctx, int slave); //设置从站设备地址 //构造查询报文的基本通信帧 int (*build_request_basis) (modbus_t *ctx, int function, int addr, int nb, uint8_t *req); //构造响应报文的基本通信帧 int (*build_response_basis) (sft_t *sft, uint8_t *rsp); //构造响应报文TID参数 int (*prepare_response_tid) (const uint8_t *req, int *req_length); //发送报文前的预处理 int (*send_msg_pre) (uint8_t *req, int req_length); //发送报文 ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); //接收报文 int (*receive) (modbus_t *ctx, uint8_t *req); //接收报文 该函数被receive函数调用 ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); //用于数据完整性检查 int (*check_integrity) (modbus_t *ctx, uint8_t *msg, const int msg_length); //确认响应报文的帧头是否一致 int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length); //建立连接 int (*connect) (modbus_t *ctx); //关闭连接 void (*close) (modbus_t *ctx); //清空缓冲区 int (*flush) (modbus_t *ctx); //用于设置超时并读取通信事件,以检测是否存在待接收数据 int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length); //释放内存 void (*free) (modbus_t *ctx);} modbus_backend_t;

05. modbus_mapping_t结构体声明

modbus_mapping_t声明在modbus.h文件中,其声明如下:

typedef struct _modbus modbus_t;typedef struct _modbus_mapping_t {
int nb_bits; //线圈寄存器的数量 int start_bits; //线圈寄存器的起始地址 int nb_input_bits; //离散输入寄存器的数量 int start_input_bits; //离散输入寄存器的起始地址 int nb_input_registers; //输入寄存器的数量 int start_input_registers; //输入寄存器的起始地址 int nb_registers; //保持寄存器的数量 int start_registers; //保持寄存器的起始地址 uint8_t *tab_bits; //指向线圈寄存器的值 uint8_t *tab_input_bits; //指向离散输入寄存器的值 uint16_t *tab_input_registers; //指向输入寄存器的值 uint16_t *tab_registers; //指向保持寄存器的值} modbus_mapping_t;

06. 附录

libmodbus源码下载:

转载地址:https://dengjin.blog.csdn.net/article/details/116669466 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【嵌入式】Libmodbus源码分析(二)-常用接口函数分析
下一篇:【嵌入式】Libmodbus下载和编译详解

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月15日 23时56分59秒