通信原理课设(gec6818) 004:触摸屏

1、触摸屏

        就像之前说的,在linux中,一切皆文件。触摸屏:在linux也是一个文件:/dev/input/event0。触摸屏是一个二维的,我们的手在触摸屏上面滑动点击就是坐标的变动,而我们的内存又是一个一维的, 因此必须有多个参数才能表示这个坐标,因此输入事件是维护在一个结构体里面的
 

struct input_event 
{
	struct timeval time;
	__u16 type;     	
	__u16 code;     	
	__s32 value;    	
};

参数解释:

time:你的事件发生的时间,这个时间是一个绝对时间。绝对时间就是:1970.1.1 0:0:0到现在所有的秒数,一般为了去实现回溯,我们的点击和长按就可以通过这个时间去搞定。

type:你的事件的类型,这个值说明你现在获取到的是一个什么样子的输入事件(#define EV_ABS 0x03)

code:编码,这个编码在触摸屏事件里面是用于去区分XY轴的
            #define REL_X 0x00
            #define REL_Y 0x01

value:值   这里表示坐标值。

if(code == REL_X)
{
	     x = value;
}
else if(code == REL_Y)
{
	    y = value;
}

2、练习

在触摸屏上利用手势的变换,如上滑、下滑、左滑、右滑。实现切换图片的效果。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/input.h>

int lcd_fd = -1;  // Global LCD file descriptor
unsigned int *plcd = NULL;  // Global mapping base address

void LcdInit(void) {
    lcd_fd = open("/dev/fb0", O_RDWR);
    if (-1 == lcd_fd) {
        perror("open fb0 error");
        exit(1);
    }
    plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (MAP_FAILED == plcd) {
        perror("mmap lcd error");
        exit(2);
    }
}

//绘制一个点
void Display(int x, int y, unsigned int color) {
    if (x >= 0 && x < 800 && y >= 0 && y < 480) {
        *(plcd + y * 800 + x) = color;
    }
}
//打开bmp
void DisplayBmpPic(const char* pic)
{
    //1、打开文件
    int fd = open(pic , O_RDONLY);
    if( fd == -1)
    {
        perror("open bmp error");
        return;
    }

    //2、判断这个文件是不是真的bmp图片
    //暂时省略

    //读取bmp文件头相关信息:
    int width,height,depth=0;
    //读取宽度、高度
    lseek(fd,0x12,SEEK_SET);
    read(fd,&width,4);
    read(fd,&height,4); //高度和宽度连在一起
    //读取色深
    lseek(fd,0x1c,SEEK_SET);
    read(fd,&depth,2);
    printf("width= %d  height= %d  depth= %d\n",width,height,depth);

    //为了凑4的倍数,需要在每一行的后面加1/2/3/0个字节
    int n =(4 - width * (depth / 8) % 4) % 4;
    //计算像素数组 w*h*(depth/8) 由于数组较大,故采用动态内存分配
    unsigned char *coclorbuf = malloc((width*(depth/8)+n)*height);
    //读取像素数组,偏移过头部
    lseek(fd,0x36,SEEK_SET);
    read(fd,coclorbuf,(width*(depth/8)+n)*height);

    //拿到每一个像素点的rgb
    unsigned char c_a,c_r,c_g,c_b;
    unsigned int color;
    int i=0;//coclorbuf的下标
    int x=400-(width/2),y=240+(height/2);//坐标
    for(y=240+(height/2)-1 ; y>=240-(height/2) ; y--)//列
    {
        for(x=400-(width/2) ; x<width+400-(width/2) ; x++)//行
        {
            c_b = coclorbuf[i++];
            c_g = coclorbuf[i++];
            c_r = coclorbuf[i++];
            if( 32 == depth)  // 32/8=4 说明存储的是argb
            {
                c_a = coclorbuf[i++];
            }
            color = c_a<<24 | c_r<<16 | c_g<<8 | c_b;
            Display(x,y,color);
        }
        i += n;//每走完一行都要跳过后面补的没用的n个字节
    }
    //释放动态分配内存 free只能释放动态内存空间
    free(coclorbuf);
    //3、关闭文件
    close(fd);
}

//切换
void Switching()
{
    int fd = open("/dev/input/event0",O_RDWR);
    if(-1 == fd)
    {
        perror("open event0 error");
    }
    //操作这个触摸屏 一般触摸屏的操作是不会死掉的  因此我们需要实现死循环
    struct input_event ev;
    int flag = 0;//超时的flag
    int ev_x0,ev_y0,ev_x,ev_y;

    while(1)
    {
        //我们想获取坐标值  那么就是从这个文件里面读取内容
        int r = read(fd,&ev,sizeof(ev));
        if(sizeof(ev) != r)//读出问题出来了
        {
            usleep(10);
            flag++;
            if(10 <= flag)
            {
                //超时太多了  不行了
                perror("read ev error");
                break;
            }
            continue;
        }
        flag = 0;
        //将数据打印出来看看
        //printf("type:%d code:%d value:%d\n",ev.type,ev.code,ev.value);
        //获取坐标
        if(EV_ABS == ev.type)//接下来的数据就是坐标
        {
            if(REL_X == ev.code)//x轴
            {
                ev_x = ev.value;
            }
            else if(REL_Y == ev.code)//y轴
            {
                ev_y = ev.value;
            }
        }
        if(0x01 == ev.type && BTN_TOUCH == ev.code && 0x01 == ev.value)//手按下去的时候
        {
            ev_x0 = ev_x;
            ev_y0 = ev_y;
        }
        else if(0x01 == ev.type && BTN_TOUCH == ev.code && 0x00 == ev.value)//手抬起来
        {
            //实现点击和方向判断
            if(ev_x0 == ev_x && ev_y0 == ev_y)//你的手没有动
            {
                printf("点击\n");
            }
            else//滑动 滑动就会有方向
            {
                if(ev_x > ev_x0 && abs(ev_x - ev_x0) > abs(ev_y - ev_y0))
                {
                    //sprintf(picture,"%d.bmp",i);

                    //sprintf(picture,"%d.bmp",i);
                    lseek(fd,0x00,SEEK_SET);
                    DisplayBmpPic("1.bmp");
                    printf("右滑\n");
                }
                else if(ev_x < ev_x0 && abs(ev_x - ev_x0) > abs(ev_y - ev_y0))
                {
                    lseek(fd,0x00,SEEK_SET);
                    DisplayBmpPic("2.bmp");
                    printf("左滑\n");
                }
                else if(ev_y > ev_y0 && abs(ev_y -ev_y0) > abs(ev_x - ev_x0))
                {
                    lseek(fd,0x00,SEEK_SET);
                    DisplayBmpPic("3.bmp");
                    printf("上滑\n");
                }
                else if(ev_y < ev_y0 && abs(ev_y -ev_y0) > abs(ev_x - ev_x0))
                {
                    lseek(fd,0x00,SEEK_SET);
                    DisplayBmpPic("4.bmp");
                    printf("下滑\n");
                }
            }
        }
    }
    //3 关闭这个文件
    close(fd);
}

int main()
{   
    //1 打开这个触摸屏
    LcdInit();  
    //调用图片切换函数  在图片切换函数中嵌套音乐切换
    Switching();
    return 0;
}

代码解释:

ev_x0,ev_y0代表手挪动前的坐标,ev_x,ev_y;代表手挪动后的坐标。
点击:手挪动前后的坐标相同(ev_x0 == ev_x && ev_y0 == ev_y)

左滑:手挪动后的x坐标小于手挪动前的x坐标,且x轴方向的坐标绝对值变化大于y轴方向的坐标值变化(ev_x < ev_x0 && abs(ev_x - ev_x0) > abs(ev_y - ev_y0)

右滑:手挪动后的x坐标大于手挪动前的x坐标,且x轴方向的坐标绝对值变化大于y轴方向的坐标值变化(ev_x > ev_x0 && abs(ev_x - ev_x0) > abs(ev_y - ev_y0)

上滑:手挪动后的y坐标大于手挪动前的y坐标,且x轴方向的坐标绝对值变化小于y轴方向的坐标值变化(ev_y > ev_y0 && abs(ev_y -ev_y0) > abs(ev_x - ev_x0)

下滑:手挪动后的y坐标小于手挪动前的y坐标,且x轴方向的坐标绝对值变化小于y轴方向的坐标值变化(ev_y < ev_y0 && abs(ev_y -ev_y0) > abs(ev_x - ev_x0)

posted @ 2023-12-23 16:32  Flying3080  Views(103)  Comments(0Edit  收藏  举报  来源