请教关于串口流控制的过程,以及在API编程中怎么使用有关问题

请问关于串口流控制的过程,以及在API编程中如何使用问题
1、最近做串口编程,但一直对CTS RTS等的使用不是很明白,查了很多资料讲得也不是很详细,请高手们来讲讲具体的工作过程。
2、在WINDOWS的API编程中如何有效控制使用握手信号CTS和RTS,网上commix等软件也有对其的设置,但不明白具体对应的代码应该如何写,请大虾们讲讲,谢谢!

------解决方案--------------------
up
------解决方案--------------------


如果你的项目中不使用【调制解调器】的话,暂时可以不管这个。
------解决方案--------------------
帮助UP
------解决方案--------------------
以前挺明白的,今天一下子觉得以前的理解都不对了,以下三种解释哪个对呢?

解释一:
RTS:终端我已经准备就绪,有数据就发过来吧
CTS:来了,接招

解释二:
RTS:终端我准备发数据给你,快用CTS应答,准备好没?
CTS:好了,来吧

解释三:
CTS:主机,我有数据,请求接收
RTS:我是主机,就绪,请求发送。

我今天弄了个SIM100模块,我将RTS设置无效之后,凡是要发往主机的数据都没有发过来(包括主动数据RING),指令和指令返回结果都没有返回,都缓存在模块之中,等我将RTS设置有效后,缓存的数据全发来了,包括一大堆指令的执行结果,由此,我觉得上面的“解释一”应该正确,而“解释二”应该是错的,但“解释三”是否正确呢?就是说CTS和RTS哪个是发起者呢?

答:
一是错的
二是RS232标准
三是MODEM的硬件流控
SIMCOM公司的解释完全正确

很久很久以前,计算机还没有出现,那时就已经存在了(计算机)史前的串口设备(电传打字机,工控测量设备,通信调制解调器),为了连接这些串口,EIA制定了RS232标准,采用DB25接插件,支持同步和异步串口,D型的接口可以有效防止插反。标准化给使用带来了便利。
时光荏苒,个人计算机出现了,这些已有的串口设备毫无疑问地成为了最初的外设,自然而然地RS232标准被个人计算机采纳。但是设备制造商倾向于体积更小,成本更低的接口,因此,将DB25中未使用的和支持同步模式的引脚去掉,形成DB9。最初的情况相当混乱,因为DB9只定义了信号,却没有指定信号和引脚的对应关系,各个制造商只能自行定义。幸运的是,IBM的PC成了工业标准,DB9逐渐统一到IBM的定义上来。
DB9只有9根线,遵循RS232标准。定义如下:
DTR,DSR------DTE设备准备好/DCE设备准备好。主流控信号。
RTS,CTS------请求发送/清除发送。用于半双工时,收发切换。属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送,一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。
全双工时,这两个信号一直有效即可。

随着计算机的日益普及,很多非RS232的串口也要接入PC机,如果为每一种新出现的串口都增加一个新的I/O口显然不现实,因为PC后面板位置有限,因此,将RS232串口和非RS232串口都通过RS232口接入是最佳方案。UART的U(通用)指的就是这个意思。早期ROM BIOS和DOS里的通信软件都是为RS232设计的,在没有检测到DCD有效前不会发送数据,因此,就连发送一个字符这样朴素的应用也要给出DCD、DTR、DSR等控制信号。因此,串口接头上要将一些控制线短接,或者干脆绕过系统软件自己写通信程序。
到此,UART的涵义就总结为:通用的异步 (串行) I/O口。
就在UART冠以通用二字,准备一统江湖的时候,制造商们不满于它的速度、体积和灵活性(软件可配置),推出了USB和1394串口。目前,笔记本上的UART串口有被取消的趋势,因而有网友发出了“没有串口,吾谁与归”的慨叹,古今多少事,都付笑谈中,USB取代UART是后话,暂且不表。
话说自从贺氏(Hayes)公司推出了聪明猫(SmartModem),他们制定的MODEM接口就成了业界标准,自此以后,所有公司制造的兼容猫都符合贺氏标准(连AT指令也兼容,大家一起抄他呗)。
细观贺氏制定的MODEM串口,与RS232标准大不相同。DTR在整个通信过程中一直保持有效,DSR在MODEM上电后/可以拨号前有效(取决于软件对DSR的理解),在通信过程的任意时刻,只要DTR/DSR无效,通信过程立即终止。在某种意义上,这也可以算是流控,但肯定不是RS232所指的那种主流控。如果拘泥于RS232,你是不会理解DTR和DSR的用途的。
贺氏不但改了DTR和DSR,竟然连RTS和CTS的涵义也重新定义了。因此,RTS和CTS已经不具有最开始的意义了。从字面理解RTS和CTS,是用于半双工通信的,当DTE想从收模式改为发模式时,就有效RTS请求发送,DCE收到RTS请求后不能立即完成转换,需要一段时间,然后有效CTS通知DTE:DCE已经转到发模式,DTE可以开始发送了。在全双工时,RTS和CTS都缺省置为有效即可。然而,在贺氏的MODEM串口定义中,RTS和CTS用于硬件流控,和什么劳什子的全双工/半双工一点关系也没有。
注意,硬件流控是靠软件实现的,之所以强调“硬件”二字,仅仅是因为硬件流控提供了用于流量情况指示的硬件连线,并不是说,你只要把线连上,硬件就能自己流控。如果软件不支持,光连上RTS和CTS是没有用的。
RTS和CTS硬件流控的软件算法如下:(RTS有效表示PC机可以收,CTS有效表示MODEM可以收,这两个信号互相独立,分别指示一个方向的流量情况。)

dengm 发表于 2005-1-14 07:52 侃单片机

PC端处理:
发. 当 发现(不一定及时发现) CTS (-3v to -15v)无效时,停止发送,
当发现(不一定及时发现) CTS (3v to 15v)有效时,恢复发送;

收. 0<M<N<LEN_OF_RX_BUFFERS
当接收buffers中的bytes<M 时,给 RTS 有效信号(+3v to +15v),
当接收buffers中的bytes>N 时,给 RTS 无效信号(-3v to -15v);

MODEM端处理:
同上,但RTS与CTS交换。

你迷惑的原因是因为你学习的是RS232标准,却使用贺氏标准的猫,两个标准风马牛不相及。

------解决方案--------------------
流控制的使用是比较复杂的,以下是我使用的一些总结:
  在流控制方式为“无”和“软件控制”的情况下,基本上没有什么问题,但在“硬件控制”下,win32 手册中说明 RTS_CONTROL_HANDSHAKE 控制方式的含义是:

Enables RTS handshaking. The driver raises the RTS line when the "type-ahead" (input) buffer is less than one-half full and lowers the RTS line when the buffer is more than three-quarters full. If handshaking is enabled, it is an error for the application to adjust the line by using the EscapeCommFunction function.

也就是说,当缓冲区快满的时候 RTS 会自动 OFF 通知对方暂停发送,当缓冲区重新空出来的时候, RTS 会自动 ON,但我发现当 RTS 变 OFF 以后即使你已经清空了缓冲区, RTS 也不会自动的 ON,造成对方停在那里不发送了,所以,如果要用硬件流控制的话,还要在接收后最好加上检测缓冲区大小的判断,具体是使用 ClearCommError 后返回的 COMSTAT.cbInQue,当缓冲区已经空出来的时候,要使用 invoke EscapeCommFunction,hCom,SETRTS 重新将 RTS 设置为 ON。
------解决方案--------------------
DTR和RTS是输出,在RS232标准里做为主硬件流控,CTS、DSR属于辅助流控信号。
  DTR在整个通信期间保持有效,DSR在MODEM上电后立即有效/在发出载波后有效(这取决于程序对DSR的理解,是把它简单地看成电源开关指示还是看成拨号后的指示)并在整个通信过程中一直保持有效。DTR或DSR在任何时间点无效,都将终止通信过程。但目前MODEM中没有按照RS232的规范将DTR和DSR用于硬件流控,它只使用这两个信号指示DTE和DCE已经上电,可以开始工作,MODEM是通过RTS和CTS实现的硬件流控。
  RTS(Request To Send请求发送),CTS(Clear To Send清除发送)------------半双工时,用于收发模式切换。属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送,一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。

一般这样使用:
C/C++ code

    //流控制设置
    switch ( m_nFlowCtrl ) 
    { // Judge flow control
    case IdFlowX:
        /*--------软件流控制方式---------------*/
        dcb.fOutX = TRUE;                            // XON/XOFF out flow control
        dcb.fInX = TRUE;                            // XON/XOFF in flow control
        dcb.XonLim = CommXonLim;                    // transmit XON threshold 
        dcb.XoffLim = CommXoffLim;                    // transmit XOFF threshold 
        dcb.XonChar = XON;                            // Tx and Rx XON character              
        dcb.XoffChar = XOFF;                        // Tx and Rx XOFF character
        /*-------------------------------------*/
        break;
    case IdFlowHard:
        /*--------硬件流控制方式---------------*/

        dcb.fDtrControl = CommXDtrControl;
        
        dcb.fOutxCtsFlow = m_nFlowCtrl==1;            // CTS output flow control 
        dcb.fRtsControl = CommXRtsControl;        // RTS output flow control 
                                                
        /*--------------------------------------*/ 
        break;
        
    }