1.5.1. RTS/CTS和DTR/DSR之间的对比

先列出关于流控制协议的一些名词:

  • DTR – Data Terminal Ready
  • DSR – Data Set Ready
  • RTS – Request To Send
  • CTS – Clear To Send

于此相关的其他一些名词:

  • DCE:Data Communication Equipment,可以理解为:数据的发起方

    比如,计算机终端

  • DTE:Data Terminal Equipment,可以理解为:数据的接收方

    原先定义为,数据通信设备,比如调制解调器Modem

RTS/CTS和DTR/DSR,用的物理引脚是不同的;

而关于DTR/DSR和RTS/CTS共存(没有统一只使用单个的一组硬件引脚(要么用RTS/CTS,要么用DTR/DSR)去实现流控制)的原因是:

背景是:

最开始先出现的RTS/CTS,但是设计出RTS/CTS的初衷,即原先的目的,就不是把RTS/CTS去用来当做流控制的

-> 而是用来:去协调两个半双工(工作模式下的)的猫modem之间的通讯

-> 不至于让两个半双工的modem,在通讯时,互相掐架,互相抢占数据通道,互相同时要么都要发送数据,要么都要接受数据,由此而容易导致混乱和(总线上的)数据异常

-> 但是结果,(被设计用于协调两个两个半双工的modem之间的通讯的)RTS/CTS,结果被大家误用,误当做(后来大量出现和使用的,全双工的串口等设备中的)流控制

-> 即,对于都是全双工的两个串口来说:

计算机(上面的串口) <-> (开发板或其他设备上面的)串口

分别对应着的概念是:

DCE <-> DTE

此处,分别叫做:

数据发送方 <-> 数据接收方

此处,暂且叫做:

串口A <-> 串口B

此时就是:

A打算发送数据到B中

A设置RTS(Request To Send),表示:请求发送(数据到对方)

此时:

  • 正常情况下,数据接收方,B不忙的时候,即不是busy的状态,则:
    • B去设置对应的CTS(Clear To Send):
    • 两种理解,不确定是哪种:

      清除(发送者A之前的设置的RTS),表示可以接受数据了

      Clear表示OK,清楚,明白,意思是明白对方的意思了,表示对方可以发送数据了

    • -> 发送者A,就可以直接去发送数据给B了,B也就可以去接受数据,处理收到的数据了;
  • 偶尔特殊的时候,处于忙的状态,即busy,比如忙着处理上次发送的数据呢,所以没空理会你这次还要发的数据:
    • 那么此时就是:不去设置对应的CTS,表示自己忙,来不及处理你将要发送的数据
    • -> 数据发送者A,见状,就继续检测CTS,直到(数据接受者B,忙清了自己手上的活,有空接受数据了,然后)CTS被接受者B去设置对应的CTS,表示可以接受数据了,然后A才去发送数据给B

DTR/DSR,主要是用来做建立链接

即,数据发送和接受之前,先要建立A和B的连接,这时候才用到DTR/DSR

A设置RTS表示要发送数据给B,而B设置CTS表示可以接受数据,通知A发送数据给B,A就开始去真正的发送数据给B了

的背景是:

硬件连接是:

  • A的RTS<->B的RTS
  • A的CTS<->B的CTS

对应的:

  • A一般是计算机PC
  • B一般是接在PC上的一个modem猫

对应的,A要发送数据给B的执行过程是:

  1. A设置A的RTS:表示要发数据给B;
  2. A检测A的CTS:
    • 如果A的CTS是被设置了,那说明B设置了B的CTS
      • 表示B可以接受数据了
        • A就去发送数据给B了
    • 如果A的CTS没被设置,那说明B没有去设置B的CTS
      • 说明B还出于busy忙的状态
        • 等B忙清了,再去设置B的CTS
          • 此时A才能检测到A的CTS,是被设置了,才能发送数据给B

对于目前常见的,直接两个DB9的串口直接相连,物理上对应的引脚的接法:

  • A的RTS,CTS,分别接B的RTS,CTS
  • A的Tx,Rx,分别接B的Rx和Tx

目前对于DTR/DSR的理解:

数据发送和接受之前,先要建立A和B的连接。这时候才用到,用于建立链接的,DTR/DSR

RTS/CTS的流控制过程如下:

如果A和B,(其中A是Imager,要发送图像数据,B是对应的接受设备),A想要发送数据给B,那么用硬件的RTS/CTS作为硬件流控制机制的话,

A如果想要发送数据给B的话,A会使得RTS(Request To Send)引脚有效,表明其想要“请求发送”数据给作为接收设备的B,

然后A接着就会去检测对应的来自B的CTS引脚,直到CTS有效(此时意味着B已经做 好了相关的准备工作了,然后设置了CTS(Clear To Send) ,表明自己准备好接受数据了),才会真正开始发送数据。

并且在接下来发送每个字符(data character)之前,都会去检测对应的CTS是否有效

如果有效,才会继续传输对应的数据,

如果发现CTS无效(此时意味着B那么发生了啥情况,导 致无法继续正常接受数据了,所以将CTS设置为了无效),那么就不能再继续发送数据。

对于上述CTS一直有效的情况下,A就一直发送数据给B,到了最后数据发送完之后,再把RTS设置为无效,表示数据已经发送完了。

这就是整个单个的数据发送流程,用RTS和CTS来控制传输的逻辑。

对此流程,做个简单的比喻,未必很恰当,但是可以很形象的说明数据发送的流程:

A和B,相当于马路的两边,A要发送数据给B,就相当于A要过马路,具体的流程就是:

  1. A说,我要过马路

    就相当于A要将CTS设置有效,表示要发送数据(过马路到B那里去)

  2. B根据自己情况,决定亮红灯不允许过,还是亮绿灯允许过(CTS有效)

    B对于接下来将要接受的数据,要有一个准备的过程,这要花点时间,在这段时间内,肯定不会让你发送数据

    也就是亮红灯不允许你过马路,将CTS设置无效,表示我还没准备好

    然后A那边呢就一直检测CTS是否有效,发现是无效,就知道现在B那边还没准备好,不允许我发送数据

    然后过了会B准备好了, 就把CTS设置为有效,表示准备好了,A可以发送数据给B了,即亮绿灯,让A过马路了

    而A此时就检测到CTS是有效的了,就可以发送数据了,即看到绿灯,可以过马路了。

  3. A要发送给B的每一个字节数据之前,都会看看是否是绿灯,如果是,继续发送数据,如果不是,就停止发送

    接下来的,A要把一个个字节的数据(就相当于一个个要过马路的人),发送给B

    在发送之前都要像前面一样,去检测CTS是否有效

    如果有效,就亮绿灯,可以继续发送数据,即过马路

    如果CTS无效,说明B出啥问题了,比如缓存满了,要处理一下,接着再让你发送数据,就亮红灯,A不能继续过马路了。

    然后A就一直检测CTS直到CTS有效,再发送数据,即A一直看灯,直到红灯变绿,再继续过马路。

  4. 在CTS一直有效的情况下,A发送数据完成后,把RTS设置为无效

    所有的A都过完马路了,就把原先设置的标示RTS设置为无效,表示数据发送完成了。

可以将上面一大堆繁琐的解释,总结为简单的逻辑:

  1. A先设置RTS为1,表示要发数据给B
  2. B检测到了RTS为1,就看看自己是否已经准备好: <listitem>如果准备好,就设置CTS为1表示A可以发送数据给我B了;</listitem><listitem>如果没有准备好,那就继续处理需要处理的事情,比如缓存满了,尽快去搬移数据。弄完了,再去设置CTS为1,让A发送数据过来。</listitem>
  3. A发现CTS为1了,就开发发送数据给B。
  4. A每发送一次数据给B之前,都继续上面的逻辑,就是先检测CTS是否为1,如果不是1,继续等待,如果是1,就发送数据。
  5. A把所有数据都发送完毕了,就去设置为RTS为0,表示数据发送完了。B也就不会再去准备接受数据了。