12下一页
返回列表 发新帖本帖赏金 3.00元(功能说明)

论RS485总线如何实现多主通信

[复制链接]
3907|41
 楼主 | 2016-5-5 15:54 | 显示全部楼层 |阅读模式
本帖最后由 幸福至上 于 2016-5-12 15:39 编辑

    RS485是一种常用的工业现场总线,由于其只是电气连接,所以在使用时,还需要一个通信协议来定义各设备的具体通信方式,以实现多设备有秩序地使用总线。
一般地,RS485总线上所使用的是一主多从通信协议,采用轮询方式进行数据通信。也即一条RS485总线上,只有一台主机,其余的都是从机,主从机之间要进行通信时,是需要主机依次轮询,轮询到了要发数据的从设备,从设备才能发送数据。这种通信方式存在通信实时性,可靠性差,而且各个从设备之间是不能通信的。另一种稍微高级一点的RS485通信协议可以实现从设备之间的通信,但这还是需要主设备的协调。有点类似于USB通信协议,工作机理大致如下:从设备首先向主设备发送数据发送请求或数据,再由主设备将数据发送给另外的从设备这种方式。
    我想构建一种基于RS485总线的多主通信协议,所有挂载在RS485总线上的设备均可自由地使用总线,而不需要先向主机申请。这样的话就能够大大提高地提高总线上设备的实时性,可靠性。在这之中,比较关键要解决的是:总线竞争以及仲裁机制。
为此,我设计了这样一个机制:设备在RS485总线进行数据发送前,先检测当前总线是否有数据正在传输,如果没有,则先发送一串数据,用以声明总线被占用。然后进行有效数据发送,并等待DATA_ACK.
数据目标设备在接收到数据后,此时仅可发送DATA_ACK信息,用以告诉数据发送设备已经收到信息。之后数据发送设备,再次在总线上发送信息,声明释放总线。在这期间,其它挂接在RS485总线上的设备也能够接收到数据,不过因为总线已经被声明占用,将不得
发送任何数据。
    在这之中,发现两个可能的原因还是会导致总线竞争:    1、RS485总线上的设备接收到的总线占用和总线释放声明信息有误码,导致解析失败。设备就相当于没有收到总线占用和释放声明,而如果这个期间进行数据发送,就可能出错。
    2、RS485总线上,有两个或多个设备,同时声明总线占用。此时已经导致总线竞争,从而所有设备都没有收到有效的总线占用信息,那么之后的数据发送仍会很有可能出现总线竞争。
    当然,所有的设备在进行任何数据发送前,都会先进行总线载波检测,以判断当前总线上是否有数据发送。但仍有一定的概率出现两设备几乎同时开始发送一串数据的第一位数据,从而导致竞争。
    查看了一下CAN总线的总线竞争以及仲裁机制,其接口芯片可以一边发送,一边读取当前总线状态,如果发送位和读取到的总线状态不一致,则自动丢失总线权,这种非破坏的总线竞争方式挺好,就是貌似RS485上无法实现,因为RS485芯片不能边发送边读取。
大家麻烦给点意见哦,也不知有哪位成功实现了这种多主通信的吗?
=====================================================分割线=========================================================>>
结贴前,对大家讨论的结论归纳如下:
要实现RS485总线上的多主通信机制,首先在硬件设计上,需要能够让485芯片的TX和RX使能分别单独控制;采用半驱方式进行485总线驱动更好,这样可以实现类似CAN总线的总线竞争检测以及仲裁机制;
软件设计上,每个设备在进行总线数据发送前,必须先侦听总线是否有数据正在传输,如果没有,则启动传输。在传输的过程中,在逐字节地发送数据的同时,也一直侦听并读取总线上的数据,如果读取到的数据和发送的不一致,就说明总线上此时还有其它设备正在发送,由此实现总线竞争检测;
如果要做到类似CAN的无破坏总线竞争检测以及仲裁,那么还需要做到传输数据的逐位检测,不过这貌似对一般的Uart口来说并不容易实现;
另一种比较稳定的多主通信方式就是使用令牌,令牌在各个设备之间传递,只有拥有令牌的设备才有总线使用权。
以上为讨论后的归纳总结,非常谢谢各位朋友的指点。



打赏榜单

xyz549040622 打赏了 3.00 元 2016-05-06
理由:欢迎继续分享!

| 2016-5-5 17:14 | 显示全部楼层
1.首先要解决电气层的冲突,半驱基本可以;
2.要有退出和重试机制。
上面2条都可以参考CAN的做法。
 楼主 | 2016-5-5 18:23 | 显示全部楼层
fzyuan 发表于 2016-5-5 17:14
1.首先要解决电气层的冲突,半驱基本可以;
2.要有退出和重试机制。
上面2条都可以参考CAN的做法。 ...

请问半驱是什么意思?退出和重试的机制肯定是需要的,我是这么设计的:
退出:1、收到数据接收方的Data_Ack;2、如果是发送Data_Ack,则发送完毕直接退出;3、重发超过最大次数限制;
重试:1、规定时间内没有收到Data_Ack,则重发数据,且重发次数+1;2、重发次数超过最大限制,则退出。
关于总线竞争检测,我发现RS485芯片似乎可以这样做:分别控制RS485的发送和接收控制管脚,使RS485芯片一直可以接收数据,在仅需要进行数据发送时,控制RS485发送管脚进行数据发送。这样一帧数据发送完毕之后,再从Uart接收区读出并比对,如果收发一致,则无总线竞争,否则就是出现了总线竞争。
| 2016-5-5 22:05 | 显示全部楼层
半驱是指:485芯片只发送逻辑0,而逻辑1则由485接收方由失效保护的上下拉得到,简而言之,485芯片的TxD端接地,MCU的TxD反相后接到485的DE端,485的RE始终使能。
退出应是发送者自觉的,只要监测到自己发送的数据有误(应检查每个字节),就停止发送。
任何发送者在发送前必须探测总线状态,遇忙应随机延时后重新探测。
| 2016-5-6 08:54 | 显示全部楼层
全双工的485可以实现边发边收的。你这个多主机的没想过,485的双机通讯就是可以做到主从切换的。
 楼主 | 2016-5-6 11:55 | 显示全部楼层
本帖最后由 幸福至上 于 2016-5-6 11:56 编辑
xyz549040622 发表于 2016-5-6 08:54
全双工的485可以实现边发边收的。你这个多主机的没想过,485的双机通讯就是可以做到主从切换的。 ...

谢谢建议,我上网查了一下,找到了一个RS485全双工的硬件连接图,如下:

如果该图正确的话,即RS485全双工工作时,设备接收端接在其它设备的发送总线上,设备的发送端接在其它设备的接收总线上。这样的话,如果还是有两个设备同时要发送数据,产生了总线竞争,依然是不能检测到的。
我猜想这种全双工的RS485应该还是工作在主从模式,最左边的应该是主机,因为其发送端接在其它几个设备的接收端。那么主机发送到从机的信息是不会产生竞争的,而从机要发送数据,则要和其他从设备共用总线,如果要避免竞争,肯定还是需要
主机设备来从中协调。
我准备这样来做个试验:使用半双工的RS485芯片,其内部结构如下:

可以看出,其内部结构的接收和发送是各自由独立管脚控制的,所以我想这样设置:SP485芯片的RE管脚一直拉低,使RO管脚能够一直吐出总线上的有效数据。设置DE管脚平时为低,发送数据时,为高进行数据发送,发送完毕后又置低。
这样,当数据发送完毕后,其实发送设备自己也应该收到一份自己发出的数据。
查看该芯片的收发真值表,如下:

从左图可以看出:当发送数据时,RE管脚的电平不影响数据发送。从右图来看:当接收数据时,DE管脚都是设置为0,但也并没明确说明DE为1就不行。因为我刚开始调试485时,有遇到过自己发送的数据自己能收到的现象,估摸就是因为当时芯片的RE和DE管脚是各自分开控制的。
接下来准备做个试验来验证下,如果可行的话,就可以实现类似CAN总线的总线竞争检测机制了。;)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2016-5-6 16:42 | 显示全部楼层
fzyuan 发表于 2016-5-5 22:05
半驱是指:485芯片只发送逻辑0,而逻辑1则由485接收方由失效保护的上下拉得到,简而言之,485芯片的TxD端接 ...

哦。对的。你这所说的半驱很类似CAN总线的做法:也是只发送逻辑0,平时由上下拉电阻将总线置为逻辑1。我现在采取的做法思路和你所说大致相同的:485的RE始终使能,可以一直监听总线上的数据,发送数据前先判断总线状态,空闲才发送。待到发送一个或一帧发送完毕后,对收发数据进行比对,由此来判断是否出现了总线竞争情况。485芯片还可以这样用,还真没想到。
你这里的"只要检测到自己发送的数据有误(逐个字节),就停止发送"。这样做,产生总线竞争的所有设备还是都需要重发数据,因为不能逐位检测发送数据。这就是和CAN总线不同的地方,CAN总线能够做到逐位检测,以实现无破坏的总线竞争检测。

评论

dukedz 2018-4-7 21:20 回复TA
RS485 也完全可以跟 CAN 一样逐位检测,见 #10 楼。 
| 2016-5-6 23:58 | 显示全部楼层
这种冲突检测+竞争想靠软件做好还是不容易的,RS485多主总线大多都是采用令牌总线方式

评论

dukedz 2018-4-7 21:54 回复TA
没错,靠软件不容易,但可以靠专用的硬件控制器,见 #10 楼连接。 
 楼主 | 2016-5-9 15:18 | 显示全部楼层
yhn1973 发表于 2016-5-6 23:58
这种冲突检测+竞争想靠软件做好还是不容易的,RS485多主总线大多都是采用令牌总线方式 ...

嗯,令牌总线方式是一种比较稳定可靠,485时序很明确的方式,以后可以尝试一下。现在用边接收边侦听方式也初步实现了总线竞争检测机制,待进一步实验进行验证。
| 2017-6-17 12:03 | 显示全部楼层

效率

本帖最后由 dukedz 于 2018-4-16 13:18 编辑
幸福至上 发表于 2016-5-9 15:18
嗯,令牌总线方式是一种比较稳定可靠,485时序很明确的方式,以后可以尝试一下。现在用边接收边侦听方式 ...

对于 RS485 多主冲突的问题,开源的 CDBUS 协议就可以完美解决,使用配套的控制器模组/芯片,很简单的就实现了多主对等通讯,而且速率可以达到 10Mbps 及以上,有人拿来传视频都没有问题。原理跟 CAN 一样,是非破坏性仲裁,但用起来方便很多:github.com/dukelec/cdbus_doc/blob/master/intro_zh.md

令牌实时性不好,效率也差,还要协商谁来发令牌,很麻烦,出错的机会多。
有些做法,即使没有数据,也要不停传递令牌,效率低下,调试抓包时有意义的数据完全被洪水淹没。而且配置麻烦,也没那么自由,譬如很难实现设备动态接入移出,万一掉线一台设备,可能就麻烦了。

CDBUS 的仲裁测试,场景是两台电脑通过 RS485 通讯,下载文件、连续几天上网播放 MV 视频:

/dev/ttyUSB1 对应的设备优先级较低,所以在完成单向发送了一千六百多万个数据包的时候,一共顺利主动避让了 9753 次数据冲突,除此以外,无一错包、丢包发生。(避让冲突后硬件会自动重发数据包)

测试的 RS485 波特率为 1Mbps + 10Mbps, 用 2 米多的杜邦线连接。

而且就算短路总线、断开总线等人为破坏测试,上层 CDNET 协议也会自动重传出错的数据包,以保证用户数据完整性。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2017-6-18 20:59 | 显示全部楼层
赚积分下东西
| 2017-6-19 11:53 | 显示全部楼层
你可以参考无线通讯的一些办法,原则上还是一个主机控制,但只发一个时间计数,每个需要发送数据的分主机会根据这个时间计数做分时,具体的就简单了。
| 2017-6-19 11:54 | 显示全部楼层
如下图的参考时序

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2017-6-19 12:25 | 显示全部楼层
为啥不直接用can?你这个做法很不合适。

评论

dukedz 2018-4-7 21:21 回复TA
CAN 最快 1Mbps, 最多传 8 个字节,性能太差。 
z_no1 2018-4-14 08:54 回复TA
@dukedz : CAN性能再差,485上了令牌,算上协议的消耗,只能比CAN更差. 既然厂家又发明了CAN,肯定是有优势的.不然你以为他们傻吗? 我就是要从485转CAN的一个.  
dukedz 2018-4-15 11:48 回复TA
@z_no1 :沒說上 485 就要用令牌啊,完全可以和 CAN 用一樣的按位仲裁避免衝突啊,485 是最經典的總線,而 CAN 被 485 和 工業以太網 聯合夾擊,快不行了 
z_no1 2018-4-15 17:28 回复TA
@dukedz :CAN行不行,见仁见智吧,485如果是单主多从,还算可以,多主多从,理论上是可以的,可要加不少代码,速度也不会很快,所以还是在自己适合的环境下用. 
dukedz 2018-4-16 13:16 回复TA
@z_no1 :不用加代码,硬件控制器处理就好,你可以去了解一下最常见的 RS485 对等通讯控制器 CDCTL-Bx 
| 2017-6-19 12:28 | 显示全部楼层
mark,好文
| 2017-7-2 09:16 | 显示全部楼层
半双工的方式用数据检测是可以识别总线冲突的,然后一直监测总线等待总线空闲
| 2018-4-7 21:10 | 显示全部楼层
本帖最后由 dukedz 于 2018-4-7 21:40 编辑
苏山人家 发表于 2017-7-2 09:16
半双工的方式用数据检测是可以识别总线冲突的,然后一直监测总线等待总线空闲 ...

我曾经天真的想法:
发送数据的时候同时接收,然后比对数据是否相同,相同就认为没有发生冲突。。。
如果检测到冲突就等个随机时间再重新发送啰,虽然会牺牲很多效率。。。

然而,由于线路导线的电阻存在,当两个节点同时发送数据时,一个人发 0,一个人发 1:那么发 0 的人读回来的是 0,发 1 的人读回来的还是 1。因为每个节点就近读回来的是自己推挽发出的数据,0 和 1 数据的压差全被线路承受了。也就是说这种想当然的方法就连冲突检测都无法胜任。
楼上讨论的半驱虽然理论上可以解决,但实际上冲突的时机也会有一定的影响,譬如某个节点回读总线的数据的时候,总线数据恰好跳变,那么它有一半的机率误判。(因为软件没那么实时,很难对一个位宽度内的时间做很好的把控)

还有就是检测到总线当前为空闲才发送数据的做法,根本没法保证不会有多个节点同时发送数据。

所以还是建议使用 #10 楼的方法,简单、完美解决问题。

| 2018-4-9 09:28 | 显示全部楼层
dukedz 发表于 2018-4-7 21:10
我曾经天真的想法:
发送数据的时候同时接收,然后比对数据是否相同,相同就认为没有发生冲突。。。
如果 ...

如果存在一个主机,可以用分时复用来给每个子节点做时间片分配,也可以学学USB做热拔插
如果没有等级都相同速率不高不如CAN(CAN就是利用线与的加ID来判断碰撞和优先级)

评论

dukedz 2018-4-9 12:48 回复TA
时间分配比较复杂、低效率、低实时性,且不好添加备用主机,譬如当前主机死机,轻则影响生产进度,重则导致事故。10 楼的方案就跟 CAN 原理一样。 
| 2018-4-12 14:31 | 显示全部楼层
再多主的协议也是有优先权的吧!所以说不存在什么多主的,只是说法不同而已。

评论

dukedz 2018-4-16 13:21 回复TA
这可不只是说法不同,不支持多主的协议两个节点同时发送数据,数据会破坏;支持多主的协议其数据永远不会因为冲突而破坏。 
| 2018-4-13 17:11 | 显示全部楼层
有啥 好 讨论的,直接 用 CAN 就可了,CAN的成本 比485 低

详细见:
http://bbs.21ic.com/icview-1945634-1-1.html
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

关闭

热门推荐上一条 /4 下一条

分享 快速回复 返回顶部 返回列表