• Modbus-RTU协议代码


    下面是RTU协议代码,读写寄存器数据组包,校验,解析

    modbus_common.h文件:
    /**************************************************************************
    ** 名称: modbus_common.h头文件
    * 日期:
    * 作者:
    * 描述:
    * 修改记录:
    ***************************************************************************/
    #ifndef __MODBUS_COMMON_H__
    #define __MODBUS_COMMON_H__

    #ifdef __cplusplus
    #if __cplusplus
    extern "C"{
    #endif
    #endif /* __cplusplus */

    #include <stdarg.h>
    #include <stdio.h>

    /**************************************************************************
    ** 宏定义
    **************************************************************************/
    /* 简化类型定义 */
    typedef unsigned char uint8_t;
    typedef signed char int8_t;
    typedef unsigned short uint16_t;
    typedef signed short int16_t;
    typedef unsigned int uint32_t;
    typedef signed int int32_t;
    typedef unsigned long long int uint64_t;
    typedef signed long long int int64_t;


    #define M_MODBUS_OK (0) /* 成功 */
    #define M_MODBUS_ERR (-1) /* 失败 */

    #ifndef bool
    typedef unsigned char bool;
    #endif

    #ifndef false
    #define false (uint8_t)(0)
    #endif

    #ifndef true
    #define true (uint8_t)(1)
    #endif

    #define DEBUG (1)

    /* 打印重定义 */
    #ifdef DEBUG
    #define M_MODBUS_LOG_DEBUG(format,...) printf("[%s][%d] debug: "format" ", __func__, __LINE__, ##__VA_ARGS__)
    #define M_MODBUS_LOG_WARN(format,...) printf("[%s][%d] warn: "format" ", __func__, __LINE__, ##__VA_ARGS__)
    #define M_MODBUS_LOG_ERROR(format,...) printf("[%s][%d] error: "format" ", __func__, __LINE__, ##__VA_ARGS__)
    #define M_MODBUS_LOG_INFO(format,...) printf("[%s][%d] info: "format" ", __func__, __LINE__, ##__VA_ARGS__)
    #define M_MODBUS_TRACE_IN() printf("[%s][%s][%d] trace in ", __FILE__, __func__, __LINE__)
    #define M_MODBUS_TRACE_OUT() printf("[%s][%s][%d] trace out ", __FILE__, __func__, __LINE__)
    #else
    #define M_MODBUS_LOG_DEBUG(format,...)
    #define M_MODBUS_LOG_WARN(format,...)
    #define M_MODBUS_LOG_ERROR(format,...)
    #define M_MODBUS_LOG_INFO(format,...)
    #define M_MODBUS_TRACE_IN()
    #define M_MODBUS_TRACE_OUT()
    #endif


    /**************************************************************************
    ** 结构体声明
    **************************************************************************/
    /* 寄存器错误码应答 */
    typedef enum _MODBUS_ERROR_CODE_E
    {
    E_CODE_NO_ERR = 0,
    E_CODE_ILLEGAL_FUNC_ERR, /* 非法功能错误 */
    E_CODE_ILLEGAL_REG_ADDR_ERR, /* 非法寄存器数据地址 */
    E_CODE_ILLEGAL_REG_VAL_ERR, /* 非法寄存器数据值 */
    E_CODE_SLAVER_FAULT_ERR, /* 从设备故障 */
    E_CODE_DEALING_CONFIRM_ERR, /* 正在确认 */
    E_CODE_OTHER_ERR, /* 其他错误 */
    } MODBUS_ERROR_CODE_E;

    /* 寄存器类型 */
    typedef enum _MODBUS_FUNC_CODE_TYPE_E
    {
    E_FUNC_CODE_READ_COILS = 0x01, /* 读线圈状态 */
    E_FUNC_CODE_READ_DISCRETE_INPUTS = 0x02, /* 读离散输入状态 */
    E_FUNC_CODE_READ_HOLDING_REGISTERS = 0x03, /* 读保持寄存器 */
    E_FUNC_CODE_READ_INPUT_REGISTERS = 0x04, /* 读输入寄存器 */
    E_FUNC_CODE_WRITE_SINGLE_COIL = 0x05, /* 写单个线圈 */
    E_FUNC_CODE_WRITE_SINGLE_REGISTER = 0x06, /* 写单个保持寄存器 */
    E_FUNC_CODE_READ_EXCEPTION_STATUS = 0x07, /* 读异常状态 */
    E_FUNC_CODE_WRITE_MULTIPLE_COILS = 0x0F, /* 写多个线圈 */
    E_FUNC_CODE_WRITE_MULTIPLE_REGISTERS = 0x10, /* 写多个保持寄存器 */
    E_FUNC_CODE_REPORT_SLAVE_ID = 0x11, /* 报告从机标识 */
    } MODBUS_FUNC_CODE_TYPE_E;

    /* 支持三种协议方式, modbus ASCII, RTU, RTU_TCP */
    typedef enum _MODBUS_PROTOCOL_TYPE_E
    {
    E_START_PROTOCOL_TYPE = 0,
    E_ASCII_PROTOCOL_TYPE,
    E_RTU_PROTOCOL_TYPE,
    E_RTU_TCP_PROTOCOL_TYPE,
    } MODBUS_PROTOCOL_TYPE_E;

    /* 波特率 */
    typedef enum _MODBUS_BAUD_E
    {
    E_BAUD_2400BPS = 2400,
    E_BAUD_4800BPS = 4800,
    E_BAUD_9600BPS = 9600,
    E_BAUD_14400BPS = 14400,
    E_BAUD_19200BPS = 19200,
    E_BAUD_28800BPS = 28800,
    E_BAUD_38400BPS = 38400,
    E_BAUD_57600BPS = 56700,
    E_BAUD_115200BPS = 115200,
    E_BAUD_128000BPS = 128000,
    E_BAUD_256000BPS = 256000,
    } MODBUS_BAUD_E;

    /* 数据位 */
    typedef enum _MODBUS_DATA_BIT_E
    {
    E_DATA_4BITS = 4,
    E_DATA_5BITS = 5,
    E_DATA_6BITS = 6,
    E_DATA_7BITS = 7,
    E_DATA_8BITS = 8,
    } MODBUS_DATA_BIT_E;

    /* 停止位 */
    typedef enum _MODBUS_STOP_BIT_E
    {
    E_STOP_1V0BIT = 0,
    E_STOP_1V5BITS,
    E_STOP_2V0BITS,
    } MODBUS_STOP_BIT_E;

    /* 校验符 */
    typedef enum _MODBUS_CHECK_E
    {
    E_CHECK_NONE = 0,
    E_CHECK_EVEN,
    E_CHECK_ODD,
    E_CHECK_MARK,
    E_CHECK_SPACK,
    } MODBUS_CHECK_E;

    /* modbus的驱动口的相关参数 */
    typedef struct _modbus_com_params_st
    {
    char *device; /* 硬件设备 */
    int32_t baud; /* 波特率 */
    uint8_t data_bit; /* 数据位 */
    uint8_t stop_bit; /* 停止位 */
    char parity; /* 校验符 */
    } modbus_com_params_st;

    /**************************************************************************
    ** 函数声明
    **************************************************************************/
    /**************************************************************************
    * 函 数: void modbus_log_hex_print(uint8_t *data, uint32_t datalen)
    * 描 述: 打印hex数据
    * 入 参: uint8_t *data : 需要打印的数据流
    uint32_t datalen : 数据长度
    * 出 参: void
    * 返回值: void
    **************************************************************************/
    void modbus_log_hex_print(uint8_t *data, uint32_t datalen);

    /**************************************************************************
    * 函 数: int32_t modbus_calc_crc(uint8_t *data, uint32_t datalen, uint16_t *crc)
    * 描 述: 计算crc校验函数
    * 入 参: uint8_t *data : 计算crc校验的数据
    uint32_t datalen : 计算crc校验的数据长度
    * 出 参: uint16_t *crc : 计算crc校验值
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_calc_crc(uint8_t *data, uint32_t datalen, uint16_t *crc);

    #ifdef __cplusplus
    #if __cplusplus
    }
    #endif
    #endif /* __cplusplus */

    #endif

    ## modbus_common.c文件:

    /**************************************************************************
    ** 名称: modbus_common.c文件
    * 日期:
    * 作者:
    * 描述:
    * 修改记录:
    ***************************************************************************/
    #include "modbus_common.h"
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    #include <netinet/in.h>

    /**************************************************************************
    ** 宏定义
    **************************************************************************/
    #define M_MODBUS_POLY_VALUE (0x1021) /* 定义的多项式值 */
    #define M_MODBUS_CRC_SEED_VALUE (0xFFFF) /* 预置值 */

    /**************************************************************************
    ** 结构体声明
    **************************************************************************/

    /**************************************************************************
    ** 函数声明
    **************************************************************************/

    /**************************************************************************
    ** 函数定义
    **************************************************************************/
    /**************************************************************************
    * 函 数: void modbus_log_hex_print(uint8_t *data, uint32_t datalen)
    * 描 述: 打印hex数据
    * 举 例: 输入data: 0x12 0x34 0x56 0x00 0x78 0x90; datalen: 6
    打印结果: "hex_data[6]: 12 34 56 00 78 90"
    * 入 参: uint8_t *data : 需要打印的数据流
    uint32_t datalen : 数据长度
    * 出 参: void
    * 返回值: void
    **************************************************************************/
    void modbus_log_hex_print(uint8_t *data, uint32_t datalen)
    {
    uint32_t index = 0;
    uint32_t temp_data_len = datalen * 3 + 1;
    uint32_t templen = 0;
    char *temp_data = NULL;

    if ((NULL == data) || (0 == datalen))
    {
    M_MODBUS_LOG_ERROR("print hex data log failed, input param is error.");
    return;
    }

    temp_data = (char
    *)malloc(temp_data_len);
    if (NULL == temp_data)
    {
    M_MODBUS_LOG_ERROR("print hex data log, malloc data[%d] space failed.", temp_data_len);
    return;
    }

    (void)memset(temp_data, 0, temp_data_len);
    for (index = 0; index < datalen; index++)
    {
    templen += sprintf(&temp_data[templen], "%02x ", data[index]);
    }

    printf("hex_data[%d]: %s ", datalen, temp_data);

    free(temp_data);
    temp_data = NULL;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_calc_crc(uint8_t *data, uint32_t datalen, uint16_t *crc)
    * 描 述: 计算crc校验函数
    * 举 例: 输入data: 0x12 0x23 0x46 0x99; datalen = 4;
    计算得到两个字节的crc校验码: XXXX
    * 入 参: uint8_t *data : 计算crc校验的数据
    uint32_t datalen : 计算crc校验的数据长度
    * 出 参: uint16_t *crc : 计算crc校验值
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_calc_crc(uint8_t *data, uint32_t datalen, uint16_t *crc)
    {
    uint16_t crc_val = M_MODBUS_CRC_SEED_VALUE;
    uint32_t i = 0;
    uint32_t j = 0;

    if ((NULL == data) || (0 == datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error");
    return M_MODBUS_ERR;
    }

    for (i = datalen; i > 0; i--)
    {
    crc_val = crc_val ^ (*data++ << 8);

    for (j = 0; j < 8; j++)
    {
    if (crc_val & 0x8000)
    {
    crc_val = (crc_val << 1) ^ M_MODBUS_POLY_VALUE;
    }
    else
    {
    crc_val <<= 1;
    }
    }
    }

    *crc = crc_val;

    return M_MODBUS_OK;
    }

    modbus_rtu.c文件:
    /**************************************************************************
    ** 名称: modbus_rtu.c文件
    * 日期:
    * 作者:
    * 描述:
    * 1.读线圈数据(开关量-- 0x01) -- 按位进行读
    * 2.读离散型量(开关量-- 0x02) -- 按位进行读
    *
    *
    * 修改记录:
    ***************************************************************************/
    #include "modbus_rtu.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    #include "winsock2.h"

    /**************************************************************************
    ** 宏定义
    **************************************************************************/
    #define M_MODBUS_MAX_REGISTER_CNT (127) /* 读写寄存器最大个数 */

    /**************************************************************************
    ** 结构体声明
    **************************************************************************/

    /**************************************************************************
    ** 全局变量声明
    **************************************************************************/

    /**************************************************************************
    ** 函数声明
    **************************************************************************/
    /*************************************************************************
    * 函 数: int32_t modbus_rtu_pack_read_reg(modbus_read_reg_info_st *reg_info, uint8_t *data, uint32_t *datalen)
    * 描 述: 按Modbus协议,组包读寄存器
    * 举 例: 按照以下协议组包公共部分
    typedef struct _modbus_rtu_read_reg_st
    {
    uint8_t slave_addr;
    uint8_t func_code;
    uint16_t register_addr;
    uint16_t register_cnt;
    uint16_t crc;
    } __attribute__((packed)) modbus_rtu_read_reg_st;
    根据输入的寄存器信息,组包数据部分
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    * 出 参: uint8_t *data : 按modbus协议组包的数据流
    uint32_t *datalen : 数据流长度
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_rtu_pack_read_reg
    (
    modbus_read_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t *datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    modbus_rtu_read_reg_st read_reg;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参校验 */
    if ((NULL == reg_info) || (NULL == data) || (NULL == datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    /* 按modbus协议组包 */
    (void)memset(&read_reg, 0, sizeof(read_reg));
    read_reg.slave_addr = reg_info->slave_addr;
    read_reg.func_code = (uint8_t)reg_info->func_code;

    /* 组包寄存器地址 */
    read_reg.register_addr = reg_info->register_addr;

    /* 寄存器数目 */
    if ((0 == reg_info->register_cnt) || (M_MODBUS_MAX_REGISTER_CNT < reg_info->register_cnt))
    {
    M_MODBUS_LOG_ERROR("register count[%d] is over out of range", reg_info->register_cnt);
    break;
    }
    read_reg.register_cnt = reg_info->register_cnt;

    /* 大小端转换 */
    read_reg.register_addr = htons(read_reg.register_addr);
    read_reg.register_cnt = htons(read_reg.register_cnt);

    /* crc校验 */
    ret = modbus_calc_crc((uint8_t *)&read_reg, sizeof(read_reg) - sizeof(uint16_t), &read_reg.crc);
    if (M_MODBUS_OK != ret)
    {
    M_MODBUS_LOG_ERROR("calc crc is failed, ret = %d", ret);
    break;
    }

    (void)memcpy(data, (uint8_t *)&read_reg, sizeof(modbus_rtu_read_reg_st));
    *datalen = sizeof(modbus_rtu_read_reg_st);

    /* 打印组包数据 */
    modbus_log_hex_print(data, *datalen);
    M_MODBUS_LOG_DEBUG("package read status register data ok");

    ret = M_MODBUS_OK;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_read_status_reg(modbus_read_reg_info_st *reg_info,
    modbus_rtu_ack_data_rw_st *data_ack, modbus_rtu_reg_data_val_st *data_val)
    * 描 述: 按Modbus协议,解析读取状态寄存器的响应数据
    * 举 例: 按照以下协议组包进行解析,输出正常响应的数据值
    typedef struct _modbus_rtu_ack_data_rw_st
    {
    uint8_t slave_addr;
    uint8_t func_code;
    uint8_t datalen;
    uint8_t *data;
    } __attribute__((packed)) modbus_rtu_ack_data_rw_st;
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    modbus_rtu_ack_data_rw_st *data_ack : 接收的状态寄存器的信息
    * 出 参: modbus_rtu_reg_data_val_st *data_val : 输出读保存/状态寄存器的数据值信息
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_read_status_reg
    (
    modbus_read_reg_info_st *reg_info,
    modbus_rtu_ack_data_rw_st *data_ack,
    modbus_rtu_reg_data_val_st *data_val
    )
    {
    int32_t ret = M_MODBUS_ERR;

    M_MODBUS_TRACE_IN();

    do
    {
    if ((NULL == reg_info) || (NULL == data_ack) || (NULL == data_val))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    /* 读状态寄存器 */
    if (reg_info->register_cnt != (uint16_t)data_ack->datalen)
    {
    M_MODBUS_LOG_ERROR("read status register num[%x]
    not equal recv datalen[%x]",
    reg_info->register_cnt, data_ack->datalen);
    break;
    }

    /* 保存到结构体中 */
    data_val->read_reg_type = E_MODBUS_RTU_READ_STATUS_REG;
    data_val->start_register_addr = reg_info->register_addr;
    data_val->read_register_cnt = reg_info->register_cnt / 8 + (reg_info->register_cnt % 8) ? 1 : 0;
    data_val->reg_data.status_reg_value = (uint8_t *)malloc(data_val->read_register_cnt);
    if (NULL == data_val->reg_data.status_reg_value)
    {
    M_MODBUS_LOG_ERROR("malloc read status register[%d] space is failed", data_val->read_register_cnt);
    break;
    }

    (void)memset(data_val->reg_data.status_reg_value, 0, data_val->read_register_cnt);
    (void)memcpy(data_val->reg_data.status_reg_value, data_ack->data, data_val->read_register_cnt);

    M_MODBUS_LOG_DEBUG("recv read status register data ok");

    ret = M_MODBUS_OK;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_read_storage_reg(modbus_read_reg_info_st *reg_info,
    modbus_rtu_ack_data_rw_st *data_ack, modbus_rtu_reg_data_val_st *data_val)
    * 描 述: 按Modbus协议,解析读取存储寄存器的响应数据
    * 举 例: 按照以下协议组包进行解析,输出正常响应的数据值
    typedef struct _modbus_rtu_ack_data_rw_st
    {
    uint8_t slave_addr;
    uint8_t func_code;
    uint8_t datalen;
    uint8_t *data;
    } __attribute__((packed)) modbus_rtu_ack_data_rw_st;
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    modbus_rtu_ack_data_rw_st *data_ack : 接收的状态寄存器的信息
    * 出 参: modbus_rtu_reg_data_val_st *data_val : 输出读保存/状态寄存器的数据值信息
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_read_storage_reg
    (
    modbus_read_reg_info_st *reg_info,
    modbus_rtu_ack_data_rw_st *data_ack,
    modbus_rtu_reg_data_val_st *data_val
    )
    {
    uint16_t index = 0;
    int32_t ret = M_MODBUS_ERR;

    M_MODBUS_TRACE_IN();

    do
    {
    if ((NULL == reg_info) || (NULL == data_ack) || (NULL == data_val))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    /* 读保存寄存器 */
    if ((reg_info->register_cnt * 2) != (uint16_t)data_ack->datalen)
    {
    M_MODBUS_LOG_ERROR("read register num[%x *2] not equal recv datalen[%x]", reg_info->register_cnt, data_ack->datalen);
    break;
    }

    /* 解析获取到结构体中 */
    data_val->read_reg_type = E_MODBUS_RTU_READ_STORAGE_REG;
    data_val->start_register_addr = reg_info->register_addr;
    data_val->read_register_cnt = data_ack->datalen / 2;
    data_val->reg_data.storage_reg_value = (uint16_t *)malloc(data_val->read_register_cnt);
    if (NULL == data_val->reg_data.storage_reg_value)
    {
    M_MODBUS_LOG_ERROR("malloc read storage register[%d] space is failed", data_val->read_register_cnt);
    break;
    }

    (void)memset(data_val->reg_data.storage_reg_value, 0, data_val->read_register_cnt);
    for (index = 0; index < reg_info->register_cnt; index++)

    {
    data_val->reg_data.storage_reg_value[index] = data_ack->data[index * 2];
    data_val->reg_data.storage_reg_value[index] <<= 8;
    data_val->reg_data.storage_reg_value[index] |= data_ack->data[index * 2 + 1];
    }

    M_MODBUS_LOG_DEBUG("recv read storage register data ok");
    ret = M_MODBUS_OK;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_read_register(modbus_read_reg_info_st *reg_info,
    uint8_t *data, uint32_t datalen, uint16_t *pOutBuf)
    * 描 述: 按Modbus协议,解析响应的数据
    * 举 例: 按照以下协议组包进行解析,输出正常响应的数据值
    typedef struct _modbus_rtu_ack_data_rw_st
    {
    uint8_t slave_addr;
    uint8_t func_code;
    uint8_t datalen;
    uint8_t *data;
    } __attribute__((packed)) modbus_rtu_ack_data_rw_st;
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    uint8_t *data : 按modbus协议组包的数据流
    uint32_t datalen : 数据流长度
    * 出 参: modbus_rtu_reg_data_val_st *data_val : 输出读保存/状态寄存器的数据值信息,
    在调用后,成功获取完寄存器的数据后,需要释放申请的寄存器的值
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_rtu_unpack_read_register
    (
    modbus_read_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t datalen,
    modbus_rtu_reg_data_val_st *data_val
    )
    {
    int32_t ret = M_MODBUS_ERR;
    uint16_t crc_val = 0;
    uint16_t recv_crc_val = 0;
    modbus_rtu_ack_data_rw_st *data_ack = NULL;
    modbus_rtu_fail_st *fail_info = NULL;
    MODBUS_ERROR_CODE_E err_code = E_CODE_NO_ERR;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参校验 */
    if ((NULL == reg_info) || (NULL == data) || (NULL == data_val) || (3 > datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    data_ack = (modbus_rtu_ack_data_rw_st *)data;

    /* 从地址校验 */
    if (reg_info->slave_addr != data_ack->slave_addr)
    {
    M_MODBUS_LOG_ERROR("pack read_reg[%x] not equal recv read_reg[%x]",
    reg_info->slave_addr, data_ack->slave_addr);
    break;
    }

    /* CRC校验 */
    ret = modbus_calc_crc(data, datalen - 2, &crc_val);
    if (M_MODBUS_OK != ret)
    {
    M_MODBUS_LOG_ERROR("recv read_reg ack calc crc failed");
    break;
    }

    recv_crc_val = (uint16_t)(((uint16_t)data[datalen - 2] << 8) | (uint16_t)data[datalen - 1]);
    if (crc_val != recv_crc_val)
    {
    M_MODBUS_LOG_ERROR("recv read_reg(%x) not equal calc crc(%x)", recv_crc_val, crc_val);
    ret = M_MODBUS_ERR;
    break;
    }

    /* 错误功能码解析 */
    if ((uint8_t)reg_info->func_code != data_ack->func_code)
    {
    if (((uint8_t)reg_info->func_code | 0x80) == data_ack->func_code)
    {
    fail_info = (modbus_rtu_fail_st *)data;

    /* 返回的是错误码 */
    switch (fail_info->except_code)
    {
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
    case 0x05:
    {
    err_code = (MODBUS_ERROR_CODE_E)fail_info->except_code;
    break;
    }
    default:
    {
    err_code = E_CODE_OTHER_ERR;
    break;
    }
    }
    }
    else
    {
    err_code = E_CODE_OTHER_ERR;
    }

    M_MODBUS_LOG_WARN("read register data, func code[%x] is fail ack value[%x]",
    data_ack->func_code, fail_info->except_code);

    ret = M_MODBUS_OK;
    break;
    }

    switch (reg_info->func_code)
    {
    case E_FUNC_CODE_READ_COILS:
    case E_FUNC_CODE_READ_DISCRETE_INPUTS:
    {
    /* 读状态寄存器 */
    ret = modbus_rtu_unpack_read_status_reg(reg_info, data_ack, data_val);
    break;
    }
    case E_FUNC_CODE_READ_HOLDING_REGISTERS:
    case E_FUNC_CODE_READ_INPUT_REGISTERS:
    {
    /* 读存储寄存器 */
    ret = modbus_rtu_unpack_read_storage_reg(reg_info, data_ack, data_val);
    break;
    }
    default:
    {
    /* 其他 */
    M_MODBUS_LOG_WARN("not recv read register data, func code[%x]", reg_info->func_code);
    ret = M_MODBUS_ERR;
    break;
    }
    }
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_pack_write_reg(modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data, uint32_t *datalen)
    * 描 述: 按Modbus协议,组包写寄存器的值
    * 举 例:
    对于单个状态/存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    对于多个状态寄存器来说,组包格式,按bit的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + crcc(2)
    对于多个存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + crcc(2)
    * 入 参: modbus_register_info_st *reg_info : 输入写寄存器信息
    * 出 参: uint8_t *data : 按modbus协议组包的数据流
    uint32_t *datalen : 数据流长度
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_rtu_pack_write_reg
    (
    modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t *datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    uint16_t crc_val = 0;
    uint8_t index = 0;
    uint8_t templen = 0;
    uint8_t register_val_len = 0;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参校验 */
    if ((NULL == reg_info) || (NULL == data) || (NULL == datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    /* 寄存器个数为0,直接退出 */
    if (0x00 == reg_info->register_cnt)
    {
    M_MODBUS_LOG_ERROR("input param write register count is 0x00, exit.");
    break;
    }

    /* 按modbus协议组包 */
    data[templen++] = reg_info->slave_addr;
    data[templen++] = (uint8_t)reg_info->func_code;

    /* 组包寄存器地址 */
    data[templen++] = (uint8_t)((reg_info->register_addr >> 8) & 0xff);
    data[templen++] = (uint8_t)(reg_info->register_addr & 0xff);

    if (0x01 == reg_info->register_cnt)
    {
    /* 单个状态/保存寄存器 */
    data[templen++] = (uint8_t)((reg_info->reg_val.register_val[0] >> 8) & 0xff);
    data[templen++] = (uint8_t)(reg_info->reg_val.register_val[0] & 0xff);
    }
    else
    {
    /* 写寄存器个数 */
    data[templen++] = 0x00;
    data[templen++] = reg_info->register_cnt;

    if (E_FUNC_CODE_WRITE_MULTIPLE_COILS == reg_info->func_code)
    {
    /* 写多个线圈的字节数长度 */
    register_val_len = reg_info->register_cnt / 8 + (reg_info->register_cnt % 8 ? 1 : 0);
    data[templen++] = register_val_len;

    /* 多个线圈状态值 */
    (void)memcpy(&data[templen], reg_info->reg_val.multiple_status_reg_val, register_val_len);
    templen += register_val_len;
    }
    else if (E_FUNC_CODE_WRITE_MULTIPLE_REGISTERS == reg_info->func_code)
    {
    /* 写多个寄存器字节长度 */
    data[templen++] = reg_info->register_cnt * 2;

    for (index = 0; index < reg_info->register_cnt; index++)
    {
    data[templen++] = (uint8_t)((reg_info->reg_val.register_val[index] >> 8) & 0xff);
    data[templen++] = (uint8_t)(reg_info->reg_val.register_val[index] & 0xff);
    }
    }
    else
    {
    M_MODBUS_LOG_ERROR("write multiple register, func code[%d] error", reg_info->func_code);
    break;
    }
    }

    /* crc校验 */
    ret = modbus_calc_crc(data, templen, &crc_val);
    if (M_MODBUS_OK != ret)
    {
    M_MODBUS_LOG_ERROR("calc crc is failed, ret = %d", ret);
    break;
    }

    data[templen++] = (uint8_t)((crc_val >> 8) & 0xff);
    data[templen++] = (uint8_t)(crc_val & 0xff);

    *datalen = templen;

    /* 打印组包数据 */
    modbus_log_hex_print(data, *datalen);
    M_MODBUS_LOG_DEBUG("package write register data ok");
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_write_signal_reg(modbus_read_reg_info_st *reg_info,
    uint8_t *data, uint32_t datalen)
    * 描 述: 按Modbus协议,解析读取单个状态/存储寄存器的响应数据
    * 举 例: 对于单个状态/存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    uint8_t *data : 按modbus协议接收的数据流
    uint32_t datalen : 数据流长度
    * 出 参: void
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_write_signal_reg
    (
    modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    modbus_rtu_ack_write_signal_reg_st *write_signal_reg = NULL;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参判断 */
    if ((NULL == reg_info) || (NULL == data) || (3 >= datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    write_signal_reg = (modbus_rtu_ack_write_signal_reg_st *)data;

    /* 寄存器地址和寄存器值的校验 */
    write_signal_reg->register_addr = ntohs(write_signal_reg->register_addr);
    write_signal_reg->register_data = ntohs(write_signal_reg->register_data);

    if (reg_info->register_addr != write_signal_reg->register_addr)
    {
    M_MODBUS_LOG_ERROR("recv write_signal_reg addr(%x) != recv write signal addr(%x)",
    reg_info->register_addr, write_signal_reg->register_addr);
    break;
    }

    if (reg_info->reg_val.register_val[0] != write_signal_reg->register_data)
    {
    M_MODBUS_LOG_ERROR("recv write_signal_reg val(%x) != recv write signal val(%x)",
    reg_info->reg_val.register_val[0], write_signal_reg->register_data);
    break;
    }

    M_MODBUS_LOG_DEBUG("recv write signal register data ok");
    ret = M_MODBUS_OK;
    break;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;

    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_write_multiple_state_reg(
    modbus_read_reg_info_st *reg_info, uint8_t *data, uint32_t datalen)
    * 描 述: 按Modbus协议,解析读取多个状态寄存器的响应数据
    * 举 例: 对于多个状态寄存器来说,组包格式,按bit的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + crcc(2)
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    uint8_t *data : 按modbus协议接收的数据流
    uint32_t datalen : 数据流长度
    * 出 参: void
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_write_multiple_state_reg
    (
    modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    uint8_t write_data_len = 0;
    modbus_rtu_ack_write_multiple_state_reg_st *write_state_reg = NULL;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参判断 */
    if ((NULL == reg_info) || (NULL == data) || (3 >= datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    write_state_reg = (modbus_rtu_ack_write_multiple_state_reg_st *)data;

    /* 寄存器地址和寄存器个数,寄存器长度进行校验*/
    write_state_reg->register_addr = ntohs(write_state_reg->register_addr);
    write_state_reg->register_cnt = ntohs(write_state_reg->register_cnt);

    if (reg_info->register_addr != write_state_reg->register_addr)
    {
    M_MODBUS_LOG_ERROR("write_multiple_status_reg addr(%x) != recv write multiple_status addr(%x)",
    reg_info->register_addr, write_state_reg->register_addr);
    break;
    }

    if ((uint16_t)reg_info->register_cnt != write_state_reg->register_cnt)
    {
    M_MODBUS_LOG_ERROR("write_multiple_status_cnt(%x) != recv write multiple_status cnt(%x)",
    reg_info->register_cnt, write_state_reg->register_cnt);
    break;
    }

    write_data_len = reg_info->register_cnt / 8 + (reg_info->register_cnt % 8 ? 1 : 0);
    if (write_data_len != write_state_reg->register_data_len)
    {
    M_MODBUS_LOG_ERROR("write_multiple_status_data_len(%x) != recv write multiple_status data len(%x)",
    write_data_len, write_state_reg->register_data_len);
    break;
    }

    M_MODBUS_LOG_DEBUG("recv write multiple_status data ok");
    ret = M_MODBUS_OK;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_write_multiple_storage_reg(
    modbus_read_reg_info_st *reg_info, uint8_t *data, uint32_t datalen)
    * 描 述: 按Modbus协议,解析读取多个存储寄存器的响应数据
    * 举 例: 对于多个存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + crcc(2)
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    uint8_t *data : 按modbus协议接收的数据流
    uint32_t datalen : 数据流长度
    * 出 参: void
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_write_multiple_storage_reg
    (
    modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    modbus_rtu_ack_write_multiple_storage_reg_st *write_storage_reg = NULL;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参判断 */
    if ((NULL == reg_info) || (NULL == data) || (3 >= datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    write_storage_reg = (modbus_rtu_ack_write_multiple_storage_reg_st *)data;

    /* 寄存器地址和寄存器个数,寄存器长度进行校验*/
    write_storage_reg->register_addr = ntohs(write_storage_reg->register_addr);
    write_storage_reg->register_cnt = ntohs(write_storage_reg->register_cnt);

    if (reg_info->register_addr != write_storage_reg->register_addr)
    {
    M_MODBUS_LOG_ERROR("write_multiple_storage_reg addr(%x) != recv write multiple_storage addr(%x)",
    reg_info->register_addr, write_storage_reg->register_addr);
    break;
    }

    if ((uint16_t)reg_info->register_cnt != write_storage_reg->register_cnt)
    {
    M_MODBUS_LOG_ERROR("write_multiple_storage_cnt(%x) != recv write multiple_storage cnt(%x)",
    reg_info->register_cnt, write_storage_reg->register_cnt);
    break;
    }

    M_MODBUS_LOG_DEBUG("recv write multiple_storage data ok");
    ret = M_MODBUS_OK;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_unpack_write_reg(modbus_read_reg_info_st *reg_info,
    uint8_t *data, uint32_t datalen)
    * 描 述: 按Modbus协议,解析读取寄存器的响应数据
    * 举 例: 对于单个状态/存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_val(2) + crc(2)
    对于多个状态寄存器来说,组包格式,按bit的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + crcc(2)
    对于多个存储寄存器来说,组包格式,按字节的方式:
    发送->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + reg_val_len(1) + reg_val(n) + crc(2)
    应答->slave_addr(1) + func(1) + reg_addr(2) + reg_cnt(2) + crcc(2)
    * 入 参: modbus_read_reg_info_st *reg_info : 输入读写寄存器信息
    uint8_t *data : 按modbus协议接收的数据流
    uint32_t datalen : 数据流长度
    * 出 参: void
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    static int32_t modbus_rtu_unpack_write_reg
    (
    modbus_rtu_write_reg_info_st *reg_info,
    uint8_t *data,
    uint32_t datalen
    )
    {
    int32_t ret = M_MODBUS_ERR;
    uint16_t crc_val = 0;
    uint16_t recv_crc_val = 0;
    MODBUS_ERROR_CODE_E err_code = E_CODE_NO_ERR;
    modbus_rtu_fail_st *fail_info = NULL;
    modbus_rtu_ack_data_rw_st *data_ack = NULL;

    M_MODBUS_TRACE_IN();

    do
    {
    /* 入参判断 */
    if ((NULL == reg_info) || (NULL == data) || (3 >= datalen))
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    data_ack = (modbus_rtu_ack_data_rw_st *)data;

    /* 地址是否一致 */
    if (reg_info->slave_addr != data_ack->slave_addr)
    {
    M_MODBUS_LOG_ERROR("write register slave addr[%x] != recv data ack slave addr[%x]",
    reg_info->slave_addr, data_ack->slave_addr);
    break;
    }

    /* crc校验 */
    ret = modbus_calc_crc(data, datalen - 2, &crc_val);
    if (M_MODBUS_OK != ret)
    {
    M_MODBUS_LOG_ERROR("recv write_signal_reg ack calc crc failed");
    break;
    }

    recv_crc_val = (uint16_t)(((uint16_t)data[datalen - 2] << 8) | (uint16_t)data[datalen - 1]);
    if (crc_val != recv_crc_val)
    {
    M_MODBUS_LOG_ERROR("recv write_signal_reg_crc(%x) not equal calc crc(%x)", recv_crc_val, crc_val);
    ret = M_MODBUS_ERR;
    break;
    }

    /* 错误功能码解析 */
    if ((uint8_t)reg_info->func_code != data_ack->func_code)
    {
    if (((uint8_t)reg_info->func_code | 0x80) == data_ack->func_code)
    {
    fail_info = (modbus_rtu_fail_st *)data;

    /* 返回的是错误码 */
    switch (fail_info->except_code)
    {
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
    case 0x05:
    {
    err_code = (MODBUS_ERROR_CODE_E)fail_info->except_code;
    break;
    }
    default:
    {
    err_code = E_CODE_OTHER_ERR;
    break;
    }
    }
    }
    else
    {
    err_code = E_CODE_OTHER_ERR;
    }

    M_MODBUS_LOG_WARN("write signal register data, func code[%x] is fail ack value[%x]",
    reg_info->func_code, data_ack->func_code);

    ret = M_MODBUS_ERR;
    break;
    }

    switch (reg_info->func_code)
    {
    case E_FUNC_CODE_WRITE_SINGLE_COIL:
    case E_FUNC_CODE_WRITE_SINGLE_REGISTER:
    {
    ret = modbus_rtu_unpack_write_signal_reg(reg_info, data, datalen);
    }
    case E_FUNC_CODE_WRITE_MULTIPLE_COILS:
    {
    ret = modbus_rtu_unpack_write_multiple_state_reg(reg_info, data, datalen);
    }
    case E_FUNC_CODE_WRITE_MULTIPLE_REGISTERS:
    {
    ret = modbus_rtu_unpack_write_multiple_storage_reg(reg_info, data, datalen);
    }
    default:
    {
    /* 其他 */
    M_MODBUS_LOG_WARN("not recv write register data, func code[%x]", reg_info->func_code);
    ret = M_MODBUS_ERR;
    }
    }
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    /**************************************************************************
    * 函 数: int32_t modbus_rtu_init(modbus_com_params_st *com_param)
    * 描 述: 初始化modbus rtu 通信口参数
    * 入 参: modbus_com_params_st *com_param : 通信口参数信息
    * 出 参: void
    * 返回值: int32_t : M_MODBUS_OK - 成功
    M_MODBUS_ERR - 失败
    **************************************************************************/
    int32_t modbus_rtu_init(modbus_com_params_st *com_param)
    {
    int32_t ret = M_MODBUS_ERR;

    M_MODBUS_TRACE_IN();

    do
    {
    if (NULL == com_param)
    {
    M_MODBUS_LOG_ERROR("input param is error, null point");
    break;
    }

    /* 参数初始化 */
    (void)memset(&g_modbus_com, 0, sizeof(g_modbus_com));
    if (strlen(com_param->device) > 0)
    {
    (void)memcpy(g_modbus_com.device, com_param->device, strlen(com_param->device));
    }

    /* 波特率 */
    if ((E_BAUD_2400BPS > com_param->baud) || (E_BAUD_256000BPS < com_param->baud))
    {
    g_modbus_com.baud = E_BAUD_9600BPS;
    }
    else
    {
    g_modbus_com.baud = com_param->baud;
    }

    /* 数据位 */
    if ((E_DATA_4BITS > com_param->data_bit) || (E_DATA_8BITS < com_param->data_bit))
    {
    g_modbus_com.data_bit = E_DATA_8BITS;
    }
    else
    {
    g_modbus_com.data_bit = com_param->data_bit;
    }

    /* 停止位 */
    g_modbus_com.stop_bit = com_param->stop_bit;
    g_modbus_com.parity = com_param->parity;
    }
    while (0);

    M_MODBUS_TRACE_OUT();

    return ret;
    }

    modbus_rtu.h头文件:
    /**************************************************************************
    ** 名称: modbus_rtu.h头文件
    * 日期:
    * 作者:
    * 描述:
    * 修改记录:
    ***************************************************************************/
    #ifndef __MODBUS_RTU_H__
    #define __MODBUS_RTU_H__

    #ifdef __cplusplus
    #if __cplusplus
    extern "C"{
    #endif
    #endif /* __cplusplus */

    #include "modbus_common.h"

    /**************************************************************************
    ** 宏定义
    **************************************************************************/

    /**************************************************************************
    ** 结构体声明
    **************************************************************************/
    /* 返回失败功能码应答结构体 */
    typedef struct _modbus_rtu_fail_st
    {
    uint8_t slave_addr;
    uint8_t err_func_code;
    uint8_t except_code;
    uint16_t crc16;
    } __attribute__((packed)) modbus_rtu_fail_st;

    /* modbus rtu 读写寄存器响应协议结构 */
    typedef struct _modbus_rtu_ack_data_rw_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    uint8_t func_code; /* 功能码 */
    uint8_t datalen; /* 响应数长的 */
    uint8_t *data; /* 响应数据 */
    } __attribute__((packed)) modbus_rtu_ack_data_rw_st;

    /****************************************************************************
    ** 读寄存器结构体
    *****************************************************************************/
    /* 读从机寄存器的结构体(支持1-126) */
    typedef struct _modbus_read_reg_info_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    MODBUS_FUNC_CODE_TYPE_E func_code; /* 功能码 */
    uint16_t register_addr; /* 寄存器首地址 */
    uint16_t register_cnt; /* 寄存器数目 */
    } modbus_read_reg_info_st;

    /* modbus rtu 读寄存器协议结构 */
    typedef struct _modbus_rtu_read_reg_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    uint8_t func_code; /* 功能码 */
    uint16_t register_addr; /* 读寄存器地址 */
    uint16_t register_cnt; /* 寄存器数目 */
    uint16_t crc; /* crc校验 */
    } __attribute__((packed)) modbus_rtu_read_reg_st;

    /* 用于区分读状态寄存器,还是读保存寄存器 */
    typedef enum _MODBUS_RTU_READ_REG_TYPE_E
    {
    E_MODBUS_RTU_READ_STATUS_REG = 0,
    E_MODBUS_RTU_READ_STORAGE_REG,
    } MODBUS_RTU_READ_REG_TYPE_E;

    /* 用于保存读状态寄存器和保存寄存器的数据值信息 */
    typedef union _modbus_rtu_reg_data_u
    {
    uint16_t *storage_reg_value;
    uint8_t *status_reg_value;
    } modbus_rtu_reg_data_u;

    typedef struct _modbus_rtu_reg_data_val_st
    {
    MODBUS_RTU_READ_REG_TYPE_E read_reg_type; /* 状态寄存器,还是存储寄存器 */
    uint16_t start_register_addr; /* 寄存器起始地址 */
    uint8_t read_register_cnt; /* 寄存器个数 */
    modbus_rtu_reg_data_u reg_data; /* 保存的寄存器数据值 */
    } modbus_rtu_reg_data_val_st;

    /****************************************************************************
    ** 写寄存器结构体
    ****************************************************************************/
    /* 用于写寄存器的值 */
    typedef union _modbus_rtu_write_reg_val_st
    {
    uint16_t *register_val; /* 写寄存器的值 */
    uint8_t *multiple_status_reg_val; /* 多个状态寄存器的值 */
    } modbus_rtu_write_reg_val_st;

    /* 用于写状态/存储寄存器 */
    typedef struct _modbus_rtu_write_reg_info_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    MODBUS_FUNC_CODE_TYPE_E func_code; /* 功能码 */
    uint16_t register_addr; /* 寄存器首地址 */
    uint8_t register_cnt; /* 写寄存器个数 */
    modbus_rtu_write_reg_val_st reg_val; /* 寄存器的值 */
    } modbus_rtu_write_reg_info_st;

    /* 解析写单个寄存器 */
    typedef struct _modbus_rtu_ack_write_signal_reg_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    uint8_t func_code; /* 功能码 */
    uint16_t register_addr; /* 寄存器首地址 */
    uint16_t register_data; /* 写寄存器的值 */
    uint16_t crc; /* crc校验 */
    } __attribute__((packed)) modbus_rtu_ack_write_signal_reg_st;

    /* 解析写多个状态寄存器应答结构 */
    typedef struct _modbus_rtu_ack_write_multiple_status_reg_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    uint8_t func_code; /* 功能码 */
    uint16_t register_addr; /* 寄存器首地址 */
    uint16_t register_cnt; /* 寄存器个数 */
    uint8_t register_data_len; /* 寄存器数据值长度 */
    uint16_t crc; /* crc校验 */
    } __attribute__((packed)) modbus_rtu_ack_write_multiple_state_reg_st;

    /* 解析写多个状态寄存器应答结构 */
    typedef struct _modbus_rtu_ack_write_multiple_storage_reg_st
    {
    uint8_t slave_addr; /* 从设备地址 */
    uint8_t func_code; /* 功能码 */
    uint16_t register_addr; /* 寄存器首地址 */
    uint16_t register_cnt; /* 寄存器个数 */
    uint16_t crc; /* crc校验 */
    } __attribute__((packed)) modbus_rtu_ack_write_multiple_storage_reg_st;


    /**************************************************************************
    ** 函数声明
    **************************************************************************/

    #ifdef __cplusplus
    #if __cplusplus
    }
    #endif
    #endif /* __cplusplus */

    #endif
    ---------------------
    作者:chensufei24
    来源:CSDN
    原文:https://blog.csdn.net/chensufei24/article/details/82995720
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    SPLAY,LCT学习笔记(五)
    SPLAY,LCT学习笔记(四)
    SPLAY,LCT学习笔记(三)
    NOI 2012 随机数生成器
    SPLAY,LCT学习笔记(二)
    SPLAY,LCT学习笔记(一)
    bzoj 1503 郁闷的出纳员
    bzoj 1112 poi 2008 砖块
    bzoj 1064 noi2008 假面舞会题解
    数论知识点总结(noip范围)
  • 原文地址:https://www.cnblogs.com/luckytimor/p/10819038.html
Copyright © 2020-2023  润新知