MODBUS RTU C语言 主机接收实现

参考链接:Modbus协议解析--小白一看就懂的协议_“社会大学三年级”的博客-CSDN博客_modbus协议详解

水平有限,仅供参考

typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;

#define REMOTE_ADDR 0x01//设备地址
#define RCV_MAX_LENGTH 60//接收字节的最大长度

#define RX_ARR_LENGTH 50
uint8_t rxIndexHigh;
uint8_t rxIndexLow;
uint8_t rxArr[RX_ARR_LENGTH];//接收到的数据放到循环数组里

#define RX_DEAL_LENGTH 100
uint8_t rxDealLength;//目前接收到的长度
uint8_t frameLength;//这一帧的长度
uint8_t rxDealArr[RX_DEAL_LENGTH];

uint8_t rxTimeOut;//超时

typedef enum{
	n_485_HEAD=0,
	n_485_CMD,
	n_485_LENGTH,
	n_485_DATA
}Rs485StepEnum;

Rs485StepEnum step;

void rx_deal(void)//2ms执行一次
{
	uint8_t data;
	uint8_t t;

	t = 0;
	while(t < 4)//一次处理4个数据,可根据自己的数据量添加
	{
		t++;
		if(rxIndexLow != rxIndexHigh)
		{
			rxTimeOut = 0;

			data = rxArr[rxIndexLow];
			rxIndexLow++;
			if(rxIndexLow >= RX_ARR_LENGTH)rxIndexLow=0;

			switch(step)
			{
				case n_485_HEAD:
					if(REMOTE_ADDR == data)
					{
						rxDealArr[rxDealLength++] = data;
						step = n_485_CMD;
					}
					break;
				case n_485_CMD:
					if(0X06 == data || 0X10 == data || 0X03 == data)
					{
						if(0X06 == data || 0X10 == data)
						{
							frameLength = 8;
							rxDealArr[rxDealLength++] = data;
							step = n_485_DATA;
						}
						else
						{
							rxDealArr[rxDealLength++] = data;
							step = n_485_LENGTH;
						}
					}
					else
					{
						step = n_485_HEAD;
						rxDealLength = 0;
					}
					break;
				case n_485_LENGTH:
					if(data > RCV_MAX_LENGTH)
					{
						step = n_485_HEAD;
						rxDealLength = 0;
					}
					else
					{
						frameLength = dat + 5;
						rxDealArr[rxDealLength++] = data;
						step = n_485_DATA;
					}
					break;
				case n_485_DATA:
					rxDealArr[rxDealLength++] = data;
					if(rxDealLength >= frameLength)
					{
						if(crc_modbusrtu(rxDealArr,rxDealLength) == 0)
						{
							if(rxDealArr[1] == 0X06)//单个写回复
							{
								
							}
							else if(rxDealArr[1] == 0X10)//多个写回复
							{
								
							}
							else if(rxDealArr[1] == 0X03)//0X03,读回复
							{
								//这里处理返回的数据
							}
						}
						step = n_485_HEAD;
						rxDealLength = 0;
					}
					break;
				default:
					step = n_485_HEAD;
					rxDealLength = 0;
					break;
			}
		}
	}

	//超时控制,多久没接收到完整的数据就丢弃原来的数据
	if(rxTimeOut++ > 10)
	{
		rxTimeOut = 0;
		step = n_485_HEAD;
		rxDealLength = 0;
	}
}

WORD crc_modbusrtu(BYTE *ptr, BYTE len)
{
	BYTE i;
	WORD crc = 0xffff;
	WORD temp;
 
	if (len == 0) {
		len = 1;
	}
	while (len--) {
		crc ^= *ptr;
		for (i = 0; i<8; i++)
		{
			if (crc & 1) {
				crc >>= 1;
				crc ^= CRC_CHECK_NUM;
			}
			else {
				crc >>= 1;
			}
		}
		ptr++;
	}

	temp = crc>>8;
	temp |= (crc<<8);

	return(temp);
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Modbus是一种通信协议,用于在不同设备之间进行数据传输和通信。在Modbus通信中,需要编写发送和接收报文的代码来实现数据的传输。 发送报文的代码可以通过串口或网络发送数据。首先,需要定义报文的格式,包括功能码、地址、数据等。然后,使用相关的通信库或函数,将报文发送出去。通常,发送报文的代码会包含以下步骤: 1. 建立与设备的连接,例如打开串口或建立网络连接。 2. 定义报文的格式,包括功能码、地址、数据等。 3. 将报文数据转换为字节流,以便发送。 4. 使用通信库或函数发送报文数据。 5. 等待设备的响应,通常是等待一段时间或等待收到特定的响应指令。 6. 接收设备的响应报文数据。 7. 关闭与设备的连接。 接收报文的代码用于接收其他设备发送的数据,并将其解析为可读取的格式。接收报文的代码通常会包含以下步骤: 1. 建立与设备的连接,例如打开串口或建立网络连接。 2. 循环接收数据,直到接收到完整的报文数据或达到超时时间。 3. 解析接收到的报文数据,提取功能码、地址、数据等。 4. 进行相应的处理操作,例如将数据存储到数据库或进行其他计算。 5. 返回响应给发送方,例如发送一个确认响应或发送数据给请求方。 6. 关闭与设备的连接。 以上是基本的发送和接收报文的代码流程,但具体的实现方式会根据使用的编程语言和通信库的不同而有所差异。在具体编写代码时,还需考虑错误处理、异常情况等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值