嵌入式Linux 串口编程系列2--termios的VMIN和VTIME深入理解

2019-07-13 06:41发布

    在上一篇文章中,我们介绍了串口的一些基本知识、串口配置接口 termios结构体的概念,串口的配置参数有n多个,这里面不用都背下来,什么时候使用,翻看手册即可,但是有两个 参数是一定要理解的,就是VMIN和VTIME。上一篇文章中已经介绍了这两个概念,下面进一步解释:
     VMIN:指定串口至少接收VMIN个字符,才会触发读完成。这个要这么理解,本质上,串口是逐bit逐byte接收的,也就是逐个节接收,不管是采用中断还是DMA,那么VMIN的引入,就要求 只有串口接收到VMIN个字节,才会认为接收完成,read函数才会停止阻塞。     VTIME:指定了读取的字符间隔超时时间,可以理解为串口接收的过程中会触发一个 定时器,这个定时器的溢出时间就是VTIME,但是要特别注意,每接收一个字节,就会重置这个定时器,直到最后一个字节接收完成,这个时候由于不会再重置定时器,所以再等VTIME时间后,定时器溢出,相当于接收完成,read函数停止阻塞。VTIME的单位是 十分之一秒,也就是100ms。     我们理解一个概念的最好方式是要想一想,这个概念的作用,为什么要这样设计?    上一篇我们介绍了串口的一些基本知识,实际的工程实践中,我们对串口的应用编程,最常见的情况就是 要处理串口接收不定长数据。这是通信的本质,因为通信的过程中,数据长度是经常要变的,我们使用串口不可能一直把tx和rx短接在一起。     那么如何解决 接收不定长数据呢? 在非linux的串口开发中,我们采用的方式一般是两种,一种是 结合定时器方式,一种是串口DMA空闲中断。     结合定时器的方式是这样的:串口接收到第一个字节后,触发定时器计时,每接收一个新的字节,重置定时器,这样能保证定时器不会溢出,等到接受完最后一个字节后,定时器就会 按照设计的计时时间来溢出,这个溢出时间就是VTIME,最终的效果就是,串口 接收数据完成,再等VTIME时间,定时器溢出中断,我们在中断服务 程序里就可以触发应用程序对接收数据的处理。     串口DMA空闲中断:这种方式需要结合DMA外围,一旦串口接收到第一个字节后,DMA就接手串口的功能,进行接收,等到接收完成后,此时串口处于空闲,就会触发空闲中断,我们就可以在串口中断服务函数中触发应用程序对接收数据进行处理,ps:串口空闲中断不是 串口一空闲就中断,而是串口 必须要先从“忙”再到“闲”才会触发 中断。     了解了上面的描述,我们回过头来看Unix/Linux环境下怎么去解决这个问题,答案是 操作系统已经提前想到了这些问题,帮我们提供了这个 功能,也就是设计的VTIEM和VMIN机制。我们如何通过这两个参数实现串口不定长数据接收呢?这里先说答案,就是把VMIN的值设置的足够大(不超范围),把VTIME设置的足够小(不能为0),具体如何编程呢,我们下一篇文章再来详细说明。《嵌入式Linux 串口编程系列3——通过VTIM、VMIN、select实现串口不定长数据接收功能