首页 > 代码库 > 基于AVR128的简单Modbus协议实现

基于AVR128的简单Modbus协议实现

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协议0X300X31是表示的从机地址,0X33是表示命令字符,0X01表示数据域长度,0X34表示数据域,0X37是进行的LRC校验。我们采用这种方式进行简化是为了方便1602进行显示,其中0x01ASCII码中的空格’‘也能够在1602中进行显示。

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


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

按下button1结果如下


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

 

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



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

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


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

 

该仿真的仿真程序和仿真工程存放到网盘地址http://yun.baidu.com/share/link?shareid=368414814&uk=840368654&third=0

里边包含了U1 和U2的工程代码分别在各自的MAIN文件夹中。仿真文件在ISIS文件夹中。希望对你有帮助。88