RS485 MODBUS RTU通信协议
RS485 MODBUS RTU通信协议
参考资料:
https://www.cnblogs.com/lemonzhang/p/8963932.html
https://blog.csdn.net/weixin_74209371/article/details/129185203
文章目录
1、RS485接口标准
RS485由RS232和RS422发展而来,弥补了抗干扰能力差、通信距离短、速率低的缺点,增加了多点、双向通信能力,即允许多个发送器连接在同一条主线上,同时增加了发送器的驱动能力和冲突保护特性,扩展了总线共模范围。RS485可以采用二线和四线两种方式,二线制可以实现真正的多点双向通信。其主要特点如下:
-
RS485的接口信号电平比RS231-C低,不易损坏接口电路的芯片,且该电平与TTL电平兼容,方便于TTL电路相连接。
-
RS485的数据最高传输速率为10Mbps。其平衡双绞线的长度与传输速率呈反比,在100kbps速率下,才可能使用规定的最长电缆长度,只有在很短的距离下才能获得最高传输速率。
-
RS485接口采用平衡驱动器和差分接收器的组合,抗共模干扰能力强,即抗噪声干扰性好,因而通信距离远,最大传输距离大约为1200m,实际可达3000m。
-
RS485接口在总线上允许连接多达128个收发器,既具有多站能力。同时需要两个终端电阻,其阻值要求等于传输电缆的特性阻抗。在短距离300m内传输时可不连接终端电阻。
2、RS485两线组网
对于MCU来说,无论是RS485、RS232、RS422本质上都使用的是串口通讯,只不过各通信协议要求的电气特性不同。一般都是通过抓换芯片,将MCU的TTL电平转换成232或485电平。下图为RS485主从设备组网图,其实可以理解为将所有设备的串口收、发数据线线全部并在了一起,只要一个设备发送数据其他设备都能收到。当然并不是将线并到一起就完事了,还需要制定相应的通信规则,不然大家都想发数据不就乱套了,通信规则见下一小节。
3、MODBUS RTU通信规则
-
系统中只有一个设备是主机:主从通信
-
系统中的从机不可以主动的向主机发送数据
-
系统上电后所有的主从设备都应该处于监听总线的状态,也就是接收状态
-
如果要发起一次通信,必须由主机主动发起(任何一次的通信或数据交换都必须由主机来发起)
-
只有主机可以发起广播通信,从机收到广播消息无需恢复
-
主从通讯有问有答,即使主机发送的数据有误,从机也要响应
4、MODBUS RTU协议
4.1信息帧格式
地址码 | 功能码 | 数据 | 错误校验 |
---|---|---|---|
8bits(1字节) | 8bits(1字节) | N*8bits(N字节) | 16bits(2字节) |
4.2地址码
-
地址码范围: 0~247
-
对于一主多从的通讯架构中,主机为 0。从设备地址为 1~247。
-
主机发送地址码 0 ,一般称为广播数据,从机无需响应。
4.3功能码
MODBUS通讯规约定义功能码为1-127,通常主从双方会约定好使用其中一部分,如下是常用的一些功能码
功能吗 | 含义 | 操作 |
---|---|---|
0x03 | 读命令 | 支持单个和多个寄存器连续读取 |
0x10 | 写多个寄存器命令 | 支持多个寄存器连续写动作 |
0x06 | 写单个寄存器命令 | 支持单个寄存器连续写动作 |
0x04 | 读命令 | 多个寄存器连续读取 |
4.2数据
数据通常是由功能码决定的,功能码不同数据格式会有差别,这里先举一个简单的例子,先有一个了解,第5节会详细介绍读寄存器和写寄存器的详细交互流程。如下数据帧为通过0x03指令码读取寄存器数据,功能码和错误校验中间的是数据,数据共4个字节。前两字节表示寄存器地址,后两字节表示要读取的寄存器个数。
地址码 | 功能码 | 寄存器地址 | 寄存器个数 | 错误校验低位 | 错误校验高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x00,0x60 | 0x00,0x02 | 0xC4 | 0x15 |
4.2错误校验
MODBUS RTU一般采用CRC16校验方式,CRC16的多项式:0x8005,CRC校验范围为CRC字段前所有字节的校验。
4.2.1CRC校验工具
在线校验工具:https://www.metools.info/code/c15.html
如4.2节的数据计算出来的CRC值为:0x15C4(注意计算出来的数据高位在左,低位在右)
地址码 | 功能码 | 寄存器地址 | 寄存器个数 | 错误校验低位 | 错误校验高位 |
---|---|---|---|---|---|
0x01 | 0x03 | 0x00,0x60 | 0x00,0x02 | 0xC4 | 0x15 |
4.2.2错误校验代码
unsigned short count_CRC(unsigned char *addr, int num)
{
int i;
unsigned short CRC = 0xFFFF;
while (num--)
{
CRC ^= *addr++;
for (i = 0; i < 8; i++)
{
CRC = (CRC & 0x0001) ? ((CRC >> 1)^0xa001) : (CRC >> 1);
}
}
return CRC;
}
4.2.3高低位颠倒代码
通过4.2.2的代码计算出来的CRC高位在前低位在后,但 通常MODBUS的CRC用的是高位在后低位在前,所以还需要转换一下。
//大小端序转换,颠倒16位数据的高位和低位
void swap16(void *p)
{
unsigned short *ptr = p;
unsigned sort x = *ptr;
x = (x << 8) | (x >> 8);
*ptr = x;
}
//大小端序转换,颠倒32位数据的高位和低位
void swap16(void *p)
{
unsigned short *ptr = p;
unsigned sort x = *ptr;
x = (x << 16) | (x >> 16);
x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF)
*ptr = x;
}
5、读、写寄存器实例
MSB表示高字节;LSB表示低字节。每个寄存器存放两个字节;对寄存器数据类型为一个字节的数据,要求存放在低字节(LSB)。
5.1读寄存器
5.1.1主节点发送帧
5.1.2从节点正常应答帧
5.1.3从节点异常应答帧
5.2写单个寄存器
5.2.1主节点发送帧
5.2.2从节点正常应答帧
5.2.3从节点异常应答帧
5.3写多个寄存器
5.3.1主节点发送帧
5.3.2从节点正常应答帧
5.3.3从节点异常应答帧
5.4错误码
异常码名称 | 说 明 |
---|---|
01 非法功能码 | 对于从节点来说,询问中接收到的功能码是不可允许的操作。这也许是因为功能码仅仅适用于新设备而在被选单元中是不可实现的。同时,还指出从节点在错误状态中处理这种请求,例如:因为它是未配置的,并且要求返回寄存器值。 |
02 非法数据地址 | 对于从节点来说,询问中接收到的数据地址是不可允许的地址。特别是,参考号和传输长度的组合是无效的。对于带有100个寄存器的控制器来说,带有偏移量96和长度4的请求会成功,带有偏移量96和长度5的请求将产生异常码02。 |
03 非法数据值 | 对于从节点来说,询问中包括的值是不可允许的值。这个值指示了组合请求剩余结构中的故障,例如:隐含长度是不正确的。并不意味着,因为MODBUS协议不知道任何特殊寄存器的任何特殊值的重要意义,寄存器中被提交存储的数据项有一个应用程序期望之外的值。 |
原文地址:https://blog.csdn.net/m0_46295154/article/details/145139673
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!