干货|手把手带你搞懂Modbus通信协议



摘要 :昨天有小伙伴在群里问关于Modbus通信协议的,大家都比较积极地解答,所以今天果子哥总结一下关于Modbus相关的知识,适合正在入门的小伙伴“食用”。同样还是理论+实战的方式,欢迎留言区评论。

1.什么是Modbus?
顾名思义 ,它是一个Bus,即总线协议。比如串口协议、IIC协议、SPI都是通信协议。你接触到这种协议,相信你所处的行业是工业电子方面或者你的产品用于工业。
好了,现在知道了大概知道了,这是一个总线协议,是一个Mod什么的公司发表的一个通信协议。那为什么要用这个呢? 答案就是他们都在用,你就得学,啊哈哈!
正经的说,它被工业领域所接受的原因是它具备一下三个优点
- 公开发表并且无版权要求
- 易于部署和维护
- 对供应商来说,修改移动本地的比特或字节没有很多限制
简单的概括,就是 免费+简单+方便修改 !
归纳: Modbus就是一种用在工业上的简单协议!
2.Modbus用来干什么?
用两个字概括: 通信
是的,所有协议都是用来通信的,协议的制定就是让两个人根据这个协议看懂传来的一组数据。比如我给你一个 6666 ,你要是没有协议,就只知道这是 6666 ,而有了协议,你就知道了这是在问我是不是 大佬? 当然,也可以表示其他意思,具体什么意思就看你协议怎么制定!


归纳: Modbus用来通信喽,是个人都知道!
3.Modbus的内容是什么?
大致分为以下几种:
- Modbus-RTU
- Modbus-ASCII
- Modbus-TCP
以上三种协议,一个设备只会有一种协议,如果你的设备使用的是Modbus-RTU,只需查看以下对应部分,一般来说大部分的设备都是Modbus-RTU协议的。
4.通讯过程
Modbus是 主从方式通信 ,也就是说,不能同步进行通信,总线上每次只有一个数据进行传输,即主机发送,从机应答,主机不发送,总线上就没有数据通信。(所以说,这也算是一个缺点了)
举例1 : 一个总线上有一个主机,多个从机,主机查询其中一个从机,首先你必须得这些从机分配地址(这样才能知道哪个从机,而且每个地址必须唯一),分配好地址后,主机要查询,然后数据下发(数据内容下面会介绍),从机得到主机发送的数据,然后对应地址的从机回复,主机得到从机数据,这样就是一个主机到从机的通信过程,是不是很简单呢

?
举例2 : 就像打电话,你得知道对方的电话(这就是唯一地址),然后你打电话过去,相当于主机查找从机,然后对方接通电话,给你回复(返回数据),正常是这样的。
如果这时候,对方正在打电话,你应该听到的是"
sorry,you…
"这一串英文,说明对方忙,但是
Modbus总线
不能判断对方是否忙,也没有对应的仲裁机制,好了你又知道了一个缺点了!但是,你可以用软件的办法进行适当的处理数据!
5 Modbus-RTU协议
设备必须要有RTU协议!这是Modbus协议上规定的,且默认模式必须是RTU,ASCII作为选项 。(也就是说,一般的设备只有RTU这个协议,ASCII一般很少)所以说,一般学习Modbus协议,只需要了解RTU的协议,ASCII作为学习的了解就足够了。
1、帧结构
帧结构 = 地址 + 功能码+ 数据 + 校验
- 地址 : 占用一个字节,范围0-255,其中有效范围是1-247,其他有特殊用途,比如255是广播地址(广播地址就是应答所有地址,正常的需要两个设备的地址一样才能进行查询和回复)。
- 功能码 :占用一个字节,功能码的意义就是,知道这个指令是干啥的,比如你可以查询从机的数据,也可以修改数据,所以不同功能码对应不同功能。
- 数据 :根据功能码不同,有不同结构,在下面的实例中有说明。
- 校验 :为了保证数据不错误,增加这个,然后再把前面的数据进行计算看数据是否一致,如果一致,就说明这帧数据是正确的,我再回复;如果不一样,说明你这个数据在传输的时候出了问题,数据不对的,所以就抛弃了。
2、实战
只谈理论大家可能不太明白,下面举一个例子。Modbus-RTU协议一般我们用的最多功能码就是
03
和
06
,大部分都是用modbus来查询传感器上的信息用
03
查询功能码,如果需要修改传感器寄存器的值就用
06
修改功能码,其他的不需要过多关注,学多了你也记不住,哈哈哈!
2.1 查询功能码0x03
功能描述:现在我是主机,我要查询从机地址为01的数据。我现在用电脑的modbus调试助手来代替主机,stm32来代替从机。

我需要发送以下数据:
主机发送: 01 03 00 00 00 01 84 0A
从机回复: 01 03 02 19 98 B2 7E
那么这一组数据是什么意思呢?
从上面的结构图中,可以看出,主机发送的数据大致是 地址+功能码+数据+校验;
所以解析如下:
发送数据解析

01-地址,也就是你传感器的地址
03-功功能码,03代表查询功能,查询传感器的数据
00 00-代表查询的起始寄存器地址.说明从0x0000开始查询。这里需要说明以下,Modbus把数据存放在寄存器中,通过查询寄存器来得到不同变量的值,一个寄存器地址对应2字节数据
00 01-代表查询了一个寄存器.结合前面的00 00,意思就是查询从0开始的1个寄存器值
84 0A-循环冗余校验,是modbus的校验公式,从首个字节开始到84前面为止;
回复数据解析

01-地址,也就是你传感器的地址
03-功功能码,03代表查询功能,查询传感器的数据。这里要注意的是注意发给从机的功能码是啥,从机就要回复同样的功能码,如果不一样说明这一帧数据有错误
02-代表后面数据的字节数,因为上面说到,一个寄存器有2个字节,所以后面的字节数肯定是2*查询的寄存器个数;
19 98-寄存器的值是19 98,结合发送的数据看出,01这个寄存器的值为19 98
B2 7E-循环冗余校验
好了,是不是很简单呢?基本流程就是:
- 发送 :从机的地址+我要干嘛的功能码+我要查的寄存器的地址+我要查的寄存器地址的个数+校验码
- 回复 :从机的地址+主机发我的功能码+要发送给主机数据的字节数+数据+校验码
就是这么简单!
2.2 修改功能码0x06
如果我要修改从机的数据呢?那么这个协议有吗?当然有,那就是0x06
1、修改—0x06功能码
主机发送: 01 06 00 00 00 01 48 0A
从机回复: 01 06 00 00 00 01 48 0A
诶,看上去怎么一样的啊?是不是错了?答案是这是正确的;
发送数据解析

01-主机要查询的从机地址
06-功能码,06代表修改单个寄存器功能,修改有些不同,有修改一个寄存器和修改多个寄存器;
00 00-代表修改的起始寄存器地址.说明从0x0000开始.
00 01-代表修改的值为00 01.结合前面的00 00,意思就是修改0号寄存器值为00 01;
48 0A-循环冗余校验,是modbus的校验公式,从首个字节开始到48前面为止;