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
  • 19
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
要添加Modbus-RTU协议,您可以按照以下步骤进行操作: 1. 确保您的设备支持Modbus-RTU协议Modbus-RTU是一种串行通信协议,通常运行在RS-485或RS-232接口上。请检查您的设备规格和用户手册,确认它支持Modbus-RTU。 2. 确定您要使用的硬件接口。根据您的设备和系统要求,选择适合的硬件接口。一般来说,RS-485是常用的选择,因为它支持多个设备之间的通信。 3. 获取Modbus-RTU库和驱动程序。根据您的开发平台和编程语言,选择合适的Modbus-RTU库和驱动程序。一些常用的选择包括libmodbus(C语言)、pymodbus(Python)、J2mod(Java)等。从官方网站或开源社区获取这些库和驱动程序,并按照相关文档进行安装和配置。 4. 编写代码进行通信。根据您的需求,使用选定的Modbus-RTU库和驱动程序编写代码进行通信。通常,您需要初始化串口参数(如波特率、数据位、停止位等),建立连接,发送请求并接收响应。具体的代码实现会因库和编程语言而异,您可以参考相关文档和示例代码进行开发。 5. 测试和调试。在开发完成后,进行测试和调试以确保通信正常。您可以使用Modbus调试工具或模拟器来模拟设备,发送请求并验证响应。同时,注意处理异常情况和错误码,确保您的代码具有良好的稳定性和容错性。 以上是添加Modbus-RTU协议的一般步骤,具体实现会因您的开发环境和需求而有所不同。请根据您的情况进行适当调整和修改。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值