modbus协议分为很多种类,比如modbus-rtu,modbus-tcp,modbus-ascii,modbus-rtu over tcp等等,最常用的就是modbus-rtu和modbus-tcp两种类型了,其中modbus-rtu在OSI网络模型的物理层使用的大多是RS485,modbus-tcp使用的是RJ45也就是我们常说的水晶头。
为什么modbus协议搞这么麻烦,其实很简单,继续往下看。
二、modbus-rtu
这是modbus协议最开始的形态,其他版本都是基于这个版本的,理解了这个版本,其他版本就都差不多了。
1.modbus-rtu报文结构
modbus最终还是用来通信的协议,tcp通讯收发数据包,modbus收发报文,那么理解modbus报文格式将会是使用modbus协议的一项基本功。
modbus-rtu的报文分为以下几个部分:
从机地址 功能码 数据 CRC校验
8bit 8bit Nbit 16bit
2.modbus-rtu报文格式解析
现在你已经了解modbus的报文大概是什么结构,我们来看看具体怎么用。
**从机地址:**由于modbus协议采取一主多从的模式,故只有一个主机能主动发送报文,其他的从机只能回复收到的报文,所以在地址这里都是从机地址,主机不需要说明自己是谁。所有从机都能收到报文,但只有地址设置为报文中地址的从机会处理这条报文。由于这段数据长度规定为一字节,所以一条modbus上理论最多可以有0-255共256个从机。
**功能码:**这个字节用来告诉从机你准备让它干什么,常用的有1,2,3,4,5,6,15,16等,看到这么多数字可能会有点慌,但其实可以分为两个部分,很简单。其中01是用来读输出离散量或是1个bit的,02是用来读取输入离散量或是1个bit的,03是用来读取保持寄存器的,04用来读取输入寄存器,05用来写单个离散量,15用来写多个离散量,06用来写单个寄存器,16用来写多个寄存器。其中一个离散量就是1bit,一个寄存器大小是16bit。
**数据:**这里是最终你需要读或写的数据,不定长,最大250字节左右。
**CRC校验:**用来校验收到的数据是否受到损坏,如果损坏会回复错误,具体内容后面会讲,想详细了解校验方法自行百度。
上面说的这四部分就是modbus-rtu报文大致的结构,在实际使用中根据不同的功能只有较小的差距,下面举几个例子并说明。
读:
01,02,03,04发送的报文格式:
从站地址 功能码 地址高位 地址低位 数量高位 数量低位 CRC
8bit 8bit 8bit 8bit 8bit 8bit 16bit
01,02,03,04回复的报文格式:
从站地址 功能码 字节数 字节1 字节n CRC
8bit 8bit 8bit 8bit 8bit 8bit
这里发现为什么我说简单了吧,但是注意,01,02和03,04回复的解释方式是不一样的!
01,02功能码回复的字节是1bit对应一个离散量,而03,04回复的每两个字节才对应一个16位的寄存器。
现在你已经学会写所有的数据了,快来试试吧!
向地址255设备ID为2的输入寄存器写入666,用二进制或十六进制表示。
收到回复01 03 00 01 02 00 66 (十六进制,CRC校验省略),代表什么意思?
学会的朋友们可以把答案留在评论区。
写:
05,06发送的报文格式:
从站地址 功能码 地址高位 地址低位 写入高位 写入低位 CRC
8bit 8bit 8bit 8bit 8bit 8bit 16bit
这里又有一些区别,需要用一下脑子来记一记了,用05写离散量,写入数据得发送FF 00(十六进制)才代表1(true),00 00为0。而06写寄存器,高低位加起来默认是个int16。
05,06回复的报文格式:
从站地址 功能码 地址高位 地址低位 写入高位 写入低位 CRC
8bit 8bit 8bit 8bit 8bit 8bit 16bit
回复就简单了,正常回复就是直接复读发送的报文,哈哈。
15,16发送的报文格式:
从站地址 功能码 地址高位 地址低位 数量高位 数量低位 写入字节数 写入数据 CRC
8bit 8bit 8bit 8bit 8bit 8bit 8bit Nbit 16bit
这里15和16写入数据的区别跟01,03一样,一个是1bit代表一个离散量,一个是16bit一个寄存器。
15,16回复的报文格式:
从站地址 功能码 地址高位 地址低位 数量高位 数量低位 CRC
8bit 8bit 8bit 8bit 8bit 8bit 16bit
基本上也是复读,不过只复读到写入字节数之前。
异常回复:
当发送了错误的报文之后就会回复异常回复,异常回复格式为:
从站地址 异常功能码 错误码 CRC
8bit 8bit 8bit 16bit
异常功能码就是正常码加128,比如03请求出错,回复的异常功能码就是83H,错误码表如下:
异常码 | 名称 | 描述 |
---|---|---|
01 (0x01) | 非法功能码 | 从站设备不支持此功能码。 |
02 (0x02) | 非法数据地址 | 指定的数据地址在从站设备中不存在。 |
03 (0x03) | 非法数据值 | 指定的数据超过范围或者不允许使用。 |
04 (0x04) | 从站设备故障 | 从站设备处理响应的过程中,出现未知错误等。 |
05 (0x05) | 确认 | 从站设备已经接受请求,并且正在处理这个请求,但是需要长持续时间进行这些操作,返回这个响应防止在客户机(或主站)中发生超时错误,客户机(或主机)可以继续发送轮询程序完成报文来确认是否完成处理。 |
06 (0x06) | 从站设备忙 | 从站设备正在处理长持续时间的程序命令。 |
07 (0x07) | 否定确认 | 从站设备无法执行主站设备发送的请求。 |
08 (0x08) | 存储奇偶性差错 | 指示扩展文件区不能通过一致性校验。 |
10 (0x0A) | 不可用的网关路径 | 与网关一起使用,指示网关不能为处理请求分配输入端口值输出端口的内部通信路径。通常意味着网关是错误配置的或过载的。 |
11 (0x0B) | 网关目标设备响应失败 | 与网关一起使用,指示没有从目标设备中获得响应,通常意味着设备未在网络中。 |
小结:
到这里modbus的大部分东西就讲完了,但是还有很多细节没有写,这些在使用的过程中慢慢都会了解到,下面开始讲解modbus-tcp。
三、modbus-tcp
modbus-tcp和modbus-rtu很像,所以我只说有差别的部分,由于modbus-tcp的报文是嵌在tcp数据帧的数据段中,所以就不需要校验了,tcp协议做了这个工作。并且tcp已经用ip和端口号来确认从机地址了,所以就也不需要从机地址了。
1.modbus-tcp报文结构
事务处理标识符 协议标识符 长度 单元标识符 功能码 数据
16bit 16bit 16bit 8bit 8bit Nbit
后面的基本一样就是丢掉了校验,数据代表功能码后面所有其他数据,都是一样的,着重讲一下前面四个。
**事务标识符:**用于事务处理配对。回复报文会复读这一段数据。因为在以太网传输中存在一个问题,就是先发后至,我们可以利用这个事务处理标识符做一个id,来防止这种情况所造成的数据收发错乱(没人用,都是0000)。
**协议标识符:**modbus协议就是0000,固定的。
**长度:**后面的字节数
**单元标识符:**从站地址,基本没啥用,写错了也没事,原因前面讲过,很多设备的实现都会忽略这一段,但不排除有的设备非要你写对。
小结:
modbus-tcp和modbus-rtu的主要区别就是前面的一些数据,功能码后面的数据除了没有校验之外其他所有的都和rtu一样,故不再解释,下面给一个C语言收发报文的实现。
四、C语言实现收发modbus-tcp报文
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)
![img](https://i-blog.csdnimg.cn/blog_migrate/473c7781dc9ebbe482152abd1a631472.jpeg)
最后
资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!
助,可以+V:Vip1104z获取!!! (备注:嵌入式)**
![img](https://i-blog.csdnimg.cn/blog_migrate/473c7781dc9ebbe482152abd1a631472.jpeg)
最后
资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!