简介
Modbus是一种串行通信协议,是Modicon公司(现施耐德电气)于1979年发表的。
目前Modbus已经成为工业领域通信协议的业界标准,并且是工业电子设备之间常用的连接方式。
Modbus协议的通信机制是主从模式,在一条链路上可以挂载多个设备,其中有且只有一个主设备,其余设备均为从设备。
在通信过程中,所有命令均由主设备发起,从机设备只能被动接收并响应主设备发起的命令。
Modbus协议的数据帧格式有两种类型:
一种是ASCII类型,数据类型使用字符串输出。
一种是RTU类型,数据类型使用二进制输出。
目前常用的是RTU类型,二进制方式通信数据量更小,更紧凑。
Modbus协议并没有对链路层提出要求,它可以是RS485,也可以是RS232甚至是TCP/IP。
目前最常用的是RS485,因为RS485通信距离远,抗干扰能力强,成本低。
本文以下内容针对RS485-MODBUS-RTU做一些总结
RTU数据帧格式:
子地址 | 功能码 | 数据包 | 校验字 |
1字节 | 1字节 | N字节 | 2字节 |
示例数据:0x11 0x01 0x00 0x00 0x00 0x06 0xBE 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;
}