粤嵌6818开发板触摸屏应用

一、触摸屏应用

1.触摸屏设备的名字

在Linux下,一切皆文件,触摸屏也是一个文件。

触摸屏设备的名字:/dev/input/event0

2.触摸屏的两个专业术语

  • 事件 ->event0

当一些外接控制设备(鼠标、键盘,wifi,触摸屏,按键)接入到嵌入式平台(GEC6818)时,这些外接设备的状态发生了改变(鼠标的左键被按下了,键盘的R键被按下,有人连接上wifi了,触摸屏被滑动了一下,按键被按下了)时,这个动作就称之为事件.

  • 输入子系统 ->input

当事件发生的时候,就是由输入子系统来计算这些事件中产生的值。并将这些值整合到一个名为input_event结构体中。(例如:触摸屏被触摸后,输入子系统就会计算出被触摸的坐标值)

3.代码实现流程

1.打开event0文件

2.读取event0文件的数据

3.判断事件类型,打印出数据

4.关闭文件

4.触摸屏数据对应的类型

如果想知道从event0这个文件中读取出来的这个文件的数据是什么类型的,那么就必须先知道输入子系统计算完这个结果之后,是以什么形式放到这个event0这个文件中。

以前我们学习结构体的时候知道描述一个需要很多值的事件,我们可以使用结构体来描述,所以输入子系统处理好触摸屏数据后,也是将这些数据存放到一个结构体中。

该结构体已经定义好了,是被封装在一个头文件,头文件的路径在: /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;        /* 微秒 */
 };

知道触摸屏数据是存放在一个结构体中后,那么我们可以写一段代码来打印出这些数据看看:

#include <stdio.h>
​
#include <sys/types.h>
​
#include <sys/stat.h>
​
#include <fcntl.h>
​
#include <unistd.h>
​
#include <string.h>
​
#include <linux/input.h>
​
int main()
​
{
​
•    // 1.打开event0文件
​
•    int ts_fd;
​
•    ts_fd = open("/dev/input/event0", O_RDONLY);
​
•    if(ts_fd == -1)
​
•    {
​
•        printf("open ts failed!\n");
​
•        return 0;
​
•    }
​
•    // 2.读取event0文件的数据
​
•    struct  input_event ts_buf;
​
•    read(ts_fd, &ts_buf, sizeof(ts_buf));
​
•    
​
•    // 3.判断事件类型,打印出数据
​
•    printf("type = %d", ts_buf.type);
​
•    printf("code = %d", ts_buf.code);
​
•    printf("value = %d", ts_buf.value);
​
•    // 4.关闭文件
​
•    close(ts_fd);
​
•    return 0;
​
}

其实这个结构体结果的值也被封装在一个头文件中:/usr/include/linux/input-event-codes.h

input_event结构体的四个成员:

1.time(时间戳)

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

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

2.type(输入事件类型)

输入事件的类型。比如:

3.code(事件代码)

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

4.value(数据值)

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

举一个实例帮助理解输入子系统:

我们先规定
type:
= 0  吃饭
= 1  睡觉
​
code:
= 0  早餐
= 1  午餐
= 2  晚餐
​
= 0  午觉
= 1  晚觉
​
value:
= 0  吃饱了
= 1  没吃饱 
= 0  睡得着 
= 1  睡不着 
​
​
struct input_event{   -> 代表输入子系统分析出来
    .type = 0
    .code = 1
    .value = 1
    } 
​
我们再获取输入子系统整合的input_event结构体的值
​
struct input_event{   -> 代表输入子系统分析出来: 你刚刚吃晚餐没吃饱
    .type = 0
    .code = 2
    .value = 1
    } 
​
struct input_event{   -> 代表输入子系统分析出来: 你刚刚睡午觉没睡着
    .type = 1
    .code = 0
    .value = 3
    } 
 

练习:编写代码,实现打印出触摸点的坐标。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
​
int main()
{
    int ts_fd;
    struct input_event ts_buf;
    ts_fd = open("/dev/input/event0",O_RDONLY);
    if(ts_fd == -1)
    {
        printf("open ts failed!\n");
        return -1;
    }
    int x,y;
    while(1)
    {
        read(ts_fd, &ts_buf, sizeof(ts_buf));
        if(ts_buf.type == EV_ABS && ts_buf.code == ABS_X)//判断是否发生X轴绝对位移事件
        {
            x = ts_buf.value;
        }
        if(ts_buf.type == EV_ABS && ts_buf.code == ABS_Y)//判断是否发生Y轴绝对位移事件
        {
            y = ts_buf.value;
        }
        if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
        {
            printf("(x, y) = (%d, %d)\n",x,y);
        }  
    }
    close(ts_fd);
    return 0;
}

作业1:观察打印出的坐标,得出触摸屏和LCD像素对应的关系

黑色边的开发板触摸屏坐标范围是:1024*600

蓝色边的开发板触摸屏坐标范围是:800*480

练习8:通过触摸屏实现显示图片切换。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/input.h>
#include <sys/mman.h>
int ts_fd, lcd_fd;
int ts_x,ts_y;
struct input_event ts_buf;
int *p;
​
char *pic_path[] = {"./1.bmp" , "./2.bmp", "./3.bmp", "./4.bmp", "./5.bmp"};
​
/*
 *函数名:show_bmp
 *函数功能:显示bmp图片
 *参数:
 *  path: 图片的路径
 *  zs_x:  图片显示的原点x轴坐标
 *  zs_y:  图片显示的原点y轴坐标
 *  whide: 图片的宽度(单位像素)
 *  high: 图片的高度(单位像素)
*/
int show_bmp(char *path, int zs_x, int zs_y, int w, int h)
{
    // 1、打开bmp文件
​
    int bmp_fd = open(path, O_RDONLY);
    if (bmp_fd == -1) 
    {
        printf("open bmp error!\n");
        return -1;  
    }
​
    //2、 跳过bmp文件头和信息头
    lseek(bmp_fd, 54, SEEK_SET);  
​
    //3、读取bmp文件的数据
    char bmp_buf[w*h*3];
    read(bmp_fd, bmp_buf, 800*480*3);  // 读取bmp文件数据到bmp_buf
​
    
    //4、数据处理
    int lcd_buf[w*h];
    int n;
    for (n = 0; n < 800*480; n++)
    {
       
        lcd_buf[n] = bmp_buf[3*n] | bmp_buf[3*n+1]<<8 | bmp_buf[3*n+2]<<16;
    }
​
    
​
    int *new_p = p + zs_x + zs_y*800;
​
    //6、// 5、将数据拷贝到映射空间
    int x, y;
    for(y=0;y<h;y++)
    {
        for(x=0;x<w;x++)
        {
            *(new_p+x+(h-1-y)*800) = lcd_buf[x+y*w];
        }
​
    }
​
    close(bmp_fd);
}
​
void get_xy()
{
    // 2.读取event0文件的数据
    read(ts_fd, &ts_buf, sizeof(ts_buf));
​
    // 3.判断事件类型,打印出数据
    if(ts_buf.type == EV_ABS && ts_buf.code == ABS_X)//获取X轴坐标
    {
        ts_x = ts_buf.value;//0-1024  ---> 0-800
        ts_x = ts_x * 800 / 1024;
    }   
    if(ts_buf.type == EV_ABS && ts_buf.code == ABS_Y)//获取Y轴坐标
    {
        ts_y = ts_buf.value;//0-600
        ts_y = ts_y * 480 / 600;
    }       
    if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
    {
        printf("(x,y) = (%d,%d)",ts_x,ts_y);
    }
​
}
​
int main()
{
    // 1.打开fb0、event0文件
    lcd_fd = open("/dev/fb0", O_RDWR);
    if(lcd_fd < 0)
    {
        perror("open fb0");
        return -1;
    }
​
    ts_fd = open("/dev/input/event0", O_RDONLY);
    if (ts_fd == -1) 
    {
        perror("open touch failed\n");
        return -1;
    }
​
    // 内存映射
    p = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if(p == MAP_FAILED)
    {
        perror("mmap failed\n");
        return -1;
    }
   
   int i = 0;
    while (1)
    {
        get_xy();
        if(ts_buf.type == EV_KEY && ts_buf.code == BTN_TOUCH && ts_buf.value == 0)//松手检测
        {
            if(ts_x>=0 && ts_x<200)//上一张
            {
                i--;
                if(i<0)
                {
                    i = 4;
                }
                show_bmp(pic_path[i], 0, 0, 800, 480);
            }
            if(ts_x>=600 && ts_x<800)//下一张
            {
                i++;
                if(i>4)
                {
                    i = 0;
                }
                show_bmp(pic_path[i], 0, 0, 800, 480);
​
            }
            
​
​
        }
    }
    
    // 4.关闭文件
    munmap(p, 800*480*4);
    close(lcd_fd);
    close(ts_fd);
    return 0;
}

  • 27
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
粤嵌gec6818开发板可以用来制作音乐播放器。作为一块高性能的开发板,它具备强大的处理能力和丰富的接口资源,是一款理想的音乐播放器开发平台。 首先,gec6818开发板搭载了强大的八核ARM Cortex-A53处理器和高性能的Mali-T860 GPU,能够提供稳定流畅的音频播放和界面操作。其它核心配置,如4GB内存和64GB闪存,也能保证音乐播放的顺畅性和存储容量。 其次,gec6818开发板拥有丰富的接口资源,包括USB、HDMI、以太网、SD卡等,可以连接到各种外部设备,如音箱、耳机、显示器等。可以通过USB接口连接外部存储器,将音乐文件存储在U盘或移动硬盘中,方便传输和播放。 此外,gec6818开发板还支持多种音频格式和编码方式,如MP3、WAV、FLAC等,同时通过Linux操作系统的支持,可以实现强大的音频处理和控制功能,如均衡器调节、音量控制、音频格式转换等。 最后,开发者可以使用gec6818开发板上的硬件接口和软件开发工具,进行自定义的应用开发。借助开源的Linux系统和丰富的软件资源,可以实现自定义的UI界面和功能。同时,gec6818开发板还支持外接触摸屏,用户可以通过触摸屏进行音乐播放器的操作,提升用户体验。 综上所述,粤嵌gec6818开发板具备强大的处理能力和丰富的接口资源,可以用来制作高性能的音乐播放器,并提供多种功能和自定义选项,非常适合音乐爱好者和开发者使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值