<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      equal love

      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"\n", __func__, __LINE__, ##__VA_ARGS__)
      #define M_MODBUS_LOG_WARN(format,...) printf("[%s][%d] warn: "format"\n", __func__, __LINE__, ##__VA_ARGS__)
      #define M_MODBUS_LOG_ERROR(format,...) printf("[%s][%d] error: "format"\n", __func__, __LINE__, ##__VA_ARGS__)
      #define M_MODBUS_LOG_INFO(format,...) printf("[%s][%d] info: "format"\n", __func__, __LINE__, ##__VA_ARGS__)
      #define M_MODBUS_TRACE_IN() printf("[%s][%s][%d] trace in\n", __FILE__, __func__, __LINE__)
      #define M_MODBUS_TRACE_OUT() printf("[%s][%s][%d] trace out\n", __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\n", 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
      版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

       
      posted @ 2019-05-06 13:22  珵詡媛  閱讀(1069)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产91色在线精品三级| 自偷自拍亚洲综合精品| 亚洲三区在线观看无套内射 | 人妻体内射精一区二区三区| 老熟妇欲乱一区二区三区| 吐鲁番市| 四虎永久精品在线视频| 欧洲免费一区二区三区视频| 国产曰批视频免费观看完| 国产精品一区二区三区性色 | 亚洲一品道一区二区三区| 国产成人片无码视频在线观看| 激情综合色综合久久丁香| 亚洲成人资源在线观看| 日本一区二区三区有码视频 | 亚洲一区二区三区四区| 久久久天堂国产精品女人| 国产一区二区不卡在线看| 亚洲精品男男一区二区| 亚洲欧洲日产国无高清码图片| 综合激情网一区二区三区| 国产精品无遮挡猛进猛出| 日本中文字幕在线播放| 上司人妻互换中文字幕| 亚洲综合黄色的在线观看| 青青草无码免费一二三区| 强开少妇嫩苞又嫩又紧九色| 久久96热人妻偷产精品| 国产精品天干天干综合网| 夜夜春久久天堂亚洲精品| XXXXXHD亚洲日本HD| 最新亚洲人成网站在线影院 | 亚洲人成人无码网WWW电影首页| 无码专区人妻系列日韩精品 | 一 级做人爱全视频在线看| 大肉大捧一进一出视频| 99久久激情国产精品| 国产日产亚洲系列av| 国产亚洲精品AA片在线播放天| 91麻豆精品国产91久| 18禁无遮挡啪啪无码网站|