RS485-MODBUS协议总结

简介

Modbus是一种串行通信协议,是Modicon公司(现施耐德电气)于1979年发表的。 目前Modbus已经成为工业领域通信协议的业界标准,并且是工业电子设备之间常用的连接方式。

Modbus协议的通信机制是主从模式,在一条链路上可以挂载多个设备,其中有且只有一个主设备,其余设备均为从设备。 在通信过程中,所有命令均由主设备发起,从机设备只能被动接收并响应主设备发起的命令。

Modbus协议的数据帧格式有两种类型: 一种是ASCII类型,数据类型使用字符串输出。 一种是RTU类型,数据类型使用二进制输出。 目前常用的是RTU类型,二进制方式通信数据量更小,更紧凑。

Modbus协议并没有对链路层提出要求,它可以是RS485,也可以是RS232甚至是TCP/IP。 目前最常用的是RS485,因为RS485通信距离远,抗干扰能力强,成本低。


本文以下内容针对RS485-MODBUS-RTU做一些总结

RTU数据帧格式

子地址功能码数据包校验字
1字节1字节N字节2字节

示例数据:0x110x010x00 0x00 0x00 0x060xBE 0x98

子地址:0x00表示广播地址,0x01-0xF7表示从机地址,0xF8-0xFF用户自定义。 功能码:表示此次通信需要使用从机的哪些功能,具体含义因设备而异。 数据包:表示此次通信需要用到的数据,具体含义因设备和功能而异。 校验字:表示CRC16计算的校验结果,低字节在前,高字节在后。参与CRC16计算的为:子地址+功能码+数据包

1.从帧格式可以看出来,没有固定帧头,也没有帧长字段,那么接收程序怎么判定帧起始和结束? 协议规定两个字节之间的传输间隔大于传输4个字节所需的时长,则认为当前帧结束。 注意:由于接收端需要用字节间隔时间来判断帧层,因此在发送数据时,最好关闭MCU中断,或者使用硬件DMA发送,避免发送中过程中被其它任务打断。 传输时的波特率越高,间隔时长则越短。

2.接收到完整数据后要怎么验证完整性? 验证CRC16校验值,crc16(子地址+功能码+数据包),计算结果与最后2个字节进行对比,如果相同则认为数据包完整,进行下一步处理。 否则数据包有误,应该丢弃这包数据。

3.CRC16具体是怎么计算的呢? 参考如下代码:

unsigned int modbus_crc16(unsigned char *buff, unsigned int len)
{
	unsigned int crc = 0xFFFF;
	unsigned int i, j;
	for ( j = 0; j < len; j ++)
	{
		crc = crc ^ buff[j];
		for ( i = 0; i < 8; i++)
		{
			if( ( crc & 0x0001) > 0)
			{
				crc = crc >> 1;
				crc = crc ^ 0xa001;
			}
			else
			{
				crc = crc >> 1;
			}
		}
	}
	return crc;
}