GEC6818开发板——触摸屏

news/2025/3/31 2:14:05/

一、触摸屏(touch screen =TS)
1.分类
电阻触摸屏:压力感应 x+ x- y+ y-
电容触摸屏:电压感应 vcc gnd int(中断) rst(复位) scl(i2c的时钟) sda(i2c的数据)

2.触摸屏的文件路径名
/dev/input/event0

 

3.触摸屏有哪些信息
1)需要读取触摸屏的设备文件信息
2)设备文件信息包含3个信息 type\code\value

4.设备文件信息
gec@ubuntu:/mnt/hgfs/GZ2264/6_文件IO/05/code/zuoye$ vi /usr/include/linux/input.h 
 23 struct input_event {
 24     struct timeval time;
 25     __u16 type;
 26     __u16 code;
 27     __s32 value;
 28 };

说明(头文件的使用方法):
gec@ubuntu:/mnt/hgfs/GZ2264/6_文件IO/06/code$ ls /usr/include/stdio.h
/usr/include/stdio.h    ----->#include <stdio.h>
gec@ubuntu:/mnt/hgfs/GZ2264/6_文件IO/06/code$ ls /usr/include/linux/input.h 
/usr/include/linux/input.h   ----->#include <linux/input.h>

5.怎样读取触摸屏的设备文件
struct input_event ts;
read(fd,&ts,sizeof(struct input_event));
练习1:
通过指针传参来取值---指针的高级用法1
int get_value(int *x,int *y)
{
    *x = 100;
    *y = 250;    
    return 0;//不用通过返回值就可以从子函数中取值
}
int main()
{
    int num1=0,num2=0; //注意这里不要定义成int *num1与int *num2
    get_value(&num1,&num2);
    printf("num1=%d num2=%d\n",num1,num2);
    return 0;
}

6.分析触摸屏读取的type\code\value的值
练习2:(代码要在开发板上面执行)
1)读取一遍 type\code\value的值是什么?

	//打开触摸屏int fd;fd = open("/dev/input/event0",O_RDWR);//要用系统IO open函数打开硬件设备文件if(fd < 0){perror("open ts fail");return 0;}//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储在ts中struct input_event ts;while(1){	//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS &&ts.code == ABS_X){//printf("x=%d ",(int)(ts.value*0.78));  //黑色板x轴的坐标值printf("x=%d ",ts.value*800/1024);  //黑色板x轴的坐标值//printf("x=%d ",ts.value);  //蓝色板x轴的坐标值}if(ts.type == EV_ABS &&ts.code == ABS_Y){//printf("y=%d\n",(int)(ts.value*0.8)); //黑色板y轴的坐标值printf("y=%d\n",ts.value*480/600); //黑色板y轴的坐标值//printf("y=%d\n",ts.value); //蓝色板y轴的坐标值}}	//关闭触摸屏close(fd);


2)死循环读取type\code\value的值是什么,观察规律?
ts.type=3
ts.code=0
ts.value=493  //触摸屏x轴的坐标
ts.type=3
ts.code=1
ts.value=286 //触摸屏y轴的坐标
ts.type=1
ts.code=330
ts.value=1    //按键按下去
ts.type=1
ts.code=330
ts.value=0     //按键松手后

说明:
黑色的板触摸屏分辨率:1024*460;如果是这种,它的分辨率和LCD不一致,需要软件转换
蓝色的板触摸屏分辨率:800*480;如果是这种,它的分辨率和LCD一致,不需要软件转换

7.如何获取触摸屏里面的x轴和y轴的值
//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)
read(fd,&ts,sizeof(struct input_event));
if(ts.type == 3 &&ts.code == 0)
    printf("x=%d ",ts.value);  //x轴的坐标值
if(ts.type == 3 &&ts.code == 1)
    printf("y=%d\n",ts.value); //y轴的坐标值
练习3:用代码分别获取触摸屏5个点的坐标(4个边角点和1个中心点)

8.type、code、value的含义
type:输入事件的类型
code:输入事件的编码
value:输入事件的值(也是我们开发人员需要拿到的值)

type:
#define EV_ABS    0x3  //触摸屏事件类型
#define EV_KEY    0x1 //按键事件类型
code:
#define ABS_X    0x0 //x轴编码
#define ABS_Y    0x1 //y轴编码
#define BTN_TOUCH     0x14a  //按键编码

搜索指令grep
gec@ubuntu:/usr/include/linux$ grep -rn "EV_ABS"  //搜索字符串"EV_ABS"
input-event-codes.h:40:#define EV_ABS            0x03
gec@ubuntu:/usr/include/linux$ vi input-event-codes.h +40 //打开这个文件 直接跳到第30行

思考问题:
1)为什么有时候一直打印x轴的值
  当你横着滑动屏幕的时候,此时y轴的值没有产生变化,输入子系统认为你y轴的编码事件没有变化,不打印y轴值
2)为什么有时候一直打印y轴的值
 当你竖着滑动屏幕的时候,此时x轴的值没有产生变化,输入子系统认为你x轴的编码事件没有变化,不打印x轴值
3)怎样点击触摸屏让它x和y轴的值成对出现
 当你斜着滑动屏幕的时候,输入子系统认为你x轴和y轴的编码事件都有变化,都打印。

9.如何将触摸屏的分辨率转换成LCD的分辨率一模一样(强制类型转换)
//printf("x=%d ",(int)(ts.value*0.78));  //黑色板x轴的坐标值
printf("x=%d ",ts.value*800/1024);  //黑色板x轴的坐标值
//printf("y=%d\n",(int)(ts.value*0.8)); //黑色板y轴的坐标值
printf("y=%d\n",ts.value*480/600); //黑色板y轴的坐标值

10.按下去和松手后的操作识别(如何避免点下去的时候出现好几次打印)
1)单片机:
按键消抖:按下去的时候延时一会儿,再检测电平
松手检测:松手的时候延时一会儿,再检测电平
2)linux:
这里没有按键消抖和松手检测这个概念,它将按下去和松手后封装成两个事件
按下去的事件
if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value == 1)//按下去
{
    printf("按下去 x=%d y=%d\n",x,y);

松手后的事件
if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value == 0)//松手
{
    printf("松手 x=%d y=%d\n",x,y);
}

练习4:
点击屏幕左边显示left 点击屏幕右边显示right

	//打开触摸屏int fd;fd = open("/dev/input/event0",O_RDWR);//要用系统IO open函数打开硬件设备文件if(fd < 0){perror("open ts fail");return 0;}//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储在ts中struct input_event ts;int x=0,y=0;while(1){	//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS &&ts.code == ABS_X){printf("x=%d ",ts.value*800/1024);  //黑色板x轴的坐标值//printf("x=%d ",ts.value);  //蓝色板x轴的坐标值}if(ts.type == EV_ABS &&ts.code == ABS_Y){printf("y=%d\n",ts.value*480/600); //黑色板y轴的坐标值//printf("y=%d\n",ts.value); //蓝色板y轴的坐标值}/* 		//方法一:if(x<400) //有可能会出现多次打印left或right的情况printf("left\n");if(x>400)printf("right\n"); */if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value == 1)//按下去{//方法二printf("按下去 x=%d y=%d\n",x,y);if(x<400) printf("left\n");if(x>400)printf("right\n");} 		}	//关闭触摸屏close(fd);

10.滑动的原理
左右滑动:按下和松手后x轴的坐标差值
上下滑动:按下和松手后y轴的坐标差值
1)抓取按下的坐标值
while(1)
{    
    //读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)
    read(fd,&ts,sizeof(struct input_event));
    if(ts.type == EV_ABS &&ts.code == ABS_X)
    {
        //printf("x=%d ",ts.value*800/1024);  //黑色板x轴的坐标值
        x = ts.value*800/1024;
    }
    if(ts.type == EV_ABS &&ts.code == ABS_Y)
    {
        //printf("y=%d\n",ts.value*480/600); //黑色板y轴的坐标值    
        y = ts.value*480/600;
    }
    //按下去的时刻或者松手后的时刻
    if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value == 1)//按下去
    {
        printf("按下去 x=%d y=%d\n",x,y);
        break;
    }     
}    
2)抓取松手后的坐标值
while(1)
{    
    //读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)
    read(fd,&ts,sizeof(struct input_event));
    if(ts.type == EV_ABS &&ts.code == ABS_X)
    {
        //printf("x=%d ",ts.value*800/1024);  //黑色板x轴的坐标值
        x1 = ts.value*800/1024;
    }
    if(ts.type == EV_ABS &&ts.code == ABS_Y)
    {
        //printf("y=%d\n",ts.value*480/600); //黑色板y轴的坐标值    
        y1 = ts.value*480/600;
    }
    if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value == 0)//松手
    {
        printf("松手 x1=%d y1=%d\n",x1,y1);
        break;
    } 
}    

 

练习5:
将点击的代码和滑动合在一起

#include "my_head.h"enum SLIDE{left,right,up,down};
enum TOUCH{left_area,right_area};int fd;
//获取点击区域位置
int touch()
{//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中struct input_event ts;//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)int x,y;while(1){read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x = ts.value*800/1024;//x轴坐标}if(ts.type == EV_ABS && ts.code == ABS_Y){y = ts.value*480/600;//y轴坐标}//按下去的时刻或者松手后的时刻if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手后{if(x <400)return left;elsereturn right;}}
}//拿去上下左右滑动状态
int slide()
{//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中struct input_event ts;int x,y,x1,y1;while(1){while(1){read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x = ts.value*800/1024;}if(ts.type == EV_ABS && ts.code == ABS_Y){y = ts.value*480/600;}//按下去的时刻或者松手后的时刻if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)//按下去{printf("按下去 (%d,%d)\n",x,y);break;}}//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)while(1){read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x1 = ts.value*800/1024;}if(ts.type == EV_ABS && ts.code == ABS_Y){y1 = ts.value*480/600;}if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手{printf("松手后 (%d,%d)\n",x1,y1);break;}}if(x1-x > 100)return right;if(x1-x < -100)return left;if(y1-y > 100)return down;if(y1-y < -100)return up;}return 0;
}int main(int argc,char *argv[])
{//打开触摸屏fd = open("/dev/input/event0",O_RDWR);if(fd < 0){perror("open fd error!\n");return 0;}while(1){//点击switch(touch()){case left:printf("touch left!\n");break;case right:printf("touch right!\n");break;}//滑动switch(slide()){case up:printf("up slide!\n");break;case down:printf("down slide!\n");break;case left:printf("left slide!\n");break;case right:printf("right slide!\n");break;}}//关闭触摸屏close(fd);return 0;
}

练习6:
使用滑动来切换图片
 

#include "my_head.h"enum SLIDE{left,right,up,down};
int fd,fd_lcd;int show_pic(int *p,char *bmp_path)
{//打开bmp图片int bmp = open(bmp_path,O_RDWR);if(bmp < 0){printf("open bmp fail!\n");return -1;}//去除掉头54个字节lseek(bmp,54,SEEK_SET);//存储bmp图片的buffer:800*480*3char buf[800*480*3] = {0};int ret1 = read(bmp,buf,800*480*3);		sleep(1);//读bmp图片//将buf数据通过指针p填充到LCD中int x;//x表示横轴int y;//y表示纵轴for(y=0;y<480;y++){for(x=0;x<800;x++){*(p+((479-y)*800+x)) = (buf[3*(y*800+x)+0]) | (buf[3*(y*800+x)+1]<<8) | (buf[3*(y*800+x)+2]<<16);}}close(bmp);return 0;
}//拿去上下左右滑动状态
int slide()
{//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中struct input_event ts;int x,y,x1,y1;while(1){while(1){read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x = ts.value*800/1024;}if(ts.type == EV_ABS && ts.code == ABS_Y){y = ts.value*480/600;}//按下去的时刻或者松手后的时刻if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)//按下去{printf("按下去 (%d,%d)\n",x,y);break;}}//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)while(1){read(fd,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x1 = ts.value*800/1024;}if(ts.type == EV_ABS && ts.code == ABS_Y){y1 = ts.value*480/600;}if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手{printf("松手后 (%d,%d)\n",x1,y1);break;}}if(x1-x > 100)return right;if(x1-x < -100)return left;if(y1-y > 100)return down;if(y1-y < -100)return up;}return 0;
}int main(int argc,char *argv[])
{//打开触摸屏fd = open("/dev/input/event0",O_RDWR);if(fd < 0){perror("open fd error!\n");return 0;}//打开lcdfd_lcd = open("/dev/fb0",O_RDWR);if(fd_lcd < 0){printf("open fd_lcd error!\n");return 0;}//lcd映射//指针指向一个像素点int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd_lcd,0);if(p == NULL){perror("mmap fail!\n");return -1;}while(1){//指针数组存储字符串char *bmp_path[] = {"james.bmp","wade.bmp"};int i=0;//滑动switch(slide()){case up:printf("up slide!\n");show_pic(p,bmp_path[0]);break;case down:printf("down slide!\n");show_pic(p,bmp_path[1]);break;case left:printf("left slide!\n");show_pic(p,bmp_path[0]);break;case right:printf("right slide!\n");show_pic(p,bmp_path[1]);break;}}//lcd映射释放munmap(p,800*480*4);//关闭触摸屏close(fd);return 0;
}

作业1:
点击左边显示一张bmp 点击右边显示一张jpg

	//打开lcdint fd_lcd = open("/dev/fb0",O_RDWR);if(fd_lcd < 0){printf("open fd_lcd error!\n");return 0;}//lcd映射//指针指向一个像素点int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd_lcd,0);if(p == NULL){perror("mmap fail!\n");return -1;}//打开触摸屏int fd_ts = open("/dev/input/event0",O_RDWR);if(fd_ts < 0){printf("open fd_ts error!\n");return 0;}//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中struct input_event ts;//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)int x,y;while(1){//指针数组存储字符串char *bmp_path[] = {"james.bmp","wade.bmp"};int i;read(fd_ts,&ts,sizeof(struct input_event));if(ts.type == EV_ABS && ts.code == ABS_X){x = ts.value*800/1024;//x轴坐标}if(ts.type == EV_ABS && ts.code == ABS_Y){y = ts.value*480/600;//y轴坐标}//按下去的时刻或者松手后的时刻if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)//按下去{if(x <400){if(i<2){printf("left!\n");printf("show[%d]\n",i+1);				show_pic(p,bmp_path[i]);	i++;}// else// {// i=0;// show_pic(p,bmp_path[i]);// }}else if(x > 400){printf("right!\n");if(i==2){i=0;show_pic(p,bmp_path[i]);}else{lcd_draw_jpg(0,0,"./jr.jpg",NULL,0,0);}}				}}//lcd映射释放munmap(p,800*480*4);//关闭lcd\bmp\tsclose(fd_lcd);close(fd_ts);

附加题:
//触摸屏的函数封装如下
int get_xy(int *x,int *y)
{

}
int main()
{
    int x,y;
    get_xy(&x,&y);  //通过调用get_xy来获取x和y轴的坐标值
    printf("x=%d y=%d\n",x,y);    
    return 0;
}

#include "my_head.h"int get_xy(int *x,int *y)
{//打开触摸屏int fd;fd = open("/dev/input/event0",O_RDWR);if(fd < 0){perror("open fd error!\n");return 0;}	//定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中struct input_event ts;while(1){//读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)read(fd,&ts,sizeof(ts));//3. 判断事件  xif(ts.type == EV_ABS && ts.code == ABS_X){*x = ts.value*800/1024;//x轴坐标}if(ts.type == EV_ABS && ts.code == ABS_Y){*y = ts.value*480/600;//y轴坐标}if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手后break;}//关闭触摸屏close(fd);}int main(int argc,char *argv[])
{int x,y;get_xy(&x,&y);  //通过调用get_xy来获取x和y轴的坐标值printf("(%d , %d)\n",x,y);return 0;
}


http://www.ppmy.cn/news/712366.html

相关文章

【抓包工具】配置:Charles 配置华为手机 HTTPS CA 证书

目录 一、前言 二、手机开启 USB 调试模式 三、本地下载 Charles 证书保存到手机上 &#xff08;1&#xff09;通过电脑在手机存储中新增一个文件夹 &#xff08;2&#xff09;Charles 下载证书到本地电脑上 &#xff08;3&#xff09;将电脑上的 CA 证书复制黏贴进手机新…

小米手机(MIUI 13)安装Fiddler CA证书

Windows上的Fiddler设置 开启Fiddler解密Https报文设置 Tools → Options → HTTPS 如果CA证书安装失败&#xff0c;则点击Action → Export Root Certificate to Desktop操作&#xff0c;将Fidder的根证书导出存放在Windows桌面&#xff0c;然后再手动安装和信任该CA证书&a…

【elementplus】解决el-table使用el-popconfirm,只剩下一行数据时,popconfirm提示框会被el-table边框遮挡的问题

首先&#xff0c;先通过以下链接的方法&#xff0c;解决在el-table中使用popconfirm、popover、tooltip、select时&#xff0c;出现placement错位或者框被table的列遮挡的问题 然后就是有可能会出现el-table只剩下一行数据&#xff0c;popconfirm提示框依旧会被el-table边框遮…

JVM02-JVM即时编译器JIT

1-类编译加载执行过程 先了解下Java从编译到运行的整个过程 类编译&#xff1a;在编写好代码之后&#xff0c;我们需要将 .java文件编译成 .class文件&#xff0c;才能在虚拟机上正常运行代码。文件的编译通常是由JDK中自带的Javac工具完成&#xff0c;一个简单的 .java文件&a…

c语言香农编码文件压缩,谈谈熵编码无损压缩的原理

一、概要 在项目开发中,有引入用到rANS熵编码压缩算法,在使用的背后,想看看其运行的基本原理,也算补一下个人的熵编码知识。这里提到的熵编码压缩算法都是无损压缩。很久没有写文章了,太忙了,不知道一年一篇文章算不算年更 :b 二、熵编码 目前较为成熟的熵编码是霍夫曼编…

ADDS数据无损分区工具

http://jingyan.baidu.com/article/acf728fd439289f8e510a33e.html 使用u启动ADDS数据无损分区工具进行硬盘分区 http://www.cr173.com/html/13113_1.html ADDS硬盘分区王完美支持Win7无损分区扩容图文教程 转载于:https://blog.51cto.com/zzr7706/1970121

中国无损探伤检测行业发展前景与投资战略规划分析报告2021-2027年

中国无损探伤检测行业发展前景与投资战略规划分析报告2021-2027年 详情内容请咨询鸿晟信合研究院&#xff01; 【全新修订】&#xff1a;2022年2月 【撰写单位】&#xff1a;鸿晟信合研究研究 【报告目录】 第1章&#xff1a;无损探伤检测行业概述及环境分析 1.1 无损探伤检测…

Java实现哈夫曼编码--数据无损压缩

数据结构之哈夫曼编码—数据无损压缩 哈夫曼编码可以可以将数据无损压缩&#xff0c;很强大&#xff0c;那么我们来了解一下哈夫曼编码&#xff1a; 首先&#xff0c;哈夫曼编码的原理是利用了哈夫曼树&#xff0c;通过统计数据中字符出现的次数&#xff0c;让出现最多的字符…