一、linux系统IO应用实例。 -> 触摸屏。
1、触摸屏设备叫什么名字?
在linux下,一切都是文件,连触摸屏也是一个文件。
触摸屏设备名字:/dev/input/event0
2、熟悉了解触摸屏两个专业术语。
1)事件。 -> event0
当一些外接控制设备(鼠标、键盘,wifi,触摸屏,按键)接入到嵌入式平台(GEC6818)时,这些外接设备的状态发生了改变(鼠标的左键被按下了,键盘的R键被按下,有人连接上wifi了,触摸屏被滑动了一下,按键被按下了)时,这个动作就称之为事件。
2)输入子系统。 -> input
当事件发生的时候,就是由输入子系统来计算这些事件中产生的值。
3、如果我们想把触摸屏的坐标读取出来,思路是如何的呢?
1)访问触摸屏设备文件。
fd = open("/dev/input/event0");
2)直接读取即可。
read(fd);
3)分析读取出来的数据是什么类型的?
int ? char ? char []? *?
4)根据获取到的坐标做进一步的判断就可以。
if(坐标满足某一个条件)
{
}
5)关闭文件
close(fd);
例题: 尝试将数据读取到一个数组中。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
//1. 访问触摸屏设备
int fd;
fd = open("/dev/input/event0",O_RDONLY);
if(fd < 0)
{
printf("open ts error!\n");
}
//2. 读取触摸屏设备的数据
char buf[100] = {0};
while(1)
{
read(fd,buf,sizeof(buf));
printf("from file:%s\n",buf);
}
//3. 关闭文件。
close(fd);
return 0;
}
结果:
打印乱码。
二、究竟触摸屏数据对应的类型是什么?
如果想知道从event0这个文件中读取出来的这个文件的数据是什么类型的,那么就必须先知道输入子系统计算完这个结果之后,是以什么形式放到这个event0这个文件中。
1、如何来描述一个事件? -> 需要很多值 -> 结构体。
该结构体已经定义好了,是被封装在一个头文件,头文件的路径在: /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; /* 微秒 */
};
例子2: 现在我们知道读取出来的,就是一个结构体。
我们现在就把结构体里面的成员打印出来看看,究竟等于多少?
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc,char *argv[])
{
//1. 访问触摸屏设备
int fd;
fd = open("/dev/input/event0",O_RDONLY);
if(fd < 0)
{
printf("open ts error!\n");
}
//2. 读取触摸屏设备的数据
struct input_event buf;
while(1)
{
read(fd,&buf,sizeof(buf));
printf("buf.type = %d\n",buf.type);
printf("buf.code = %d\n",buf.code);
printf("buf.value = %d\n",buf.value);
}
//3. 关闭文件。
close(fd);
return 0;
}
结果:
[root@GEC6818 /]#./ts
buf.type = 3 -> 触摸屏位移
buf.code = 0 -> 触摸屏的x轴
buf.value = 274-> 点击的坐标的x轴坐标
buf.type = 3 -> 触摸屏位移
buf.code = 1 -> 触摸屏的y轴
buf.value = 384-> 点击的坐标的y轴坐标
buf.type = 1 -> 按键
buf.code = 330 -> 触摸屏压力
buf.value = 1 -> 按下
buf.type = 0
buf.code = 0
buf.value = 0
buf.type = 1 -> 按键
buf.code = 330 -> 触摸屏压力
buf.value = 0 -> 松开
buf.type = 0
buf.code = 0
buf.value = 0
结果的值也是被封装在一个头文件中:#include "input-event-codes.h"
1)事件的类型有哪些?
/*
* Event types
*/
#define EV_SYN 0x00 -> 异步通信。
#define EV_KEY 0x01 -> 按键事件 (一般指的就是这类设备:键盘/压力/按键)
#define EV_REL 0x02 -> 相对位移 (一般指的就是鼠标)
#define EV_ABS 0x03 -> 绝对位移 (一般指的就是触摸屏)
2)事件的编码由哪些?
EV_KEY -> 对应的code有哪些?
#define BTN_TOUCH 0x14a(等价于十进制的330)
EV_ABS -> 对应的code有哪些?
#define ABS_X 0x00 -> 代表触摸屏的x轴
#define ABS_Y 0x01 -> 代表触摸屏的y轴
例子3: 点击屏幕松开手,就打印一句话。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc,char *argv[])
{
//1. 访问触摸屏设备
int fd;
fd = open("/dev/input/event0",O_RDONLY);
if(fd < 0)
{
printf("open ts error!\n");
}
//2. 读取触摸屏设备的数据
struct input_event buf;
while(1)
{
read(fd,&buf,sizeof(buf)); //发生了很多个事件
//但是只有松手的事件才是我想要的。
if(buf.type == 1 && buf.code == 330 && buf.value == 0)
{
printf("your hand leave lcd!\n");
}
}
//3. 关闭文件。
close(fd);
return 0;
}
练习1: 写一个程序,实现当你的手在屏幕上滑动时,就不断打印当前坐标出来,顺便看看原点在哪里?
x y
(100,200)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc,char *argv[])
{
//1. 访问触摸屏设备
int fd;
fd = open("/dev/input/event0",O_RDONLY);
if(fd < 0)
{
printf("open ts error!\n");
}
//2. 读取触摸屏设备的数据
struct input_event buf;
int x,y;
while(1)
{
read(fd,&buf,sizeof(buf)); //发生了很多个事件
if(buf.type == 3 && buf.code == 0)
{
x = buf.value;
}
if(buf.type == 3 && buf.code == 1)
{
y = buf.value;
}
printf("(%d,%d)\n",x,y);
}
close(fd);
return 0;
}
练习2: 写一个程序,实现点击屏幕的左边松开,就打印一次"left"。
点击屏幕的右边松开,就打印一次"right"。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/input.h>
#include <strings.h>
int main(int argc,char *argv[])
{
int fd,x;
struct input_event buf;
/* 1. 访问触摸屏设备 */
fd = open("/dev/input/event0",O_RDONLY);
if(fd < 0)
printf("open event0 error!\n");
/*2. 不断读取触摸屏数据 */
while(1)
{
bzero(&buf,sizeof(buf)); //每次读取之前,都保证缓冲区是清空的状态。
read(fd,&buf,sizeof(buf));
//3. 获取手触摸到的坐标
if(buf.type == EV_ABS && buf.code == ABS_X)
x = buf.value;
//4. 判断你什么时候松手。
if(buf.type == EV_KEY && buf.code == BTN_TOUCH && buf.value == 0)
{
//5. 判断下你刚刚松手的位置在哪里
if(x < 500) //左边
{
printf("left!\n");
}
if(x > 500) //右边
{
printf("right!\n");
}
if(x == 500)
{
break;
}
}
}
//6. 关闭文件
close(fd);
return 0;
}
===================================
补充理解输入子系统的现实例子。
type:
吃饭 -> 0
睡觉 -> 1
code:
早餐 -> 0
午餐 -> 1
晚餐 -> 2
午觉 -> 0
晚觉 -> 1
value;
饱 -> 0
饿 -> 1
睡得着 -> 2
睡不着 -> 3
struct input_event{ -> 代表输入子系统分析出来: 你刚刚睡午觉没睡着
.type = 1
.code = 0
.value = 3
}