单片机 > 单片机程序设计 > 详情

基于AVR128的简单Modbus协议实现

发布时间:2023-01-10 发布时间:
|

Modbus通讯协议是由Modicon公司在1979年开发的,应用于工业现场控制的总线协议。Modbus通讯系统包括带有可编程控制的芯片节点和公共传输线组成,其目的是用于多节点数据的采集和监控。Modbus协议采用主从模式,通讯系统中有一个主机对多个节点从机进行监控,从机节点最多支持247个。每个从机均有自己独立的从机地址,而且改地址能够被主机识别。


能够支持Modbus协议的通讯系统有RS-232,RS-422,RS-485等。同时Modbus协议具有标准、开放、免费、帧格式简单等特点而被广大工程师所采用。


Modbus协议中数据传输采用ASCII和RTU两种模式。其中ASCII传输方式表示的数据通俗易懂,便于和PC机直接通信识别,但其缺点是采用单字节表示一个数据,传输相同的数据需要更多的帧数和时间。RTU模式采用压缩的十六进制表示方式,一个字节可以压缩装载两个数据,这样相同的帧数下RTU模式可以传输更多的数据。


Modbus数据帧校验分两种方式:CRC循环冗余校验和LRC纵向冗余校验。下面使用Proteus仿真atmega128.两片128之间进行串口通讯,串口通讯上跑的是简单的Modbus协议。


仿真图如下所示:


说明:U1使用1602进行接收数据的显示。数据帧采用RTU模式,但是为了方便1602进行显示,传输的数据帧消息采用了0X3x(0,1,2,3...等数的ASCII表示形式,这样可以直接送入1602进行显示,从而方便模拟)。图片中间的三个按键是U2的三个中断。


按下之后U2单片机会发送一帧数据,数据内容是0X30, 0X31,0X33,0X01,0X34,0X37。


按照Modbus协议0X30,0X31是表示的从机地址,0X33是表示命令字符,0X01表示数据域长度,0X34表示数据域,0X37是进行的LRC校验。我们采用这种方式进行简化是为了方便1602进行显示,其中0x01是ASCII码中的空格’‘也能够在1602中进行显示。


单片机U1的PB口和PE口状态分别显示了LRC校验字节和数据域首字节。


当按下button1的时候U2发送数据帧,U1进行接收并且对接收数据继续校验,如果校验无误,那么进行显示。


按下button1结果如下


中间的01由于是空格的ASCII码值所以1602显示空格。由于数据域我是采用数组存放数据方式,LCD显示代码以C语言中的’ ’结束显示,所以校验字节没有显示出来,我将它投影到端口B上,端口B的状态是0X37。这样也就验证了这个简单的Modbus协议的正常传输。

按动U2的button2可以主动产生一个LRC校验错误。(我在代码校验的时候也没有采用标准的LRC校验,只是进行了累加校验)。U2在对数据帧填充完毕的时候刻意更改校验值,将更改后的数据帧发送给U1,U1接收后进行校验则产生校验错误提示。按下button2结果如图


从虚拟终端中我们可以看出,我们手动更改了校验值,由0x37更改成0XFF,那么U1接收到的数据进行校验那么就会产生校验错误提示。。。实际校验结果还是0X37,但是我们在发送前将校验改成了0XFF,导致接收方校验0x37 !=0xff,从而产生错误。。。


按下button3回产生数据帧错误。按下button3,U2刻意发送一个不完整的数据帧。如果数据帧不完整,U1不可能进行无限时间的等待。所以U1使用定时器0进行超时判断,如果超过10ms,数据帧依然不完整那么判断此数据帧为错误帧。。结果如下。


在事件3中我们可以让U2不发送校验码,导致该帧数据不完整。U1等待10ms后判定该数据帧是帧错误。。


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32学习笔记4:外部中断