C语言-文件IO-触摸板

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值