当前位置: 首页 > news >正文

串口使用系列学习之什么是流控

概念

在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。
如台式机与单片机之间的通讯,接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。
流控制能解决这个问题,当接收端数据处理不过来时,就发出“不再接收”的信号,发送端就停止发送,直到收到“可以继续发送”的信号再发送数据。因此流控制可以控制数据传输的进程,实现收发双方的速度匹配,防止数据的丢失。
PC机中常用的两种流控制是硬件流控制(包括RTS/CTS、DTR/CTS等)和软件流控制XON/XOFF(继续/停止)。

硬件流控

硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。

  • RTS :全名为Require To Send,请求发送,为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。
  • CTS :全名为Clear To Send,允许发送,为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。

硬件流控的RTS 、CTS :
RTS (Require To Send,发送请求)为输出信号,用于指示本设备准备好可接收;
CTS (Clear To Send,允许发送)为输入信号,有效时停止发送。
假定有两通信设备:主机和从机,主机的RTS 连接从机的CTS ;主机的CTS连接从机的RTS。
前一路信号控制从机的发送,后一路信号控制主机的发送。
对从机的发送(主机接收)来说,如果主机接收缓冲快满的时发出RTS信号(高电平)(意思通知从机停止发送),从机通过CTS 检测到该信号,停止发送;一段时间后主机接收缓冲有了空余,发出RTS信号(低电平),指示从机开始发送数据。

在这里插入图片描述
物理连接:交叉连接
主机的RTS(输出)信号,连接到从机的CTS(输入)信号。
主机的CTS(输入)信号,连接到从机的RTS(输出)信号。

主机发送过程:
 主机查询主机的CTS脚信号,此信号连接到从机的RTS信号,受从机控制。如果主机CTS
信号为有效(低),表示从机的接收FIFO未满,从机可以接收,此时主机可以向从机发送
数据。并且在发送过程中要一直查询CTS信号是否为有效状态。一旦无效,则终止发送。

那主机的CTS信号什么时候会无效呢?

从机在接收到主机发送的数据时,从机的接收模块的FIFO如果满了,则会使从机RTS无效,
也即主机的CTS信号无效。主机则查询到CTS无效时,主机发送中止。

此过程可以由硬流控完成。我们只要设置开启硬流控,设置FIFO大小。RTS信号和CTS
信号由控制器代码查询和设置。

主机接收过程:
 主机如果接收FIFO未满,则使主机RTS信号有效,也即从机的CTS信号有效。此时从机
如果要发送,发送前会查询从机的CTS信号,如果为有效,则开始发送。并且在发送过程
中移植查询从机CTS信号的有效状态,如果无效则中止发送。是否无效由主机的RTS信号
决定。主机如果FIFO满了,则使主机RTS信号无效,也即从机CTS信号无效。主机接收
中止。

C++流控方法:

DCB结构体

 typedef  struct  _DCB   { // dcb 
        DWORD DCBlength;           // sizeof(DCB) 
        DWORD BaudRate;            // current baud rate 指定当前的波特率
        DWORD fBinary: 1;          // binary mode, no EOF check 指定是否允许二进制模式,WINDOWS 95中必须为TRUE
        DWORD fParity: 1;          // enable parity checking 指定奇偶校验是否允许
        DWORD fOutxCtsFlow:1;      // CTS output flow control 指定CTS是否用于检测发送控制.当为TRUE是CTS为OFF,发送将被挂起
        DWORD fOutxDsrFlow:1;      // DSR output flow control 指定DSR是否用于检测发送控制.当为TRUE是DSR为OFF,发送将被挂起
        DWORD fDtrControl:2;       // DTR flow control type DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手",
        DWORD fDsrSensitivity:1;   // DSR sensitivity 当该值为TRUE时DSR为OFF时接收的字节被忽略
        DWORD fTXContinueOnXoff:1; // XOFF continues Tx 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止.TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。
        DWORD fOutX: 1;            // XON/XOFF out flow control TRUE时,接收到XoffChar之后便停止发送.接收到XonChar之后将重新开始
        DWORD fInX: 1;             // XON/XOFF in flow control TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去.接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去
        DWORD fErrorChar: 1;       // enable error replacement 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符
        DWORD fNull: 1;            // enable null stripping TRUE时,接收时去掉空(0值)字节
        DWORD fRtsControl:2;       // RTS flow control RTS_CONTROL_DISABLE时,RTS置为OFF RTS_CONTROL_ENABLE时, RTS置为ON RTS_CONTROL_HANDSHAKE时,当接收缓冲区小于半满时RTS为ON 当接收缓冲区超过四分之三满时RTS为OFF RTS_CONTROL_TOGGLE时,当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF
        DWORD fAbortOnError:1;     // abort reads/writes on error TRUE时,有错误发生时中止读和写操作
        DWORD fDummy2:17;          // reserved 未使用
        WORD wReserved;            // not currently used 未使用,必须为0
        WORD XonLim;               // transmit XON threshold 指定在XON字符发送这前接收缓冲区中可允许的最小字节数
        WORD XoffLim;              // transmit XOFF threshold 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数
        BYTE ByteSize;             // number of bits/byte, 4-8 指定端口当前使用的数据位
        BYTE Parity;               // 0-4=no,odd,even,mark,space 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY
        BYTE StopBits;             // 0,1,2 = 1, 1.5, 2 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS
        char XonChar;              // Tx and Rx XON character 指定用于发送和接收字符XON的值
        char XoffChar;             // Tx and Rx XOFF character 指定用于发送和接收字符XOFF值
        char ErrorChar;            // error replacement character 本字符用来代替接收到的奇偶校验发生错误时的值
        char EofChar;              // end of input character 当没有使用二进制模式时,本字符可用来指示数据的结束
        char EvtChar;              // received event character 当接收到此字符时,会产生一个事件
        WORD wReserved1;           // reserved; do not use 未使用
    }  DCB; 

设置流控代码:

dcb.fDsrSensitivity = FALSE;          
dcb.fTXContinueOnXoff = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;

switch (g_lpInst->flowControl)
{
 case NoFlowControl:
 {
     dcb.fOutxCtsFlow = FALSE;
     dcb.fOutxDsrFlow = FALSE;
     dcb.fOutX = FALSE;
     dcb.fInX = FALSE;
     break;
 }
 case CtsRtsFlowControl:
 {
     dcb.fOutxCtsFlow = TRUE;
     dcb.fOutxDsrFlow = FALSE;
     dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
     dcb.fOutX = FALSE;
     dcb.fInX = FALSE;
     break;
 }
 case CtsDtrFlowControl:
 {
     dcb.fOutxCtsFlow = TRUE;
     dcb.fOutxDsrFlow = FALSE;
     dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
     dcb.fOutX = FALSE;
     dcb.fInX = FALSE;
     break;
 }
 case DsrRtsFlowControl:
 {
     dcb.fOutxCtsFlow = FALSE;
     dcb.fOutxDsrFlow = TRUE;
     dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
     dcb.fOutX = FALSE;
     dcb.fInX = FALSE;
     break;
 }
 case DsrDtrFlowControl:
 {
     dcb.fOutxCtsFlow = FALSE;
     dcb.fOutxDsrFlow = TRUE;
     dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
     dcb.fOutX = FALSE;
     dcb.fInX = FALSE;
     break;
 }
 case XonXoffFlowControl:
 {
     dcb.fOutxCtsFlow = FALSE;
     dcb.fOutxDsrFlow = FALSE;
     dcb.fOutX = TRUE;
     dcb.fInX = TRUE;
     dcb.XonChar = 0x11;
     dcb.XoffChar = 0x13;
     dcb.XoffLim = 100;
     dcb.XonLim = 100;
     break;
 }
}

相关文章:

  • 珠海网站建设哪家公司好/佛山网络推广培训
  • 网站设计的就业和发展前景/如何提高搜索引擎优化
  • 网站建设网站/竞价托管服务多少钱
  • 网站后台如何更新/搜索优化网络推广
  • 写好网页怎么建成网站/百度收录批量查询
  • wordpress 首页添加登陆/日本免费服务器ip地址
  • centos7安装docker
  • 前端基石:构造函数和普通函数
  • MySQL索引-3回表查询与覆盖索引
  • 【机器学习】阿里云天池竞赛——工业蒸汽量预测(5)
  • 可编程交换机P4网络资源
  • HTTP版本 四次挥手 同源策略
  • fastapi_No.7_获取表单和文件数据
  • YOLOX 学习笔记
  • 6.链表篇2链表的介绍和实现(单/双链表)
  • myj的补作业计划HrbustOJ新生赛(struct+优先队列)
  • Day770.Redis客户端如何与服务器端交换命令和数据 -Redis 核心技术与实战
  • 图像运算和图像增强二