zoukankan      html  css  js  c++  java
  • 串口VMIN VTIME 详解

    原文地址:

    以前跟着做过VxWorks的开发,主要通信方式是串口,因为底层BSP包已经做好了,串口通信非常简单。后来接触Linux,在一块OK6410上跑Linux串口通信,才发现原来天真的以为甚是简单的串口变得如此的不简单。

    #include <termios.h>

    1、串口的操作

    1.1打开:fd = open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NDELAY);
                  O_RDWR 读写方式打开;
                  O_NOCTTY 不允许进程管理串口(不太理解,一般都选上);
                  O_NDELAY 非阻塞(默认为阻塞,打开后也可以使用fcntl()重新设置)

    1.2写入:n = write(fd, "linux", 5);
                    n实际写入字节数;

    1.3读取:res = read(fd,buf,len);
                     res 读取的字节数;

    1.4设置:fcntl(fd, F_SETFL, FNDELAY); //非阻塞
                     fcntl(fd, F_SETFL, 0); // 阻塞

    1.5关闭:close(fd);

    2、串口配置

    struct termios options;  // 串口配置结构体
    tcgetattr(fd,&options); //获取当前设置
    bzero(&options,sizeof(options));
    options.c_cflag  |= B115200 | CLOCAL | CREAD; // 设置波特率,本地连接,接收使能
    options.c_cflag &= ~CSIZE; //屏蔽数据位
    options.c_cflag  |= CS8; // 数据位为 8 ,CS7 for 7 
    options.c_cflag &= ~CSTOPB; // 一位停止位, 两位停止为 |= CSTOPB
    options.c_cflag &= ~PARENB; // 无校验
     //options.c_cflag |= PARENB; //有校验
    //options.c_cflag &= ~PARODD // 偶校验
    //options.c_cflag |=  PARODD    // 奇校验
    options.c_cc[VTIME] = 0; // 等待时间,单位百毫秒 (读)。后有详细说明
    options.c_cc[VMIN] = 0; // 最小字节数 (读)。后有详细说明
    tcflush(fd, TCIOFLUSH); // TCIFLUSH刷清输入队列。
                                           TCOFLUSH刷清输出队列。 
                                           TCIOFLUSH刷清输入、输出队列。
    tcsetattr(fd, TCSANOW, &options); // TCSANOW立即生效;
                                                            TCSADRAIN:Wait until everything has been transmitted;
                                                            TCSAFLUSH:Flush input and output buffers and make the change

    3、VTIME 和  VMIN

    VTIME  定义要求等待的零到几百毫秒的值(通常是一个8位的unsigned char变量)。
    VMIN 定义了要求等待的最小字节数, 这个字节数可能是0。
    只有设置为阻塞时这两个参数才有效,仅针对于读操作。
    说起来比较复杂,举个例子吧,设置为阻塞状态,写操作未进行实验,这里仅讨论读操作,
    read(fd,&buf,8); // 读串口

    3.1 
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;
    VMIN = 0,当缓冲区字节数 >= 0 时进行读操作,实际上这时读串口操作并未被阻塞,因为条件始终被满足。

    3.2
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 1;
    VMIN = 1,当缓冲区字节数 >= 1 时进行读操作,当没有数据时读串口操作被阻塞。

    3.3
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 4;
    VMIN = 4,当缓冲区字节数 >= 4 时进行读操作,否则读串口操作被阻塞。每次读出的最大字节数由read函数中第三个参数决定。直到缓冲区剩下的数据< read 第三个参数 并且< 4 (如果这时read第三参数为 1 则进行4次读操作直至读完缓冲区,如read第三参数为2,连续进行读操作,直至缓冲区空或还剩一个字符)。没有设置VTIME,剩下的字符没有确定的期限,直到下次满足读条件的时候才被读出。

    ----------------------------------考虑VTIME-----------------------------

    3.4
    options.c_cc[VTIME] = 10; //单位百毫秒
    options.c_cc[VMIN] = 4;
    同3.3的区别就是,没满足条件或读缓冲区中剩下的数据会在1秒(10百毫秒)后读出。另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN ,将会将VMIN 修改为read的第三个参数,即使用read(fd,&buf,2);,以上设置变为:
    options.c_cc[VTIME] = 10;
    options.c_cc[VMIN] = 2;

     

        ptty->ntm.c_cc[VTIME] = 0; // inter-character timer unused

        ptty->ntm.c_cc[VMIN] = 1; // blocking read until 1 chars received

     

    控制符VTIMEVMIN之间有着复杂的关系。VTIME定义要求等待的零到几百毫秒的时间量(通常是一个8位的unsigned char变量,取值不能大于cc_t)VMIN定义了要求等待的最小字节数(不是要求读的字节数——read()的第三个参数才是指定要求读的最大字节数),这个字节数可能是0

    l         如果VTIME0VMIN定义了要求等待读取的最小字节数。函数read()只有在读取了VMIN个字节的数据或者收到一个信号的时候才返回。 

    l         如果VMIN0VTIME定义了即使没有数据可以读取,read()函数返回前也要等待几百毫秒的时间量。这时,read()函数不需要像其通常情况那样要遇到一个文件结束标志才返回0

    l         如果VTIMEVMIN都不取0VTIME定义的是当接收到第一个字节的数据后开始计算等待的时间量。如果当调用read函数时可以得到数据,计时器马上开始计时。如果当调用read函数时还没有任何数据可读,则等接收到第一个字节的数据后,计时器开始计时。函数read可能会在读取到VMIN个字节的数据后返回,也可能在计时完毕后返回,这主要取决于哪个条件首先实现。不过函数至少会读取到一个字节的数据,因为计时器是在读取到第一个数据时开始计时的。 

    l         如果VTIMEVMIN都取0,即使读取不到任何数据,函数read也会立即返回。同时,返回值0表示read函数不需要等待文件结束标志就返回了。

    陀螺仪实例结果:

    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 1;

    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 1;

    卡死,等待

    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 0;       等待VTIME后,read返回0

    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;       相当于非阻塞,read立即返回0。

    options.c_oflag &= ~(ONLCR | OCRNL);

    options.c_iflag &= ~(ICRNL | INLCR);
    options.c_iflag &= ~(IXON | IXOFF | IXANY);

                                                                                          c++           c++                python后c++        c++

    cout<<"options.c_cflag1:"<<options.c_cflag<<endl;    3261  -->   7346                        7346    -->    7346
    cout<<"options.c_oflag1:"<<options.c_oflag<<endl;    5        -->   0                              4          -->    0
    cout<<"options.c_iflag1:"<<options.c_iflag<<endl;      1280   -->   0                              0         -->     0
    cout<<"options.c_lflag1:"<<options.c_lflag<<endl;      35387 -->  35360                       0         -->     0

  • 相关阅读:
    DMA详解
    Python实现爬虫设置代理IP和伪装成浏览器的方法(转载)
    Python3 简单验证码识别思路及实例
    Python3 比较两个图片是否类似或相同
    python3 验证码图片切割
    python3 验证码去噪
    Python3 OpenCV应用
    python3 IEDriver抓取时报数据
    Impala 数值函数大全(转载)
    java 获取指定日前的前一天
  • 原文地址:https://www.cnblogs.com/cj2014/p/4518062.html
Copyright © 2011-2022 走看看