文章目录
一、libmodbus重要数据结构讲解
这两个结构体是 libmodbus
的核心,定义了 Modbus 通信上下文 (_modbus
) 和通信后端 (_modbus_backend
) 的详细信息,直接决定了 Modbus 的通信行为。
1. 结构体 _modbus
定义
这个结构体描述了 Modbus 通信的上下文 (modbus_t
类型的实际定义),包含了通信所需的参数和状态信息。
成员解析
struct _modbus {
/* Slave address */
int slave;
slave
:当前上下文的从站地址。对于 Modbus 主站,表示要访问的从站地址;对于 Modbus 从站,表示设备自身的地址。
/* Socket or file descriptor */
int s;
s
:文件描述符,用于标识当前连接。对于 Modbus TCP,表示一个套接字 (socket
);对于 Modbus RTU,表示一个串口文件描述符。
int debug;
debug
:调试标志。设置为1
时,启用调试模式,打印发送和接收的详细信息。
int error_recovery;
error_recovery
:错误恢复模式。启用后,通信发生错误时会自动尝试恢复连接(如重新连接或重发请求)。
int quirks;
quirks
:表示协议的特殊处理标志,用于处理不同 Modbus 实现的兼容性问题。
struct timeval response_timeout;
struct timeval byte_timeout;
struct timeval indication_timeout;
response_timeout
:等待从站响应的最大时间。byte_timeout
:等待每个字节接收的超时时间。indication_timeout
:Modbus 从站在无通信时的等待时间(仅在从站模式下使用)。
const modbus_backend_t *backend;
backend
:指向 Modbus 后端结构的指针,定义了具体的通信实现(如 Modbus TCP 或 RTU)。
void *backend_data;
backend_data
:与后端相关的私有数据指针。TCP 和 RTU 后端可能需要不同的附加信息(如 TCP 套接字地址或串口配置)。
小结
_modbus
是 Modbus 通信的抽象封装,结合backend
提供具体的通信行为。- 它统一管理通信参数和状态信息,为主站和从站操作提供支持。
2. 结构体 _modbus_backend
定义
modbus_backend_t
定义了 Modbus 的通信后端接口,抽象了具体的通信实现(如 TCP 或 RTU)。通过这个结构体,libmodbus
能够适配不同的传输协议。
成员解析
unsigned int backend_type;
backend_type
:后端类型标志,用于区分 Modbus RTU、ASCII 或 TCP。
unsigned int header_length;
unsigned int checksum_length;
unsigned int max_adu_length;
header_length
:报文头长度,Modbus RTU 和 TCP 的头长度不同。checksum_length
:校验码长度。Modbus RTU 使用 CRC 校验,Modbus TCP 不需要校验。max_adu_length
:最大 ADU(Application Data Unit)长度,限制一次传输的数据量。
int (*set_slave)(modbus_t *ctx, int slave);
set_slave
:设置 Modbus 从站地址的函数指针。
int (*build_request_basis)(modbus_t *ctx, int function, int addr, int nb, uint8_t *req);
build_request_basis
:构建 Modbus 请求帧的函数,定义了如何封装功能码、寄存器地址和数据。
int (*build_response_basis)(sft_t *sft, uint8_t *rsp);
build_response_basis
:构建 Modbus 响应帧的函数,用于从站模式。
int (*prepare_response_tid)(const uint8_t *req, int *req_length);
prepare_response_tid
:准备响应时处理事务 ID 的函数(通常用于 TCP)。
int (*send_msg_pre)(uint8_t *req, int req_length);
ssize_t (*send)(modbus_t *ctx, const uint8_t *req, int req_length);
ssize_t (*recv)(modbus_t *ctx, uint8_t *rsp, int rsp_length);
send_msg_pre
:在发送请求前进行预处理(如添加校验)。send
:发送数据帧的底层实现。recv
:接收数据帧的底层实现。
int (*check_integrity)(modbus_t *ctx, uint8_t *msg, const int msg_length);
check_integrity
:校验数据帧完整性的函数(如 CRC 校验)。
int (*pre_check_confirmation)(modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length);
pre_check_confirmation
:检查从站响应是否与主站请求匹配。
int (*connect)(modbus_t *ctx);
unsigned int (*is_connected)(modbus_t *ctx);
void (*close)(modbus_t *ctx);
connect
:建立连接的函数。is_connected
:检查连接状态的函数。close
:关闭连接的函数。
int (*flush)(modbus_t *ctx);
flush
:清空接收缓冲区的函数。
int (*select)(modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);
select
:实现select
调用,等待特定时间以接收数据。
void (*free)(modbus_t *ctx);
free
:释放上下文相关资源的函数。
小结
modbus_backend_t
是 Modbus 的后端抽象,封装了不同通信协议的操作。- 每个通信协议(TCP 或 RTU)需要实现一套符合接口的具体函数。
3. 两者关系和工作流程
关系
_modbus
是 Modbus 通信的具体上下文,它通过指针backend
关联到_modbus_backend
。_modbus_backend
提供了通信操作的实现,_modbus
负责调用这些接口。
工作流程
-
初始化
- 创建
_modbus
实例,设置从站地址和通信参数。 - 初始化对应的
_modbus_backend
实现(TCP 或 RTU)。
- 创建
-
通信
- 调用
backend
的build_request_basis
构建请求帧。 - 使用
send
和recv
函数发送和接收数据。 - 检查数据完整性并解析响应。
- 调用
-
关闭连接
- 调用
close
和free
函数,释放资源。
- 调用
这两个结构体共同构成了 libmodbus
的核心设计,通过分离上下文和后端逻辑,实现