查看原文
其他

手把手教你写Modbus-RTU协议(理论篇)

未知bug 最后一个bug 2021-01-31

1、日常唠唠嗑

    最近很多小伙伴们都反馈文章的字体有点小,非常感谢这些小伙伴们为作者提供的宝贵建议,可能是多年敲代码的原因,习惯了不是特别大的字体,因为大家都知道程序员为了跟上迅速发展的高科技术的脚步需要不断的学习,那么"一目十行"迅速捕捉文章等内容的关键内容将成为一种日常的技能,然而字体太大会导致视野内容下降从而导致相同时间内获取的知识容量下降,同样在我们阅读代码的过程中字体太大也会导致我们的理解代码结构思想带来不利的影响,不过大一点的字体能够带来更好的阅读体验,这点可能我没有注意到,所以以后就用该字体大小来书写文章,看大家觉得是否合适?(可以私信作者)

    昨天完成了《通过"库"带你学习单片机驱动编程》的连载写作,内容可能比较多,大部分初学者可能很多东西还不一定看得太明白,我建议大家可以首先先过一遍这5篇内容,在心里能够留下文章中提到的一些思想内容,然后进行其他的学习和开发,这样当你有一定的积累以后自然会有种豁然开朗的感觉。好了,该开始今天的主题了!

2、Modbus串行链路层简介

    作者在往期中有一篇《向Modbus协议说So Easy!》,这篇文章得到了大家的好评,都说比较好理解Modbus协议,不过就是距离实际的应用情景还是有点距离,所以这里作者准备花费三篇文章的内容,从理论实践代码讲解为大家剖析Modbus协议中的最常用的Modbus-RTU通讯传输模式,同时大家也最好是阅读完之前的文章再来进行该部分的内容会更容易理解。

1)理解什么是"主/从协议方式"

    我们的Modbus串行协议就是一种主从通信协议,可以说就是一种"一问一答"的通信方式,主节点问,从节点才响应,并且总线上只能有一个主节点。前面说过主节点发出的请求其ADU中的地址是从节点的地址,而从节点返回的ADU中的地址也是从节点的地址,那么modbus中的地址只有1个bye,其中地址0作为主节点的广播地址。Modbus协议中规定每个从节点的地址是在1-247中选择。

2)两种通讯模式

    那么从地址的分配来看modbus存在两种通信模式:

  • 1)点对点通讯模式:也就是主节点在同一时间只能与一个从节点读写数据的模式。

  • 2)点对多通讯模式:也就是我们的广播地址,当主节点以广播地址进行写数据的时候,所有的从节点都会接受并处理,但是不会有任何的返回。值得注意的是在进行该模式传输的时候,主节点对同一节点操作的时候需要预留足够多等待从节点处理完事务的时间。

  • 性能评价:对于点对点的通讯模式主要的延时来自于往返通讯上的传输时间和接受发送数据的数据处理时间。

3、Modbus-RTU解析

1)串行传输模型

    modbus的串行传输模式分为:RTU模式和ASCII模式

    这里作者用一个小例子来解释这两种模式,便于大家理解这两种模式的传输,比如我们需要传输0x5A,那么我们如果使用串口进行RTU传输直接一帧数据1byte搞定,而如果我们选用ASCII来进行传输需要两个byte,分别传输0x35(ASCII对应:字符5)和0x41(ASCII对应:字符A)。

    从上面的小例子我们了解到用RTU模式传输的传输效率和数据密度是高于ASCII的,那么为什么还需要用定ASCII协议呢?那我们首先简答的介绍ASCII模型传输。

2)ASCII传输模式分析

    上面我们也简单的提到了ASCII的传输模式,这里简单画一下其帧格式大家应该就可以了解了:

    解析:ASCII模式以冒号开头,与回车-换行结束(0x0D-0x0A),基本上由之前的RTU一个字节变成了两个字节,传输效率大大降低。由于该协议本身存在起始和结束标识符,那么其字符接受间隔可以达到1s,而RTU帧与帧之间就只能有1.5个字符,而报文与报文之间应>3.5个字符。那么ASCII它虽然传输速度不如RTU,不过其可读性比较好,我们有时候可以直接通过串口调试助手即可直观的解读数据信息。ASCII不是我们的重点,这里不多讲。

小知识-LRC校验

Modbus的LRC校验:(一句话搞定)

    除去ADU中的冒号和LR-LF,其他数据以两个字符对应的hex格式数据相加,然后取反+1求补码,然后再把hex格式转回为ASCII的两个字符进行传输,同时记得"高位在前,低位在后"即可。

3)RTU传输模式中的1.5和3.5

    <1.5个字符:是RTU中1byte与另外一个byte的传输时间必须小于1.5个字符,表示字符与字符之间的最大间隔时间。

    >3.5个字符:表示RTU中1个报文与下一个报文之间的间隔需要>3.5个字符,即传输一个ADU与下一个ADU的时间间隔,这个主要是用于判断报文发送完毕。

    总结:其实modbus之间的1.5和3.5其实都是表示的是时间,那么很多小伙伴们会问这个时间该如何计算呢?

    我们以串口通讯中:RTU传输模式的串口格式为"1个起始位+8个数据位+1个奇偶校验位+1个停止位"= 11个bit,那么我们又知道我们的串口总线上的波特率是唯一的,比如以baudrate = 9600bit/s,那么传输11/9600 = 1个字符时间(s),这样就算出了我们的1个字符时间,顺便就可以算出1.5和3.5了。

    好了,今天的理论篇就讲这么多了,大家需要结合《向Modbus说So Easy!》一起阅读,我们平常一般用得比较多的是RTU模式,所以一般口头上都直接叫modbus协议。这里是公众号:"最后一个bug",我们下一期带来其超牛的Modbus代码master和Slave的实现,感谢大家的关注,也希望大家的分享转发再看

推荐阅读

向Modbus协议说"So easy!"

【连载】通过"库文件"学单片机驱动编程(1)

【连载】通过"库文件"学单片机驱动编程(2)

【连载】通过"库文件"学单片机驱动编程(3)

【连载】通过"库文件"学单片机驱动编程(4)

【连载】通过"库文件"学单片机驱动编程(5)-完结篇

嵌入式编程之动态接口技术(经验干货)

嵌入式编程之"重构"代码(C语言版本)

单片机常用程序框架之分时轮询(详注代码)

更多精彩文章大家可以在主页目录中查找!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存