赞
踩
一、触摸屏应用
1.触摸屏设备的名字
在Linux下,一切皆文件,触摸屏也是一个文件。
触摸屏设备的名字:/dev/input/event0
2.触摸屏的两个专业术语
事件 ->event0
当一些外接控制设备(鼠标、键盘,wifi,触摸屏,按键)接入到嵌入式平台(GEC6818)时,这些外接设备的状态发生了改变(鼠标的左键被按下了,键盘的R键被按下,有人连接上wifi了,触摸屏被滑动了一下,按键被按下了)时,这个动作就称之为事件.
输入子系统 ->input
当事件发生的时候,就是由输入子系统来计算这些事件中产生的值。并将这些值整合到一个名为input_event结构体中。(例如:触摸屏被触摸后,输入子系统就会计算出被触摸的坐标值)
3.代码实现流程
1.打开event0文件
2.读取event0文件的数据
3.判断事件类型,打印出数据
4.关闭文件
4.触摸屏数据对应的类型
如果想知道从event0这个文件中读取出来的这个文件的数据是什么类型的,那么就必须先知道输入子系统计算完这个结果之后,是以什么形式放到这个event0这个文件中。
以前我们学习结构体的时候知道描述一个需要很多值的事件,我们可以使用结构体来描述,所以输入子系统处理好触摸屏数据后,也是将这些数据存放到一个结构体中。
该结构体已经定义好了,是被封装在一个头文件,头文件的路径在: /usr/include/linux/input.h
- /* * The event structure itself //事件结构体 */
- struct input_event { -> 专门用于描述一个事件。
- struct timeval time; -> 事件发生的时间。
- __u16 type; -> 事件的类型 (输入子系统会用这个值来描述刚才发生事件的硬件设备)
- __u16 code; -> 事件的编码 -> 对事件进一步的描述 左键/右键 A键/R键 x轴/y轴
- __s32 value; -> 事件的值
- };
-
- struct timeval {
- long tv_sec; /* 秒 */
- long tv_usec; /* 微秒 */
- };
知道触摸屏数据是存放在一个结构体中后,那么我们可以写一段代码来打印出这些数据看看:
- #include <stdio.h>
-
- #include <sys/types.h>
-
- #include <sys/stat.h>
-
- #include <fcntl.h>
-
- #include <unistd.h>
-
- #include <string.h>
-
- #include <linux/input.h>
-
- int main()
-
- {
-
- • // 1.打开event0文件
-
- • int ts_fd;
-
- • ts_fd = open("/dev/input/event0", O_RDONLY);
-
- • if(ts_fd == -1)
-
- • {
-
- • printf("open ts failed!\n");
-
- • return 0;
-
- • }
-
- • // 2.读取event0文件的数据
-
- • struct input_event ts_buf;
-
- • read(ts_fd, &ts_buf, sizeof(ts_buf));
-
- •
-
- • // 3.判断事件类型,打印出数据
-
- • printf("type = %d", ts_buf.type);
-
- • printf("code = %d", ts_buf.code);
-
- • printf("value = %d", ts_buf.value);
-
- • // 4.关闭文件
-
- • close(ts_fd);
-
- • return 0;
-
- }

其实这个结构体结果的值也被封装在一个头文件中:/usr/include/linux/input-event-codes.h
input_event结构体的四个成员:
1.time(时间戳)
输入事件发生的时间戳,精确到微秒。时间结构体定义如下:
- struct timeval
- {
- __time_t tv_sec; // 秒
- long int tv_usec; // 微秒(1微秒 = 10-3毫秒 = 10-6秒)
- };
2.type(输入事件类型)
输入事件的类型。比如:
3.code(事件代码)
这个 事件代码用于对事件的类型作进一步的描述。比如:当发生EV_KEY事件时,则可能是键盘被按下了,那么究竟是哪个按键被按下了呢?此时查看code就知道了。当发生EV_REL事件时,也许是鼠标动了,也许是滚轮动了。这时可以用code的值来加以区分。
4.value(数据值)
当code都不足以区分事件的性质的时候,可以用value来确认。比如由EV_REL和REL_WHEEL确认发生了鼠标滚轮的动作,但是究竟是向上滚还是向下滚呢?再比如由由EV_KEY和KEY_F确认了发生键盘上F键的动作,但究竟是按下呢还是弹起呢?这时都可以用value值来进一步判断。
举一个实例帮助理解输入子系统:
- 我们先规定
- type:
- = 0 吃饭
- = 1 睡觉
-
- code:
- = 0 早餐
- = 1 午餐
- = 2 晚餐
-
- = 0 午觉
- = 1 晚觉
-
- value:
- = 0 吃饱了
- = 1 没吃饱
- = 0 睡得着
- = 1 睡不着
-
-
- struct input_event{ -> 代表输入子系统分析出来
- .type = 0
- .code = 1
- .value = 1
- }
-
- 我们再获取输入子系统整合的input_event结构体的值
-
- struct input_event{ -> 代表输入子系统分析出来: 你刚刚吃晚餐没吃饱
- .type = 0
- .code = 2
- .value = 1
- }
-
- struct input_event{ -> 代表输入子系统分析出来: 你刚刚睡午觉没睡着
- .type = 1
- .code = 0
- .value = 3
- }

练习:编写代码,实现打印出触摸点的坐标。
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <linux/input.h>
-
- int main()
- {
- int ts_fd;
- struct input_event ts_buf;
- ts_fd = open("/dev/input/event0",O_RDONLY);
- if(ts_fd == -1)
- {
- printf("open ts failed!\n");
- return -1;
- }
- int x,y;
- while(1)
- {
- read(ts_fd, &ts_buf, sizeof(ts_buf));
- if(ts_buf.type == EV_ABS && ts_buf.code == ABS_X)//判断是否发生X轴绝对位移事件
- {
- x = ts_buf.value;
- }
- if(ts_buf.type == EV_ABS && ts_buf.code == ABS_Y)//判断是否发生Y轴绝对位移事件
- {
- y = ts_buf.value;
- }
- if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
- {
- printf("(x, y) = (%d, %d)\n",x,y);
- }
- }
- close(ts_fd);
- return 0;
- }

作业1:观察打印出的坐标,得出触摸屏和LCD像素对应的关系
黑色边的开发板触摸屏坐标范围是:1024*600
蓝色边的开发板触摸屏坐标范围是:800*480
练习8:通过触摸屏实现显示图片切换。
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <linux/input.h>
- #include <sys/mman.h>
- int ts_fd, lcd_fd;
- int ts_x,ts_y;
- struct input_event ts_buf;
- int *p;
-
- char *pic_path[] = {"./1.bmp" , "./2.bmp", "./3.bmp", "./4.bmp", "./5.bmp"};
-
- /*
- *函数名:show_bmp
- *函数功能:显示bmp图片
- *参数:
- * path: 图片的路径
- * zs_x: 图片显示的原点x轴坐标
- * zs_y: 图片显示的原点y轴坐标
- * whide: 图片的宽度(单位像素)
- * high: 图片的高度(单位像素)
- */
- int show_bmp(char *path, int zs_x, int zs_y, int w, int h)
- {
- // 1、打开bmp文件
-
- int bmp_fd = open(path, O_RDONLY);
- if (bmp_fd == -1)
- {
- printf("open bmp error!\n");
- return -1;
- }
-
- //2、 跳过bmp文件头和信息头
- lseek(bmp_fd, 54, SEEK_SET);
-
- //3、读取bmp文件的数据
- char bmp_buf[w*h*3];
- read(bmp_fd, bmp_buf, 800*480*3); // 读取bmp文件数据到bmp_buf
-
-
- //4、数据处理
- int lcd_buf[w*h];
- int n;
- for (n = 0; n < 800*480; n++)
- {
-
- lcd_buf[n] = bmp_buf[3*n] | bmp_buf[3*n+1]<<8 | bmp_buf[3*n+2]<<16;
- }
-
-
-
- int *new_p = p + zs_x + zs_y*800;
-
- //6、// 5、将数据拷贝到映射空间
- int x, y;
- for(y=0;y<h;y++)
- {
- for(x=0;x<w;x++)
- {
- *(new_p+x+(h-1-y)*800) = lcd_buf[x+y*w];
- }
-
- }
-
- close(bmp_fd);
- }
-
- void get_xy()
- {
- // 2.读取event0文件的数据
- read(ts_fd, &ts_buf, sizeof(ts_buf));
-
- // 3.判断事件类型,打印出数据
- if(ts_buf.type == EV_ABS && ts_buf.code == ABS_X)//获取X轴坐标
- {
- ts_x = ts_buf.value;//0-1024 ---> 0-800
- ts_x = ts_x * 800 / 1024;
- }
- if(ts_buf.type == EV_ABS && ts_buf.code == ABS_Y)//获取Y轴坐标
- {
- ts_y = ts_buf.value;//0-600
- ts_y = ts_y * 480 / 600;
- }
- if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
- {
- printf("(x,y) = (%d,%d)",ts_x,ts_y);
- }
-
- }
-
- int main()
- {
- // 1.打开fb0、event0文件
- lcd_fd = open("/dev/fb0", O_RDWR);
- if(lcd_fd < 0)
- {
- perror("open fb0");
- return -1;
- }
-
- ts_fd = open("/dev/input/event0", O_RDONLY);
- if (ts_fd == -1)
- {
- perror("open touch failed\n");
- return -1;
- }
-
- // 内存映射
- p = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
- if(p == MAP_FAILED)
- {
- perror("mmap failed\n");
- return -1;
- }
-
- int i = 0;
- while (1)
- {
- get_xy();
- if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
- {
- if(ts_x>=0 && ts_x<200)//上一张
- {
- i--;
- if(i<0)
- {
- i = 4;
- }
- show_bmp(pic_path[i], 0, 0, 800, 480);
- }
- if(ts_x>=600 && ts_x<800)//下一张
- {
- i++;
- if(i>4)
- {
- i = 0;
- }
- show_bmp(pic_path[i], 0, 0, 800, 480);
-
- }
-
-
-
- }
- }
-
- // 4.关闭文件
- munmap(p, 800*480*4);
- close(lcd_fd);
- close(ts_fd);
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。