一、觸摸屏(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;
}
總結
以上是生活随笔為你收集整理的GEC6818开发板——触摸屏的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。