• 触摸屏(应用层)


    触摸屏工作原理(输入子系统)


     如上图所示,Linux在处理这些纷繁各异的输入设备的时候,采用的办法是找中间层来屏蔽各种细节。硬件设备通过输入子系统接入到系统中去,当硬件设备产生脉冲信号的时候,会将信号传递到驱动层,驱动层将此信号转换成数字信号,并这些数字信号转换成一个结构体,输入子系统则分辨出是哪个硬件设备产生的数据后,将数据发送到数据触发层,最后由该层将数据发送到指定驱动文件中去,用户就可以根据相关结构体的格式读取相关文件的数据了。

    如何操作触摸屏

     使用命令cat /input/event0(触摸屏设备文件)后,点击触摸屏看是否有数据产生(乱码),确保触摸屏没有问题。
      1.打卡触摸屏对应的设备文件;
      2.用相关结构体格式去读取文件的内容;
      3.根据触摸屏数据去做一些操作;
      4.关闭文件。

    输入子系统头文件分析

    /usr/include/linux/input.h
    struct input_event {
        struct timeval time; // 用于描述事件发生的时间
        __u16 type;       // 用来区分不同类型的硬件,比如键盘/鼠标/蓝牙/游戏遥感/触摸屏等等
        __u16 code;      // 用来区分不同硬件中的具体事件, 比如键盘的某个按键、鼠标中的某个按键、触摸屏的X/Y
        __s32 value;     // 用来表示具体的值,比如某个按键的状态(安下/松开) 触摸屏中具体的数值
    };
    
    </usr/include/linux/input-event-codes.h>//该文件包含了输入子系统中所要用到的宏
    /*
     * Event types
     */
    #define EV_SYN          0x00   // 事件分割标志
    #define EV_KEY          0x01   // 键盘事件
    #define EV_REL          0x02   // 相对位移事件
    #define EV_ABS          0x03   // 绝对位移事件 
    
    
     /*
     * Keys and buttons
     */
     #define BTN_TOUCH       0x14a    // 按键被触摸
    
    
    /*
     * Absolute axes
     */
    #define ABS_X           0x00   // X轴
    #define ABS_Y           0x01   // Y轴
    

    实验程序1

     在开发板中执行下面程序,点击触摸屏将产生数据。

    #define     TS_PATH     "/dev/input/event0"
    
    int main(int argc, char const *argv[])
    {
        //打开触摸屏
        int fd_ts = open( TS_PATH , O_RDWR);
        if (fd_ts < 0 )
        {
            perror("open event0 error");
            return -1 ;
        }
        
    
        //读取文件的内容
        struct input_event ts_event ;
    
        while(1)
        {
            read( fd_ts , &ts_event , sizeof(struct input_event));
    
    
            //分析数据
    
            //为所欲为
            printf("Time:%d.%d	Type:%d	Code:%d	Value:%d
    ",
                    ts_event.time.tv_sec,
                    ts_event.time.tv_usec,
                    ts_event.type,
                    ts_event.code,
                    ts_event.value);
        }
        //关闭文件  
        close(fd_ts);
    
        return 0;
    }
    
    输出:
    。。。
    Time:1420087593.789776  Type:3  Code:0    Value:546
    Time:1420087593.789781  Type:3  Code:1    Value:202
    Time:1420087593.789785  Type:1  Code:330  Value:1  //按下
    Time:1420087593.789789  Type:0  Code:0    Value:0 //事件分割标志
    Time:1420087593.873062  Type:1  Code:330  Value:0  //松开
    Time:1420087593.873067  Type:0  Code:0    Value:0
    。。。
    

    备注:
    此程序不支持滑屏

    实验程序2

     下面程序将在开发板的LCD显示出一个十字架,十字架的坐标便是触摸屏上被触摸的坐标。

    #define     CYAN        0x00FFFF
    #define     PPuff       0xFFDAB9
    #define     RED         0xFF0000
    #define     YELLOW      0XFFFF00
    #define     BLUE        0x0000FF
    #define     INRED       0xEE6363
    #define     SNOW        0xFFFAFA
    #define     PURPLE      0xA020F0
    
    #define  TS_PATH    "/dev/input/event0"
    #define     LCD_PATH    "/dev/fb0"
    #define     LCD_W       800
    #define     LCD_H       480
    #define     LCD_SIZE    LCD_W*LCD_H*4
    
    bool draw_point(int *address, int color, int x, int y)
    {
        if (MAP_FAILED  == address)
        {
            printf("draw_point msg:%s
    ", strerror(errno));  
            return false;
        }
    
        *(address + (x + (y*800))) = color; 
    
        return true;
    }
    
    bool draw_Hline(int *address, int color, int len, int x, int y)
    {
        if (MAP_FAILED == address)
        {
            printf("draw_line msg:%s
    ", strerror(errno));        
            return false;
        }
        int wide = LCD_W - 10;
        while (wide--)
        {
            draw_point(address, color, wide, y);
    
        }
        return true;
    }
    
    bool draw_Vline(int *address, int color, int len, int x, int y)
    {
        if (MAP_FAILED == address)
        {
            printf("draw_line msg:%s
    ", strerror(errno));        
            return false;
        }
        int high = LCD_H - 10;
        while (high--)
        {
            //address = address + LCD_W;
            draw_point(address, color, x, high);
        }
        return true;
    }
    
    bool touch_screen_pos(int fd, int *x, int *y)
    {
        int tmp_x = 0; 
        int tmp_y = 0;
        int cnt = 0;
    
        while (1)
        {
            
            int ret = read(fd, &ts_event, sizeof(struct input_event));
            if(0 == ret)
            {   
                return false;
            }
            if (ts_event.type == EV_ABS)
            {
                if (ABS_X == ts_event.code )
                {
                    tmp_x = (ts_event.value*800)/1024; //LCD与触摸屏的坐标转换
                    cnt++;
                }
                if (ABS_Y == ts_event.code)
                {
                    tmp_y = (ts_event.value*480)/600; //LCD与触摸屏的坐标转换
                    cnt++;
                }
            }
            //得到完整数据便返回成功
            if (2 == cnt)
            {
                *x = tmp_x;
                *y = tmp_y;
                return true;
            }
        }
    }
    
    int main(int argc, char const *argv[])
    {
        // 打开lcd设备文件  /dev/fb0  --》 由驱动工程师完成
        int fd  = open(LCD_PATH , O_RDWR);
        if (fd < 0 )
        {
           perror("open lcd error");
           return -1 ;
        }
       
        // 内存映射
        int * lcd_p = (int *)mmap(NULL ,   // 指向欲对应的内存起始地址, 通常设为 NULL, 代表让系统自动选定地址
                                LCD_SIZE,  // 显示器的大小
                                PROT_READ | PROT_WRITE,  // 配置内存区可读, 可写
                                MAP_SHARED,    // 设置内存区为共享*(对内存的任何操作都会被复制到文件中)
                                fd,        // 需要映射的文件
                                0);        // 偏移量
        if (MAP_FAILED ==  lcd_p)
        {
            perror("mmap error ");
            return -1 ;
        }
        
        int fd_ts = open(TS_PATH, O_RDWR);
        if (fd_ts < 0)
        {
            perror("open event0 error
    ");
            return -1;
        }
    
        int x = 0;
        int y = 0;
        int cnt = 0;
        while (1)
        {   
            touch_screen_pos(fd_ts, &x, &y);
            printf("(%d,%d)
    ",x,y);
    
             int i ;
             //得到触摸数据后刷新屏幕,将LCD上一次的内容刷掉
             for ( i = 0; i < 800*480; i++)
             {
                  *(lcd_p+i) = SNOW ;
     
             }
            
            //打印十字架
            draw_Vline(lcd_p, CYAN, 500, x, y);
            draw_Hline(lcd_p, CYAN, 400, x, y);
    
        }
    
        close(fd);
        close(fd_ts);
        munmap(lcd_p, LCD_SIZE);
        
        return 0;
    }
    
    
  • 相关阅读:
    codeforces 459C Pashmak and Buses(模拟,组合数A)
    HDU 4639 Hehe(字符串处理,斐波纳契数列,找规律)
    HDU 1671 Phone List(字符处理)
    网页爬虫【原创】【开源】
    asp.net mvc 配合前端js的CMD模块化部署思想,小思路
    [转]阎宏博士的JAVA与模式
    [转]使用设计模式改善程序结构(三)
    [转]使用设计模式改善程序结构(二)
    [转]使用设计模式改善程序结构(一)
    html符号转换
  • 原文地址:https://www.cnblogs.com/ding-ding-light/p/14166008.html
Copyright © 2020-2023  润新知