基于GEC6818的触摸屏

1. 输入子系统

连接操作系统的输入设备,可不止一种,也许是一个标准PS/2键盘,也许是一个USB鼠标,或者是一块触摸屏,甚至是一个游戏机摇杆,Linux在处理这些纷繁各异的输入设备的时候,采用的办法还是找中间层来屏蔽各种细节,请看下图:

在Linux的内核中,对输入设备的使用,实际上运用了3大块来管理,他们分别是所谓的输入设备驱动层、输入子系统核心层,以及事件触发层。他们各自的工作分别是:

  1. 输入设备驱动层:
    每一种设备都有其特定的驱动程序,他们被妥当地装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。

  2. 核心层:
    此处将收集由设备驱动层发来的数据,整合之后触发某一事件。

  3. 事件触发层:
    这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件来获知某设备的某一个动作。

以触摸屏为例,当手指在屏幕上滑动的时候,数据流大致是这样的:驱动层中的触摸屏驱动会源源不断地产生触摸屏相关数据,并向上递送给内核输入子系统,输入子系统进一步将这些信息规整为统一的结构体,并借助事件触发层发往对应的设备节点,至此,应用程序即可从这些设备节点读取相关信息。

值得注意的是,底层驱动产生的设备数据与上层应用读取设备数据是两个完全异步的过程,彼此之间是没有耦合和约束的,例如:当底层驱动产生的触摸屏坐标信息比应用层读取的速度要快时,应用程序将会丢失一部分坐标信息。

2. 输入信息结构体

在最靠近应用程序的事件触发层上,内核所获知的各类输入事件,比如键盘被按了一下,触摸屏被滑了一下等,都将被统一封装在一个叫做 input_even 的输入信息结构体当中,这个结构体定义如下:

vincent@ubuntu:/usr/include/linux/$ cat input.h -n
     1    #ifndef _INPUT_H
     2    #define _INPUT_H
     3    
     ...
     ...
    20    
    21    struct input_event {
    22        struct timeval time;
    23        __u16 type;
    24        __u16 code;
    25        __s32 value;
    26    };
    27    
    ...

1. time
输入事件发生的时间戳,精确到微秒。时间结构体定义如下:

struct timeval
{
__time_t tv_sec; // 秒
long int tv_usec; // 微秒(1微秒 = 10-3毫秒 = 10-6秒)
};

2. type
输入事件的类型。比如:

事件类型(type)说明
EV_SYN事件间的分割标志,有些事件可能会在时间和空间上产生延续,比如持续按住一个按键
为了更好地管理这些持续的事件,EV_SYN用以将他们分割成一个个的小的数据包。
EV_KEY用以描述键盘,按键或者类似键盘的设备的状态变化。
EV_REL相对位移,比如鼠标的移动,滚轮的转动等。
EV_ABS绝对位移,比如触摸屏上的坐标值。
EV_MSC不能匹配现有的类型,这相当于当前暂不识别的事件
比如在Linux系统中按下键盘中针对Windows系统的“一键杀毒”按键,将会产生该事件。
EV_LED用于控制设备上的LED灯的开关,比如按下键盘的大写锁定键
会同时产生 ”EV_KEY” 和 ”EV_LED” 两个事件。
… …… …

3. code 

这个 事件代码 用于对事件的类型作进一步的描述。比如:当发生EV_KEY事件时,则可能是键盘被按下了,那么究竟是哪个按键被按下了呢?此时查看code就知道了。当发生EV_REL事件时,也许是鼠标动了,也许是滚轮动了。这时可以用code的值来加以区分。

事件类型(type)事件代码(code)说明
EV_KEYBTN_TOUCH触摸屏发生了按压、松开事件
EV_KEYKEY_LEFT键盘的左箭头发生了按压、松开事件
EV_KEYKEY_RIGHT键盘的右箭头发生了按压、松开事件
EV_ABSABS_X触摸屏发生了x轴坐标事件
EV_ABSABS_Y触摸屏发生了y轴坐标事件
EV_RELABS_Y触摸屏发生了y轴坐标事件
EV_ABSABS_Y触摸屏发生了y轴坐标事件
… …… …… …

 4. value

当code都不足以区分事件的性质的时候,可以用value来确认。比如由EV_REL和REL_WHEEL确认发生了鼠标滚轮的动作,但是究竟是向上滚还是向下滚呢?再比如由由EV_KEY和KEY_F确认了发生键盘上F键的动作,但究竟是按下呢还是弹起呢?这时都可以用value值来进一步判断。

事件类型(type)事件代码(code)发生值(value)说明
EV_KEYBTN_TOUCH大于0手指按压了触摸屏
EV_KEYBTN_TOUCH0手指松开了触摸屏
EV_KEYKEY_LEFT大于0左箭头被按下
EV_KEYKEY_LEFT0左箭头被松开
EV_ABSABS_X213触摸屏产生了一个233的 x 轴坐标
EV_ABSABS_Y448触摸屏产生了一个448的 y 轴坐标
… …… …… …… …

 3. 触作摸屏操作

对于触摸屏而言,该设备会产生三种数据:

  • X轴坐标值
  • Y轴坐标值
  • P压力值

理论上来说,从手指放上屏幕开始,到滑动一段距离,离开屏幕结束,会产生如下所示的一系列数据:

(X Y P1) SYN (X Y) SYN (X Y) SYN (X Y) ... ... (X Y) SYN (X Y P2)

有如下地方需要注意:

  • 在刚开始的第一个坐标值和最后一个坐标值中,都连带会读到压力值P
  • P1是手指刚落下时,产生压力值大于0的数据
  • P2是手指离开时,产生压力值等于0的数据
  • 应用层并不能保证能严格交替读取 (X,Y) 坐标值,它们会由于异步等原因出现断续,比如 (X X X X Y)
  • 若手指滑动的方向刚好垂直与坐标轴,会导致其中一个维度的坐标值不变,那么也可能会导致只出现一个维度坐标值的情形,例如:
... (X) SYN (X) SYN (X Y) SYN (Y) ... ... (X Y) SYN ...

这种情况下需要借助系统自动产生的 SYN 事件来整理出成对的坐标值。

4、触摸屏相关函数代码

//触摸屏划屏函数

#include <stdio.h>  //usr/include/stdio.h
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*输入子系统头文件*/
#include <linux/input.h>   //usr/include/linux/input.h

int main(int argc,char **argv)
{
	/*打开触摸屏*/
	int fd;
	fd = open("/dev/input/event0",O_RDWR);
	if(fd < 0)
	{
		perror("open ts fail");
		return -1;
	}
	
	/*操作触摸屏*/
	//定义一个存储触摸屏信息的结构体
	struct input_event ts;
	
	int x1=0,y1=0; //按下去的坐标值
	int x2=0,y2=0; //松手后的坐标值

	while(1)//循环读取数据
	{		
		/*抓取按下去的坐标值*/
		while(1)
		{	
			//在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
			read(fd,&ts,sizeof(struct input_event));
			if(ts.type == EV_ABS && ts.code==ABS_X) //x轴的坐标值
			{
				//printf("x=%d ",ts.value); //蓝色触摸屏的坐标值
				x1 = ts.value;
				//printf("x=%d ",(int)(ts.value*0.78)); //蓝色触摸屏的坐标值 1024 方法一
				//printf("x=%d ",ts.value*800/1024); //方法二
			}
			if(ts.type == EV_ABS && ts.code==ABS_Y) //y轴的坐标值
			{
				//printf("y=%d\n",ts.value);//蓝色触摸屏的坐标值
				y1 = ts.value;
				//printf("x=%d ",(int)(ts.value*0.8));//黑色触摸屏的坐标值 600 方法一
				//printf("y=%d\n",ts.value*480/600); //方法二
			}
			
			//当按下去的那一刻,跳出循环;只抓取按下去的坐标值
			if(ts.type == EV_KEY && ts.code==BTN_TOUCH && ts.value == 1)//
			{
				printf("按下去:x1=%d y1=%d\n",x1,y1);
				break;
			}
		}	

		/*抓取松手后的坐标值*/
		while(1)
		{	
			//在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
			read(fd,&ts,sizeof(struct input_event));
			if(ts.type == EV_ABS && ts.code==ABS_X) //x轴的坐标值
			{
				//printf("x=%d ",ts.value); //蓝色触摸屏的坐标值
				x2 = ts.value;
				//printf("x=%d ",(int)(ts.value*0.78)); //蓝色触摸屏的坐标值 1024 方法一
				//printf("x=%d ",ts.value*800/1024); //方法二
			}
			if(ts.type == EV_ABS && ts.code==ABS_Y) //y轴的坐标值
			{
				//printf("y=%d\n",ts.value);//蓝色触摸屏的坐标值
				y2 = ts.value;
				//printf("x=%d ",(int)(ts.value*0.8));//黑色触摸屏的坐标值 600 方法一
				//printf("y=%d\n",ts.value*480/600); //方法二
			}
			
			//当按下去的那一刻,跳出循环,只抓取松手后的坐标值
			if(ts.type == EV_KEY && ts.code==BTN_TOUCH && ts.value == 0)//
			{
				printf("松手:x2=%d y2=%d\n",x2,y2);
				break;
			} 
		}	
		
		if(x2-x1 > 50) //50差值决定你滑动的灵敏度
			printf("right\n");
		if(x2-x1 < -50) 
			printf("left\n");	
		if(y2-y1 > 50) 
			printf("down\n");
		if(y2-y1 < -50)
			printf("up\n");		
	}	
	/*关闭触摸屏*/
	close(fd);
	
	return 0;
}

//触摸屏单击函数
#include <stdio.h>  //usr/include/stdio.h
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*输入子系统头文件*/
#include <linux/input.h>   //usr/include/linux/input.h

int main(int argc,char **argv)
{
	/*打开触摸屏*/
	int fd;
	fd = open("/dev/input/event0",O_RDWR);
	if(fd < 0)
	{
		perror("open ts fail");
		return -1;
	}
	
	/*操作触摸屏*/
	//定义一个存储触摸屏信息的结构体
	struct input_event ts;
	
	//读取触摸屏的设备文件
	while(1)
	{	
		//在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
		read(fd,&ts,sizeof(struct input_event));
		if(ts.type == EV_ABS && ts.code==ABS_X) //x轴的坐标值
		{
			//printf("x=%d ",ts.value); //蓝色触摸屏的坐标值
			//printf("x=%d ",(int)(ts.value*0.78)); //蓝色触摸屏的坐标值 1024 方法一
			printf("x=%d ",ts.value*800/1024); //方法二
		}
		if(ts.type == EV_ABS && ts.code==ABS_Y) //y轴的坐标值
		{
			//printf("y=%d\n",ts.value);//蓝色触摸屏的坐标值
			//printf("x=%d ",(int)(ts.value*0.8));//黑色触摸屏的坐标值 600 方法一
			printf("y=%d\n",ts.value*480/600); //方法二
		}
	}	
	
	/*关闭触摸屏*/
	close(fd);
	
	return 0;
}

  • 6
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 基于GEC6818的五子棋是一种在GEC6818开发板上实现的五子棋游戏。GEC6818是一款功能强大的开发板,搭载了ARM架构的处理器和Linux操作系统,可以方便地开发各种应用程序。 在这个基于GEC6818的五子棋游戏中,我们可以通过连接显示器和输入设备(如键盘或鼠标)来进行游戏。通过GUI界面,我们可以看到一个棋盘和棋子,通过点击鼠标或使用键盘来下棋。 这个五子棋游戏程序是在GEC6818上通过编程实现的。首先,我们需要设计一个算法来判断下棋位置的合法性,并在合法的位置上落子。接着,我们需要实现一个判断胜负的算法,以便在游戏进行中及时判断出胜利者。 在这个基于GEC6818的五子棋游戏中,我们还可以实现一些高级功能,如悔棋、重新开始、人机对战、网络对战等。通过GEC6818的强大计算能力和网络功能,我们可以实现人机对战或网络对战功能,与其他玩家进行五子棋对局。 总而言之,基于GEC6818的五子棋是一款利用GEC6818开发板的处理能力和软件开发环境实现的五子棋游戏。通过这个游戏,我们可以利用GEC6818的强大功能进行智能手动对弈,提高智力和娱乐性,推动技术的发展和应用的普及。 ### 回答2: 基于GEC6818的五子棋是一种利用GEC6818开发板的硬件资源和软件平台来实现的五子棋游戏。GEC6818是一款ARM架构的开发板,拥有强大的计算能力和扩展性,非常适合用于实现五子棋游戏。 在硬件方面,我们可以利用GEC6818的高性能处理器和丰富的接口来实现五子棋游戏的核心功能。开发板上的触摸屏可以作为游戏的输入设备,玩家可以通过触摸屏来落子。同时,GEC6818的HDMI接口可以连接到显示器,用于展示游戏界面和棋盘。 在软件方面,我们可以使用C/C++语言和相关的开发工具来编写五子棋的算法和游戏逻辑。利用GEC6818强大的计算能力,可以实现高效的搜索算法和智能的人机对战。同时,开发板上的Linux操作系统和相关的开发框架可以为我们提供丰富的软件资源和开发工具,使得五子棋游戏的开发更加便捷和高效。 在游戏界面方面,我们可以利用GEC6818的图形处理能力和相关的图形库来设计美观的游戏界面。可以绘制出棋盘、棋子和其他游戏元素,给玩家带来良好的视觉体验。 总之,基于GEC6818的五子棋是一种利用GEC6818开发板的硬件资源和软件平台来实现的五子棋游戏。通过充分利用GEC6818的强大计算能力、丰富的接口和开发工具,我们可以实现高性能、智能化和美观的五子棋游戏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值