RS485是最常见的一种远距离可靠传输和组网的UART串口信号接口协议。与同样传输UART串口信号的RS422协议相比,RS485使用半双工通信,即只有一个信道,在同一时刻要么从A到B,要么从B到A传输信号;而不能同时双向传输信号。因此理论上说,每个RS485接口芯片就都需要一个“收发切换”信号,以控制该接口芯片当前是发送还是接受信号。在单片机系统中就往往需要一个额外的GPIO来控制收发状态的切换。这本来是显而易见的道理,我已经见惯不怪了,但有一天突然看到市面上有供PC或工控机使用的UART-RS485转换器,我迷惑了:它是如何通过PC输出的UART实现RS485收发切换控制的呢?
显然,这不是通过PC软件控制收发的,那就一定有硬件电路实现了“RS485自动收发切换”功能。我查阅了网络,发现还真有一些公开电路,我根据自己对这些公开电路优缺点的分析,也自创了一种RS485自动收发切换电路,与广大网友共享。
以下原创内容欢迎网友转载,但请注明出处: https://www.cnblogs.com/helesheng
一、常见RS485接口电路(无自动收发切换功能)
各大半导体公司都有自己的RS485收发器,且解法基本相同,这里给出典型的收发器解法。
图1
使用RS485协议组网通信的工程项目中,往往采用图1所示的电路作为每个网络节点的接口电路。所有节点的差分信号线对:RS485_A/RS485_B,则被短路到一起进行通信。由于网络中所有节点的通信信号RS485_A/RS485_B全部被短接在一起,因此每个时刻只能有一个通信节点处于发送状态,而其他节点的RS485_A/RS485_B信号只能处于高阻态,否则两个处于发送状态的节点将发生“撞车”,而无法通信。
为实现上述功能,RS485接口芯片提供了写使能管脚DE和读使能管脚#RE。为节约单片机管脚,两者的逻辑是相反的:DE为高电平有效,低电平无效;#RE为低电平有效,低电平无效。如图1所示,它们可以被短接在一起由一个GPIO控制。每个节点的单片机在认为该自己占据RS485_A/RS485_B总线发送数据时,将USART_EN信号拉高,从而使接口芯片退出高阻态,控制差分信号的电平。
二、RS485自动收发切换电路
本文的目的,是总结常见的自动收发切换信号USART_EN信号产生电路,从而为省去其占用的GPIO,以节约单片机资源并为PC等不具备GPIO的设备提供收发控制。
1、低成本自动收发切换电路
下图所示的是网络中可以查阅得到的最常见RS485收发自动控制电路。
图2
图2电路设计非常精巧,其原理为:1、但UART发送管脚USART_TX输出低电平时,三极管Q1截止,接收使能#RE和发送使能DE同时被R6拉高,接口芯片进入发送状态。此时会将连接到发送信号管脚DI上的低电平发送除去,从而在差分输出RS485_A/RS485_B上得到逻辑低电平对应的输出。2、当USART_TX管脚发送高电平时,三极管Q1导通,接收使能#RE和发送使能DE同时被拉低,接口芯片进入接收状态,A、B两个管脚为高阻态。但此时连接到RS485_A/RS485_B上的其他网络节点,却会因为电阻R2和R3(4.7KΩ)的上下作用,将RS485_A/RS485_B上的高阻态理解为高电平。因此,图2虽未直接将USART_TX的信号发送到RS485_A/RS485_B上,但却在逻辑上同时起到了发送数据和自动控制收发状态切换的作用。
图2中的电路,几乎不需要增加附加成本(小功率NPN三极管非常便宜,且不占PCB面积),应该是大部分PC或工控机使用的UART-RS485转换器所使用的原理,被很多老工程师奉为经典。
但我窃以为这个电路有着明显的缺点,在对成本不敏感的高可靠性工控产品中未必是最佳选择。原因如前所述:图2输出的高电平不是由接口芯片直接驱动的,而是在接口芯片进入高阻态后,由上下拉电阻R2和R3产生的。正常情况下一般RS485接口芯片驱动能力可轻松达30mA以上(表1为MAX485的驱动能力),从而保障了RS485接口电路的驱动距离、负载数和强干扰环境下的可靠性。
表1 MAX485驱动能力
但图2所示电路高电平的短路驱动能力(Driver Short-Circuit Current)仅为VCC/(R2+R3)。为了保证输出低电平时系统的总体功耗,R2和R3又不可能太低,如图2所示仅为4.7KΩ,显然无法完全发挥RS485接口的驱动和抗干扰能力。
2、自创的高性能自动收发切换电路
我自己反复分析图2电路的优缺点后,也未能找到更有效的解决方案。一觉醒来,发现上述电路的本质问题是单片机和接口电路交互的信息熵不足的问题:接口电路需要单片机高速自己1)高阻接收,2)驱动发送高电平,3)驱动发送低电平三种不同可能的信息熵;但单片机如果只使用USART_TX一个GPIO向接口电路发送信息,则只能表述1bit,两种不同可能的信息熵。因此这个问题是不可能完整解决的,只能牺牲掉某种性能才能换取部分实现所需的功能。图2的电路就是牺牲了区分高阻态和发送高电平的性能,实现了收发的自动切换。
我考虑还可以使用牺牲部分发送时间的方式,实现收发的自动切换:在单片机和RS485接口之间增加一个可重复触发的单稳态触发器。
如图3所示,UART帧协议总是由一个低电平码元构成的起始位作为一个字节的开始,而空闲时USART_TX总是停留在高电平。
图3
将USART_TX连接到可重复触发单稳态触发器的输入端,而单稳态触发器的输出则连接到RS485接口电路的发送使能管脚DE。这样单稳态触发器将在USART_TX开始发送数据之后的一段时间内,控制接口电路一直保持在发送状态,并在这段时间内保持接口电路最佳的驱动能力。
图4
这样做的缺点在于:单稳态触发器不仅会被起始位的低电平触发,还有可能被随后的数据位中的0重复触发,从而造成本节点接口电路超时占用RS485_A/RS485_B总线。可将单稳态触发器的亚稳态持续时间设置为11个UART码元的时间,这样保证了发送数据0xFF这样全高电平的字节时,后续的数据域和停止位时段都保证接口电路占用总线,获得最佳驱动能力。另外也使得当数据域中有低电平码元的情况下,接口电路占用总线的时间最短。
至于上述电路的实现思路,可以选择低成本的单片但问题触发器74HC122,如图5所示通过阻容的数值来确定亚稳态时间的长度。
图5 74HC122构成的单稳态触发器
另一种实现上述思路的方法,是使用可编程逻辑器件(PLD)来实现单稳态触发器。对于板子上已经有GAL、CPLD或FPGA的系统而言,这几乎是不需要成本的,但对于没有这些PLD器件的系统而言,这将增加系统的成本和功耗。以下给出我的Verilog HDL代码。
1 module RS485_DIR_CTL( input usart_tx, 2 input clk, 3 output rs485_ctl 4 ); 5 parameter DLY_NUM = 8_000;//最长延迟的时钟数,由10个最长码元确定,现设置为1ms左右(8MHz时钟) 6 reg[14:0] cnt; 7 always@(posedge clk or negedge usart_tx) 8 begin 9 if(!usart_tx) 10 cnt[14:0] <= 15'd0; 11 else begin 12 if(cnt[14:0] < 15'd20_000) 13 cnt[14:0] <= cnt[14:0] + 15'd1; 14 else 15 cnt[14:0] <= cnt[14:0]; 16 end 17 end 18 assign rs485_ctl = (cnt[14:0] < DLY_NUM); 19 endmodule
其设计思路是usart_tx有低电平就将控制管脚切换到发送状态,直到TXD恢复高电平一段时间。为了保证输出切换及时,usart_tx被设计成了异步复位信号,通过调整DLY_NUM可以调整单稳态计数器的亚稳态持续时间,从而调整控制接口输出的时间长度。Quartus II综合后电路如下图所示。
图6
计数所需时钟则可由单片机或其他时钟电路提供,我这里使用了STM32的PA8脚的MCO时钟输出功能,配置代码如下:
1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//PA8 2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 3 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度 4 GPIO_Init(GPIOA, &GPIO_InitStructure); 5 RCC_MCOConfig(RCC_MCO_HSE); // MCO选择输出频率
3、带有自动收发切换功能的RS485接口芯片
美信公司(现已被ADI收购)有一款自动换向的RS485芯片MAX13487。我猜测其原理无外乎我上面提到了两种,但其价格较高,且采购渠道不是特别顺畅,与上面提到的两种方法相比不具有可比性,我这里就不展开叙述了。
图7 MAX13487/MAX13488
三、总结
低成本、非工业环境可选择图2所示的低成本方案一,但其将在高电平期间降低抗干扰能力和带载能力。不差钱,不考虑货期,且无需国产化需求的项目,可选图7所示的美信产品方案三。系统中已经有GAL、CPLD或FPGA的产品,选择PLD实现的方案二是0成本的最佳方案;系统中没有PLD,又想获得高可靠性、带载能力和低成本的可以选择图5所示74HC122小规模集成电路实现的方案二。
本文提出的方案二的缺点在于少量增加节点占用RS485总线的时间,但每帧数据最长增加总线占用时间仅为10个码元时长,而这对于常见RS485组网通信系统几乎是可以忽略不计的。