参考链接:Modbus协议解析--小白一看就懂的协议_“社会大学三年级”的博客-优快云博客_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);
}