stm32移植libmodbus-RTU思路

写的有些乱,别介意,希望给到你思路
后面有空再写个总结性的。


libmodbus默认是给win32写的。
修改带前下划线(_)私有函数,这是作者写demo用的,用户应该根据平台修改。
如_modbus_set_slave

RTU私有函数

modbus-rtu.c
配置/移植内容
接口结构体定义,这是官方给的,移植的时候应该自己写

//L1182
const modbus_backend_t _modbus_rtu_backend = {
    _MODBUS_BACKEND_TYPE_RTU,			//模式配置 RTU or tcp
    _MODBUS_RTU_HEADER_LENGTH,			//头长度:1
    _MODBUS_RTU_CHECKSUM_LENGTH,		//校验长度:1
    MODBUS_RTU_MAX_ADU_LENGTH,			//应用数据单元长度   ADU(Application Data Unit)
    _modbus_set_slave,					//设置从机地址
    _modbus_rtu_build_request_basis,	//
    _modbus_rtu_build_response_basis,	//
    _modbus_rtu_prepare_response_tid,	//
    _modbus_rtu_send_msg_pre,			//
    _modbus_rtu_send,					//
    _modbus_rtu_receive,				//
    _modbus_rtu_recv,					//
    _modbus_rtu_check_integrity,		//
    _modbus_rtu_pre_check_confirmation,	//
    _modbus_rtu_connect,				//
    _modbus_rtu_is_connected,			//
    _modbus_rtu_close,					//
    _modbus_rtu_flush,					//
    _modbus_rtu_select,					//
    _modbus_rtu_free					//
};

作者基于win32写的实体函数

static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req)
{
    int rc;
    modbus_rtu_t *ctx_rtu = ctx->backend_data;

    if (ctx_rtu->confirmation_to_ignore) {
        _modbus_receive_msg(ctx, req, MSG_CONFIRMATION);
        /* Ignore errors and reset the flag */
        ctx_rtu->confirmation_to_ignore = FALSE;
        rc = 0;
        if (ctx->debug) {
            printf("Confirmation to ignore\n");
        }
    } else {
        rc = _modbus_receive_msg(ctx, req, MSG_INDICATION);
        if (rc == 0) {
            /* The next expected message is a confirmation to ignore */
            ctx_rtu->confirmation_to_ignore = TRUE;
        }
    }
    return rc;
}

static ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
{
#if defined(_WIN32)
    return win32_ser_read(&((modbus_rtu_t *) ctx->backend_data)->w_ser, rsp, rsp_length);
#else
    return read(ctx->s, rsp, rsp_length);
#endif
}

创建RTU时会绑定这些私有函数,如果自己创建了modbus_rtu_backend,要把这里的也改一下

modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)
{
	...
    ctx->backend = &_modbus_rtu_backend;
    ...
}

结构体结构

//modbus-private.h L69
typedef struct _modbus_backend {
    unsigned int backend_type;
    unsigned int header_length;
    unsigned int checksum_length;
    unsigned int max_adu_length;
    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);
    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);
    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);
    unsigned int (*is_connected)(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;

其他需要改的内容

看代码的过程又发现一个带前下划线的函数

//modbus.c L1707
void _modbus_init_common(modbus_t *ctx)
{
    /* Slave and socket are initialized to -1 */
    ctx->slave = -1;
    ctx->s = -1;

    ctx->debug = FALSE;
    ctx->error_recovery = MODBUS_ERROR_RECOVERY_NONE;
    ctx->quirks = MODBUS_QUIRK_NONE;

    ctx->response_timeout.tv_sec = 0;
    ctx->response_timeout.tv_usec = _RESPONSE_TIMEOUT;

    ctx->byte_timeout.tv_sec = 0;
    ctx->byte_timeout.tv_usec = _BYTE_TIMEOUT;

    ctx->indication_timeout.tv_sec = 0;
    ctx->indication_timeout.tv_usec = 0;
}

于是, 直接在文档里搜索_modbus_,把带下划线的都找出来改掉
在这里插入图片描述

libmodbus下载地址


题外话
在这里插入图片描述
AI不太同意我的猜想,但我就觉得前下划线是移植/配置接口文件。
串口发送、接收、关闭就是应该根据硬件平台定义的。
_modbus_rtu_send、_modbus_rtu_receive、modbus_rtu_close
另外,stm32中弱定义,前面就有“
”,给我感觉就是可以用户自己定义

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_MspInit can be implemented in the user file
   */
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值