1. 主从模式 RS-485上的软件层协议ModBus主要依赖于主从模式。主从模式是指在半双工通讯方式上,2个或者2个以上的设备组成的通讯系统中:/ H# T/ l$ r" l* j+ n5 f/ Z! J8 t (1) 至少且只有一个主机,其他的都是从机' L3 i6 v! S9 }% M% p$ ], w (2) 不管任何时候,从机都不能主动向主机发送数据: C# N4 q: _% p' a (3) 主机具有访问从机的权限,从机不可以主动访问从机,任何一次数据交换,都要由主机发起6 x9 ?' H; S- R" U2 [8 m4 F (4)不管是主机还是从机,系统一旦上电,都要把自己置于接收状态(或者称为监听状态) 主从机的数据交互,需要:$ |& n* i- h: P% a, [+ `) p8 n; s a. 主机将自己转为发送状态 $ k, h0 T. {2 h1 }. ]! u; s) P b. 主机按照预先约定的格式发出寻址数据帧。 所谓的约定,可是主机开发者和从机开发者约定好的规约,好,例如主机要通过从机控制接在从机的电机,主机要启动电机就往从机发0x1,停止电机就往从机发0x2。这就是一种预7 V0 j0 x E3 m/ o# W 先约定好的格式,但是这样做,互换性、兼容性、通用性差,例如其他公司是约定发送0x03让电机转动,发0x04让电机停止。导致不同厂家的主机、从机不能相互通讯。用户需要的,就像网络操作,只要接入有网的网线那么计算机都能上网。 所以说,我们需要一种大家都共同遵循的规则(可以是ModBus,也可以是TCP/IP等上层协议),这种大家认可,共同遵循的软件层协议。软件层协议主要是解决如何解析传输的数据,即传输的目的或者更加可靠的传输数据。 半双工通讯中,都是主机寻找从机,主机的目的无非有: 主机要发数据给从机,或者主机要从从机中获取数据。 6 r5 j* ~0 w3 h$ z8 C+ ^# \% e* K; N c. 主机恢复自身的接收状态% t5 u& D% y6 I( t- A8 {) ? 主机等待自身所寻址的从机作回应,也就是说从机接收到主机的寻址命令、数据后一定要回应主机,不然主机会认为从机通讯异常。回应数据包也是要按照ModBus协议规约(其实不局限ModBus,像TCP/IP也需要回应是吧!~), C* U0 k. A0 A, v: d/ E 9 Z% y% H, F7 i2 U( D& c 2. ModBus通讯协议* e& N' _5 s6 W. _, h: {) ~ 通俗点来讲,ModBus规约了起停电机,主机要分别发送什么命令给从机。ModBus规定主从机之间数据的交互,需要遵循什么样的格式,如何保证数据在传输过程中不发生冲突。只要都遵循这个协议,那么不同厂家的主从机就可以共用了。 ModBus一般是工作在一主多从的场景,还是这个图: 主机和从机之间的连线不一定是非要485来作为载体,也可以是IIC,SPI。因为ModBus是软件层的协议,它既可以规约485硬件接线方式,也可以规约其他硬件接线方式。很多资料会写”基于RS-485的ModBus通讯协议”,意思是底层的0、1数据是通过RS-485方式去传输的,0、1的意义则是通过ModBus去解析的。强调,硬件协议可以确保数据得以传输出去,软件协议保障数据的有序传输,数据不会发生冲突。8 G: w6 t1 w) l9 P N7 V T ModBus规定: (1) 主从模式! ^9 ~" [9 X( l8 A4 {0 w) O 有的协议规定是多主模式,意思是系统中的设备都是主机,它们并没有主从之分,任何时刻,谁想发送数据都可以往总线上发送,例如网络通信、CAN总线通讯,自然它们自有一套防止数据冲突机制,485由于不具备冲突检测的硬件机制,所以它必须遵循主从模式。主从模式的原则是,整个系统只能有一个主机,每一个从机都必须有一个唯一的地址) C: o( _. A' O6 o9 q 4 A/ n/ d' v4 m0 s! V( e1 Y+ E (2) 从机的地址是作为每个从机的唯一标识。地址取值是0-247,0号地址表示广播地址,广播地址由主机保留,当主机向0号地址发数据包的时候,每一个从机设备都会收到数据包。也就是说,当主机发出的寻址帧的地址是0的时候,所有从机都要执行主机要求的动作。按理说,从机收到主机的寻址帧之后,是要做出应答包的,但是现在是0号地址,也就是要回的话每台从机都要回,那么肯定会造成RS-485通讯线上的数据混乱,因此所有从机在主机发0号地址时候不予返回数据包应答。 从机的地址有两个作用 a. 主机向目标从机发寻址帧时其地址部分为从机地址,这样主机才可以检索到目标从机. i; A9 x9 q' o6 ]: Y7 _ b. 对于主机的目标从机,当收到主机发来的非0地址时,要做出数据包应答,假设从机要返回数据包给主机,自然是要把数据包放到RS-485总线上,因为每台从机,其物理连线是在一起的,所以这就会造成其他从机认为数据是要发送给它的现象,所以在从机回复主机的数据包中,加上从机自身的地址,那么其他从机读取到这个地址值跟自己的地址不相同,就不会去响应了。 ( y! g3 b- |1 z9 d4 Z& w0 a3 D (3) ModBus数据包的格式# m4 |- Y a! s; }: F 主机要寻找某台从机,需要发出相应格式的信息,这就需要谈到ModBus的两种传输方式: a. RTU传输方式 RTU实际上也成为二进制方式。假设主机要发送0x23,那就是发送0010 0011,按照485通讯协议,先发高位,即1100 0100。前后分别加上起始、停止位: “起始位 1100 0100 停止位”共10位数据 b. ASC传输方式. F5 ~1 a. w+ U5 d# C8 `8 ] O 同样要发送0x23,它是十六进制数,会将其拆成十位的’2’和个位的’3’,将它们的asc码依次发出去,’0’的asc码是0x32,’3’的asc是0x33,转为二进制为0011 0010和0011 0011,同样要加上停止、起始位,共20位数据 很明显,asc传输方式比较低,但是由于它传输的是asc码,所以可以利用一些串口终端将其数值打印出来。 0 ]! ?* |( w/ z5 q ) R. O# F( D4 ^ i 特别提醒,RS-485硬件协议决定,对于每一个字节数据的传输是先发高位,再发地位,所以假设数组u8型数组revArr[2]存放着接收到的数据,那么接收端解析数据应该是u16型data = revArr[0] * 256 + revArr[1]。 2 ^% G; R/ [' ^: ?- }# y 在工业控制、电力通讯、智能仪表等领域,通常情况下是采用串口通信的方式进行数据交换。最初采用的方式是RS232接口,由于工业现场比较复杂,各种电气设备会在环境中产生比较多的电磁干扰,会导致信号传输错误。除此之外,RS232接口只能实现点对点通信,不具备联网功能,最大传输距离也只能达到几十米,不能满足远距离通信要求。( e; X# u/ D, y, T " ]$ t8 b9 ~% v) E) A: g 而RS485则解决了这些问题,数据信号采用差分传输方式,可以有效的解决共模干扰问题,最大距离可以到1200米,并且允许多个收发设备接到同一条总线上。随着工业应用通信越来越多,1979年施耐德电气制定了一个用于工业现场的总线协议Modbus协议,现在工业中使用RS485通信场合很多都采用Modbus协议,所以今天我们来了解下RS485通信和Modbus通信协议。 . v! `7 K3 \& h; l0 e* G+ q) E 【RS485通信】2 i2 G& L! |- j$ M1 ^ , D* g% Q# `6 I( A* N+ p9 C; w & j% A/ g2 y# W: f7 g# G5 l8 Q 实际上在RS485之前RS232就已经诞生,但是RS232有几处不足的地方:- n6 E% u+ n% m0 O9 A F , j8 n$ l2 c( e+ `& a 1、接口的信号电平值较高,达到十几V,容易损坏接口电路的芯片,而且和TTL电平不兼容,因此和单片机电路接起来的话必须加转换电路。- `, u4 J/ L- ]. N+ B. u 2、传输速率有局限,不可以过高,一般到几十Kb/s就到极限了。& f- E4 A+ E9 u / P5 e5 L n( [# q& O 3、接口使用信号线和GND与其他设备形成共地模式的通信,这种共地模式传输容易产生干扰,并且抗干扰性能也比较弱。 + i: L* a, ^5 |2 V 4、传输距离有限,最多只能通信几十米。 ; L. k! q0 V" F8 b" a( M 5、通信的时候只能两点之间进行通信,不能够实现多机联网通信。 针对RS232接口的不足,就不断出现了一些新的接口标准,RS485就是其中之一,他具备以下的特点: # ^/ G9 q/ ]4 ?( e, D+ K 1.逻辑“1”以两线间的电压差为+(2—6)V表示;逻辑“0”以两线间的电压差为-(2—6)V表示。接口信号电平比RS232C降低了,就不易损坏电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接。# v! L# c6 _7 j # t7 P3 t9 w1 L! \$ Z4 N 2.RS485通信速度快,数据最高传输速率为10Mbps以上* n% D3 j; i+ P/ F$ a 0 l2 q6 w0 _& Q5 o 3.RS485内部的物理结构,采用的是平衡驱动器和查分接收器的组合,抗干扰能力大大增加。; j' g/ k4 j/ e; t 4.传输速率最远可达到1200米左右,但是他的传输速率和传输距离是成反比的,只有在100KB/s以下的传输速率,才能达到最大的通信距离,如果需要传输更远距离可以使用中继。: o. J" Z6 o3 a# g- s , G; m4 ^2 e. s: W! M: V4 { 5.可以在总线上进行联网实现多机通信,总线上允许挂多个收发器,从现有的RS485芯片来看,有可以挂32、64、128、256等不同个设备的驱动器。- O( ?' x$ h- a" ` & N4 P3 ^& e- W% J RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。RS-485采用半双工工作方式,任何时候只能有一点处于发送状态,因此,发送电路须由使能信号加以控制。RS-485用于多点互连时非常方便,可以省掉许多信号线。应用RS-485可以联网构成分布式系统,其允许最多并联32台驱动器和32台接收器。在RS232或RS485设备联成的设备网中,如果设备数量超过2台,就必须使用RS485做通讯介质,RS485网的设备间要想互通信息只有通过“主(Master)”设备中转才能实现,这个主设备通常是PC,而这种设备网中只允许存在一个主设备,其余全部是从(Slave)设备。0 b1 P- C9 _( H M" B! ^3 N3 Z RS485有两线制和四线制两种接线,四线制只能实现点对点的通信方式,现很少采用,现在多采用的是两线制接线方式,这种接线方式为总线式拓朴结构在同一总线上最多可以挂接32个结点。在RS485通信网络中一般采用的是主从通信方式,即一个主机带多个从机。很多情况下,连接RS-485通信链路时只是简单地用一对双绞线将各个接口的“A”、“B”端连接起来。而忽略了信号地的连接,这种连接方法在许多场合是能正常工作的,但却埋下了很大的隐患,这有二个原因:( Q! B1 H) A# A0 K (1)共模干扰问题:RS-485接口采用差分方式传输信号方式,并不需要相对于某个参照点来检测信号,系统只需检测两线之间的电位差就可以了。但人们往往忽视了收发器有一定的共模电压范围,RS-485收发器共模电压范围为-7~+12V,只有满足上述条件,整个网络才能正常工作。当网络线路中共模电压超出此范围时就会影响通信的稳定可靠,甚至损坏接口。 (2)EMI问题:发送驱动器输出信号中的共模部分需要一个返回通路,如没有一个低阻的返回通道(信号地),就会以辐射的形式返回源端,整个总线就会像一个巨大的天线向外辐射电磁波。由于PC机默认的只带有RS232接口,有两种方法可以得到PC上位机的RS485电路:(1)通过RS232/RS485转换电路将PC机串口RS232信号转换成RS485信号,对于情况比较复杂的工业环境最好是选用防浪涌带隔离珊的产品。(2)通过PCI多串口卡,可以直接选用输出信号为RS485类型的扩展卡。/ i6 w3 c$ I+ X _4 n + f, I- y2 C3 h: F4 j* q) c4 Z 【Modbus通信协议】, h3 a Y& \, G; _9 V9 L a f0 F8 r9 i1 H3 q Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。 " G( z# h( W2 @. o& e( T( A Modbus具有以下几个特点: (1)标准、开放,用户可以免费、放心地使用Modbus协议,不需要交纳许可证费,也不会侵犯知识产权。目前,支持Modbus的厂家超过400家,支持Modbus的产品超过600种。" a' e( F( O# v. y9 K 1 U( u+ R9 w1 L4 I) ^) p' Q (2)Modbus可以支持多种电气接口,如RS-232、RS-485等,还可以在各种介质上传送,如双绞线、光纤、无线等。 3 H+ E1 B, Q2 Z4 E2 @ (3)Modbus的帧格式简单、紧凑,通俗易懂。用户使用容易,厂商开发简单。6 E) P( G5 T! p( G6 y7 b R【TU协议帧数据】7 L0 M- J) w7 y3 N" O& F Modbus有两种通信传输方式,一种是ASCII模式,一种是RTU模式。由于ASCII模式的数据字节是7bit数据位,51单片机无法实现,而且应用也相对较少,所以这里我们只用RTU模式。两种模式相似,会用一种另外一种也就会了。一条典型的RTU数据帧如图所示。+ Q8 Z& N6 W6 Z2 A ; o; ?3 N0 m5 Z" V& {6 J 和我们实用串口通信程序类似,我们一次发送的数据帧必须是作为一个连续的数据流进行传输。我们在实用串口通信程序中采用的方法是定义30ms,如果接收到的数据超过了30ms还没有接收到下一个字节,我们就认为这次的数据结束。而Modbus的RTU模式规定不同数据帧之间的间隔是3.5个字节通信时间以上。如果在一帧数据完成之前有超过3.5个字节时间的停顿,接收设备将刷新当前的消息并假定下一个字节是一个新的数据帧的开始。同样的,如果一个新消息在小于3.5个字节时间内接着前边一个数据开始的,接收的设备将会认为它是前一帧数据的延续。这将会导致一个错误,因此大家看RTU数据帧最后还有16bit的CRC校验。# @ Y) R6 j! b6 f8 F: N 9 p6 Y0 C5 @7 K8 ]- B8 p 起始位和结束符:前后都至少有3.5个字节的时间间隔,起始位和结束符实际上没有任何数据,T1-T2-T3-T4代表的是时间间隔3.5个字节以上的时间,而真正有意义的第一个字节是设备地址。+ l0 [) O b @7 ? + f0 ^3 O9 f0 }5 j 设备地址:在多机通信的时候,数据那么多,我们依靠什么判断这个数据帧是哪个设备的呢?没错,就是依靠这个设备地址字节。每个设备都有一个自己的地址,当设备接收到一帧数据后,程序首先对设备地址字节进行判断比较,如果与自己的地址不同,则对这帧数据直接不予理会,如果如果与自己的地址相同,就要对这帧数据进行解析,按照之后的功能码执行相应的功能。如果地址是0x00,则认为是一个广播命令,就是所有的从机设备都要执行的指令。 & ]" E! O; z- a& ? p 功能代码:在第二个字节功能代码字节中,Modbus规定了部分功能代码,此外也保留了一部分功能代码作为备用或者用户自定义,这些功能码大家不需要去记忆,甚至都不用去看,直到你有用到的那天再过来查这个表格即可。 6 T% [! s1 x3 w CRC校验:CRC校验是一种数据算法,是用来校验数据对错的。CRC校验函数把一帧数据除最后两个字节外,前边所有的字节进行特定的算法计算,计算完后生成了一个16bit的数据,作为CRC校验码,添加在一帧数据的最后。接收方接收到数据后,同样会把前边的字节进行CRC计算,计算完了再和发过来的CRC的16bit的数据进行比较,如果相同则认为数据正常,没有出错,如果比较不相同,则说明数据在传输中发生了错误,这帧数据将被丢弃,就像没收到一样,而发送方会在得不到回应后做相应的处理错误处理。3 L5 O/ |1 R# Q4 w( ~. q4 A- o$ i ) {0 g& e! P, i" R+ G' `5 e |