嵌入式Libmodbus源码分析-类型和结构体
Posted 沧海一笑-dj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式Libmodbus源码分析-类型和结构体相关的知识,希望对你有一定的参考价值。
00. 目录
文章目录
01. 常见类型声明
便于理解和跨平台使用。
stdint.h内容如下:
//
// stdint.h
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// The C Standard Library <stdint.h> header.
//
#pragma once
#define _STDINT
#include <vcruntime.h>
#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://github.com/stephane/libmodbus
以上是关于嵌入式Libmodbus源码分析-类型和结构体的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核实时调度类 ⑤ ( 实时调度类 rt_sched_class 源码分析 | 结构体字段及函数指针分析 )