zoukankan      html  css  js  c++  java
  • 多输入之轮询


    title: 多输入之轮询
    date: 2019/3/19 19:27:18
    toc: true

    多输入之轮询

    代码仓库

    方式一

    https://gitee.com/layty/project_for_linux/tree/master/03-ebook/02_input_by_query

    方式二

    https://gitee.com/layty/project_for_linux/tree/master/03-ebook/03_input_by_query_select

    引入

    这里我们采用两种方式的输入,使用查询的方式来读取具体的输入,轮询的前提就是所有输入设备都是非阻塞的

    • 触摸屏
    • 标准输入

    关于这里的io模型,select参考《嵌入式Linux应用程序开发标准教程》里面的第六章

    触摸屏

    对于触摸屏的库tslib,支持非阻塞打开,也就是传递参数1即可

    struct tsdev *ts_open(const char *name, int nonblock)
    {
    	if (nonblock)
    		flags |= O_NONBLOCK;
    }
    

    O_NONBLOCK (non-blocking) 它在读取不到数据时会回传-1,并且设置errno为 EAGAIN

    具体的使用代码可以参考tslib-1.4.tar.gz/tests/ts_print.c

    标准输入

    标准输入这里可以有两种方式:

    方式一 设置终端输入为非阻塞

    struct termios tTTYState;
    //get the terminal state
    tcgetattr(STDIN_FILENO, &tTTYState);
    //turn off canonical mode
    tTTYState.c_lflag &= ~ICANON;
    //minimum of number input read.
    tTTYState.c_cc[VMIN] = 0; 
    // 立即返回
    tTTYState.c_cc[TIME] = 0;   
    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);
    

    然后从流中读取

    int num_read,ch;
    char  buf_read[10];
    num_read = fread(buf_read, 1, 1, stdin);
    if(num_read)
    {
    	ch=buf_read[0];
        ....
    }
    
    

    方式二 :使用阻塞一个字符,然后使用select的超时为0来达到非阻塞的效果

    static int StdinDevInit(void)
    {
        struct termios tTTYState;
        //get the terminal state
        tcgetattr(STDIN_FILENO, &tTTYState);
        //turn off canonical mode
        tTTYState.c_lflag &= ~ICANON;
        //minimum of number input read.
        tTTYState.c_cc[VMIN] = 1;   			/* 这里其实是阻塞的有一个数据时就立刻返回 */
        //set the terminal attributes.
        tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);
    	return 0;
    }
    

    然后读取输入的时候用select来监视读取的流,select的超时为0也就是没有数据就马上退出

    int StdGet(T_InputEvent* out_input_event)
    {
    	struct timeval time_out;
    	//这里的串口读取是阻塞的,select可以设置出一个超时时间,如果设置超时为0,则也就是非阻塞的了
    	fd_set uart_fd_set;
    	time_out.tv_sec = 0;
        time_out.tv_usec = 0;
        
    	FD_ZERO(&uart_fd_set);
    	FD_SET(STDIN_FILENO, &uart_fd_set); //注意这里使用的文件句柄,而不是File*	
    	/*		fd+1,readfds,writefds,exceptfds,timeout		*/
    	select(STDIN_FILENO+1, &uart_fd_set, NULL, NULL, &time_out);//这里就是监控 STDIN_FILENO 下的读的操作
    
    	// 有数据返回
    	if(FD_ISSET(STDIN_FILENO,&uart_fd_set))
    	{
    		char ch;
    		ch=fgetc(stdin);
    		if(ch)
                ....
        }
    }
    

    BUGS

    在老师的视频处理触摸屏的时候,代码如下,这里判断的iRet=0的时候也去返回数据,这里应该是有问题的,但是老师在使用select机制来使终端的时候触摸屏不会有问题,而使用我的直接设置终端不阻塞就有问题,希望高手帮忙分析一下

    iRet = ts_read(g_tTSDev, &tSamp, 1);
    
    if (iRet < 0) {					//这里应该是 if (iRet <= 0)  0也是没有有效数据的
        return -1;
    }
    

    还有就是判断超时,没有判断大小,所以应该先判断大小先,这里应该没什么关系

    static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
    {
    	int iPreMs;
    	int iNowMs;
    	
    	iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
    	iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;
    
    	return (iNowMs > iPreMs + 500);
    }
    
    static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
    {
    	int iPreMs;
    	int iNowMs;
    	int ret;
    	
    	iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
    	iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;
    
    	ret=iPreMs-iNowMs;
    	if(ret>500 || ret <-500)
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    

    实验

    1. tslib库,这里如果有问题看之前的触摸屏驱动文章

      1. 修改 /etc/ts.conf第1行(去掉#号和第一个空格),# module_raw input改为module_raw input

      2. 设置环境变量

        export TSLIB_TSDEVICE=/dev/event0
        export TSLIB_CALIBFILE=/etc/pointercal
        export TSLIB_CONFFILE=/etc/ts.conf
        export TSLIB_PLUGINDIR=/lib/ts
        export TSLIB_CONSOLEDEVICE=none
        export TSLIB_FBDEVICE=/dev/fb0
        

      3.校准 ts_calibrate

    2. 开启telnettelnetd -l /bin/sh

    3. 运行程序./show_file -f simsun1.ttc -s 12 main.c

    4. pc上可以使用telnet再登录开发板查看cpu

  • 相关阅读:
    Codeforces Round #324 (Div. 2) D. Dima and Lisa 哥德巴赫猜想
    Codeforces Round #324 (Div. 2) C. Marina and Vasya 贪心
    Codeforces Round #324 (Div. 2) B. Kolya and Tanya 快速幂
    Codeforces Round #324 (Div. 2) A. Olesya and Rodion 水题
    使用spring-loaded实现应用热部署
    maven中properties标签定义变量
    java中的匿名内部类总结
    泛型类型限定和通配符类型限定
    基于ActiveMQ的Topic的数据同步——消费者持久化
    基于ActiveMQ的Topic的数据同步——初步实现
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10561132.html
Copyright © 2011-2022 走看看