1,触摸屏
和显示屏一样,应用层开发板不需要关心硬件底层实现,linux体系和驱动提供了对应的接口
触摸屏是输入设备,对应的设备文件 /dev/input/event0,当手指点击/滑动屏幕时,会触发输入事件,而底层会把输入事件的信息保存到这个文件中,实时保存(不是累计保存),我们只需要从该文件中读取这些信息并分析处理即可。
触摸屏可以触发两种类型的输入事件:绝对坐标事件(触摸屏事件) 和 按键事件
对该文件的基础操作步骤是: open read close
fd = open("/dev/input/event0",O_RDONLY); read(fd,?,?) close(fd); 用什么类型的变量来保存read读到的数据呢? 关键是看文件中的数据是什么类型-》 struct input_event 使用这个结构体需要包含头文件 <linux/input.h> struct input_event { struct timeval time;//事件发生的时间 __u16 type; //输入事件类型 #define EV_KEY 0x01 //按键事件 #define EV_ABS 0x03 //绝对坐标事件(触摸屏事件) __u16 code; //含义不固定的,根据 type的不同而不同 当 type为 EV_KEY 时,code表示对应按键的键值 #define BTN_TOUCH 0x14a //这就是触摸屏对应的键值 当 type为 EV_ABS时,code表示坐标轴 #define REL_X 0x00 #define REL_Y 0x01 __s32 value; //value的含义是不固定的,根据 code的不同而不同 当 code表示键值的时候,value表示该按键是按下(1)或者松开(0) 当 code表示x轴的时候,value表示x轴的坐标 当 code表示y轴的时候,value表示y轴的坐标 };
event0文件默认是以阻塞的方式打开的
一次点击的数据 type:3,code:0,value:632 type:3,code:1,value:248 type:1,code:330,value:1 type:1,code:330,value:0
练习:
1,测试出触摸屏坐标系信息
原点在哪 左上角
x轴范围 [0,1020左右]
y轴范围 [0,600]
注意:像素点坐标和触摸屏坐标 不是等价的,要进行等比例换算
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <linux/input.h>
int main()
{
int fd = open("/dev/input/event0",O_RDONLY | O_NONBLOCK);
if(-1 == fd)
{
perror("");
return -1;
}
struct input_event ev;
while(1)//点击/滑动屏幕时,并不是只有一个输入事件发生,更加不是只有一个 结构体数据,所以我们需要循环读取
{
int r = read(fd,&ev,sizeof(ev));
if(-1==r)
{
perror("");
close(fd);
return 0;
}
printf("type:%d,code:%d,value:%d\n",ev.type,ev.code,ev.value);
if(ev.type==EV_KEY&&ev.code==BTN_TOUCH&&ev.value==0)//手指松开,跳出循环
break;
}
close(fd);
return 0;
}
2,封装一个函数
获取一个触摸点的坐标
3,封装一个函数
获取手指滑动的方向
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <linux/input.h>
#include <stdlib.h>
#include "touch.h"
enum DIREC dir;
struct point get_point()
{
struct point p;
int fd = open("/dev/input/event0",O_RDONLY);
if(-1 == fd)
{
perror("");
p.x = p.y = -1;
return p;
}
struct input_event ev;
while(1)//点击/滑动屏幕时,并不是只有一个输入事件发生,更加不是只有一个 结构体数据,所以我们需要循环读取
{
read(fd,&ev,sizeof(ev));
printf("type:%d,code:%d,value:%d\n",ev.type,ev.code,ev.value);
if(ev.type==EV_ABS&&ev.code==REL_X)
p.x = ev.value;
if(ev.type==EV_ABS&&ev.code==REL_Y)
p.y = ev.value;
if(ev.type==EV_KEY&&ev.code==BTN_TOUCH&&ev.value==0)//手指松开,跳出循环
break;
}
close(fd);
return p;
}
enum DIREC get_direction()
{
int fd = open("/dev/input/event0",O_RDONLY);
if(-1 == fd)
{
perror("");
return ERROR;
}
struct input_event ev;
struct point start,end;
start.x = -1;
start.y = -1;
//获取起点和终端坐标
while(1)
{
read(fd,&ev,sizeof(ev));
printf("type:%d,code:%d,value:%d\n",ev.type,ev.code,ev.value);
if(ev.type==EV_ABS&&ev.code==REL_X)
{
end.x = ev.value;//一直覆盖,最后一个坐标就是终点坐标
if(start.x == -1)//只把第一个点的坐标赋值给 start.x,赋值之后就不会等于-1,后面就不会赋值了
start.x = ev.value;
}
if(ev.type==EV_ABS&&ev.code==REL_Y)
{
end.y = ev.value;
if(start.y == -1)
start.y = ev.value;
}
if(ev.type==EV_KEY&&ev.code==BTN_TOUCH&&ev.value==0)//手指松开,跳出循环
break;
}
//根据起点和终点坐标计算滑动方向
int _x = end.x-start.x;
int _y = end.y-start.y;
if(abs(_x) > abs(_y))
{
//水平方向大于垂直方向: 左或者右
if(_x > 10)//10个单位是为了防误触
{
//右
close(fd);
return RIGHT;
}
else if(_x < -10)
{
//左
close(fd);
return LEFT;
}
}
else
{
//水平方向小于垂直方向: 上或者下
if(_y > 10)
{
//下
close(fd);
return DOWN;
}
else if(_y < -10)
{
//上
close(fd);
return UP;
}
}
close(fd);
return OTHER;
}
void* thread_get_direction(void *arg)
{
int fd = open("/dev/input/event0",O_RDONLY);
if(-1 == fd)
{
perror("");
dir = ERROR;
return NULL;
}
struct input_event ev;
struct point start,end;
while(1)
{
start.x = -1;
start.y = -1;
//获取起点和终端坐标
while(1)
{
read(fd,&ev,sizeof(ev));
printf("type:%d,code:%d,value:%d\n",ev.type,ev.code,ev.value);
if(ev.type==EV_ABS&&ev.code==REL_X)
{
end.x = ev.value;//一直覆盖,最后一个坐标就是终点坐标
if(start.x == -1)//只把第一个点的坐标赋值给 start.x,赋值之后就不会等于-1,后面就不会赋值了
start.x = ev.value;
}
if(ev.type==EV_ABS&&ev.code==REL_Y)
{
end.y = ev.value;
if(start.y == -1)
start.y = ev.value;
}
if(ev.type==EV_KEY&&ev.code==BTN_TOUCH&&ev.value==0)//手指松开,跳出循环
break;
}
//根据起点和终点坐标计算滑动方向
int _x = end.x-start.x;
int _y = end.y-start.y;
if(abs(_x) > abs(_y))
{
//水平方向大于垂直方向: 左或者右
if(_x > 10)//10个单位是为了防误触
{
dir = RIGHT;
}
else if(_x < -10)
{
dir = LEFT;
}
else
dir = OTHER;
}
else
{
//水平方向小于垂直方向: 上或者下
if(_y > 10)
{
//下
dir = DOWN;
}
else if(_y < -10)
{
//上
dir = UP;
}
else
dir = OTHER;
}
}
close(fd);
}
#ifndef __TOUCH_H__
#define __TOUCH_H__
extern enum DIREC dir;
//坐标结构体
struct point
{
int x;
int y;
};
enum DIREC
{
ERROR,
UP,
DOWN,
LEFT,
RIGHT,
OTHER
};
//获取触摸坐标,失败返回坐标为(-1,-1)的结构体
struct point get_point();
enum DIREC get_direction();
void* thread_get_direction(void *arg);
#endif