• Linux输入设备应用编程(触摸屏获取坐标信息)


    上一章学习了开发板外接键盘并获取键盘的的输入

    Linux输入设备应用编程(键盘,按键)-CSDN博客

    本章编写触摸屏应用程序,获取触摸屏的坐标信息并将其打印出来

    目录

    一 触摸屏数据分析(触摸,点击,松开)

    1.1 硬件须知 

    1.2 触摸屏信息分析

    二 触摸屏应用编程

    2.1 获取触摸屏的最大同时触点

    2.2  触摸屏单点触点编程


    一 触摸屏数据分析(触摸,点击,松开)

    1.1 硬件须知 

    首先在测试触摸屏之前,需要保证开发板上已经连接了LCD屏

    使用命令"cat /proc/bus/input/devices",确定触摸屏对应的设备节点(本人将指令封装成了cat_dev),如下所示:  

    7寸的LCD屏 红线划的是我LCD的设备名与设备节点

    1.2 触摸屏信息分析

    执行input文件后,一个手指点击触摸屏后松开,终端将会打印如下信息:  

    首先第一行上报了绝对位移事件EV_ABS(type=3)中的ABS_MT_TRACKING_ID(code=57)事件,并且value值等于246,也就是ID,这个ID是一个非负数,所以表示这是一个新的触摸点被创建,也就意味着触摸屏上产生了一个新的触摸点(手指按下)。

    第二行上报了绝对位移事件EV_ABS(type=3)中的ABS_MT_POSITION_X(code=53)事件,其value对应的便是触摸点的X坐标;

    第三行上报了ABS_MT_POSITION_Y(code=54)事件,其value值对应的便是触摸点Y坐标,所以由此可知该触摸点的坐标为(890, 445)。

    第四行上报了按键类事件EV_KEY(type=1)中的BTN_TOUCH(code=330),value值等于1,表示这是触摸屏上最先产生的触摸点(slot=0、也就是触摸点0)。

    第五行和第六行分别上报了绝对位移事件EV_ABS(type=3)中的ABS_X(code=0)和ABS_Y(code=1),其value分别对应的是触摸点的X坐标和Y坐标。多点触摸设备也会通过ABS_X、ABS_Y事件上报触摸点的X、Y坐标,但通常只有触摸点0支持,所以可以把多点触摸设备当成单点触摸设备来使用。

    第七行上报了同步类事件EV_SYN(type=0)中的SYN_REPORT(code=0)事件,表示此次触摸点的信息全部上报完毕。

    第八行当手指松开时,触摸点就会被销毁,上报ABS_MT_TRACKING_ID事件,并将value设置为-1(ID)

    第四行上报了按键类事件EV_KEY(type=1)中的BTN_TOUCH(code=330),value值等于0,表示触摸屏上的触摸点销毁

    最后一行上报同步事件(type=0、code=0),告知应用层数据完整。

    二 触摸屏应用编程

    2.1 获取触摸屏的最大同时触点

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(int argc, char *argv[])
    9. {
    10. struct input_absinfo info; //调用 ioctl()会将获取到的信息写入到struct input_absinfo对象
    11. int fd = -1;
    12. int max_slots; //最大触摸点数
    13. /* 校验传参 */
    14. if (2 != argc) {
    15. fprintf(stderr, "usage: %s \n", argv[0]);
    16. exit(-1);
    17. }
    18. /* 打开文件 */
    19. if (0 > (fd = open(argv[1], O_RDONLY))) {
    20. perror("open error");
    21. exit(-1);
    22. }
    23. /* 获取slot信息 */
    24. if (0 > ioctl(fd, EVIOCGABS(ABS_MT_SLOT), &info)) {
    25. perror("ioctl error");
    26. close(fd);
    27. exit(-1);
    28. }
    29. max_slots = info.maximum + 1 - info.minimum;
    30. printf("max_slots: %d\n", max_slots);
    31. /* 关闭、退出 */
    32. close(fd);
    33. exit(0);
    34. }

     代码写完后,进行交叉编译,通过scp指令将文件发送到开发板上,然后执行input_slot文件

    所以从打印结果可知,我们这个屏是一个5点触摸屏。 

    2.2  触摸屏单点触点编程

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(int argc, char *argv[])
    9. {
    10. int fd = -1;
    11. struct input_event in_ev;
    12. int x = 0; //触摸点 x和 y坐标
    13. int y = 0;
    14. int start = 3; //用于记录 BTN_TOUCH事件的 value,1表示按下,0表示松开,-1表示移动
    15. int valid = -1; //用于记录数据是否有效(我们关注的信息发生更新表示有效,1表示有效,0表示无效
    16. /* 校验传参 */
    17. if (2 != argc) {
    18. fprintf(stderr, "usage: %s \n", argv[0]);
    19. exit(-1);
    20. }
    21. /* 打开文件 */
    22. if (0 > (fd = open(argv[1], O_RDONLY))) {
    23. perror("open error");
    24. exit(-1);
    25. }
    26. while(1)
    27. {
    28. if(sizeof(struct input_event) != read(fd,&in_ev,sizeof(struct input_event)))
    29. {
    30. perror(" ");
    31. exit(-1);
    32. }
    33. switch (in_ev.type)
    34. {
    35. case EV_KEY: //按键事件
    36. if (BTN_TOUCH == in_ev.code) //触摸屏第一个点
    37. {
    38. start = in_ev.value; //触摸屏状态
    39. valid = 1; //同步时间标志位
    40. }
    41. break;
    42. case EV_ABS: //绝对位移事件
    43. switch (in_ev.code)
    44. {
    45. case ABS_X: //X坐标
    46. x = in_ev.value;
    47. valid = 1;
    48. break;
    49. case ABS_Y: //Y坐标
    50. y = in_ev.value;
    51. valid = 1;
    52. break;
    53. }
    54. break;
    55. case EV_SYN: //同步事件
    56. if (SYN_REPORT == in_ev.code) {
    57. if (valid) {//判断是否有效
    58. switch (start) {//判断状态
    59. case 1:
    60. printf("按下(%d, %d)\n", x, y);
    61. break;
    62. case 0:
    63. printf("松开\n");
    64. break;
    65. case -1:
    66. printf("移动(%d, %d)\n", x, y);
    67. break;
    68. }
    69. valid = 0; //重置valid
    70. start = -1; //重置start
    71. }
    72. }
    73. break;
    74. }
    75. }
    76. /* 关闭、退出 */
    77. close(fd);
    78. exit(0);
    79. }

    程序中首先校验传参,通过传参的方式将触摸屏设备文件路径传入到程序中,main()函数中定义了4个变量:

    1. 变量x表示触摸点的X坐标;
    2. 变量y表示触摸点的Y坐标;
    3. 变量start表示手指状态时候按下、松开还是滑动,start=1表示手指按下、start=0表示手指松开、start=-1表示手指滑动;
    4. 变量valid表示数据是否有效,valid=1表示有效、valid=0表示无效;有效指的是我们检测的信息发生了更改,譬如程序中只检测了手指的按下、松开动作以及坐标值的变化。

    接着调用open()打开触摸屏设备文件得到文件描述符fd;在for循环之前,首先对x、y、start、valid这4个变量进行初始化操作。在for循环读取触摸屏上报的数据,将读取到的数据存放在struct input_event数据结构中。在switch…case语句中对读取到的数据进行解析,获取BTN_TOUCH事件的value数据,判断触摸屏是按下还是松开状态,获取ABS_X和ABS_Y事件的value变量,得到触摸点的X轴坐标和Y轴坐标。

    当上报同步事件时,表示数据已经完整,接着对我们得到的数据进行分析、打印坐标信息。

    将编译得到的可执行文件拷贝到开发板,准备进行测试。

    当手指点击触摸屏时会打印"按下(X, Y)",松开时会打印"松开",手指在触摸屏上滑动时会打印"移动(X, Y)"等信息。

  • 相关阅读:
    任务调度平台在服务器集群上的分布式搭建笔记
    使用Django JWT实现身份验证
    人体神经元细胞分布图片,神经元人体分布大图
    最新Tuxera NTFS2023最新版Mac读写NTFS磁盘工具 更新详情介绍
    输入框自动保留2位小数
    高效案例检索工具,Alpha案例库智慧检索成为律师检索工具首选
    【刷题】代码随想录算法训练营第二十三天|669、修剪二叉搜索树,108、将有序数组转换为二叉搜索树,538、把二叉搜索树转换为累加树
    SpringBoot单元测试(unit testing)
    【WhatsApp营销】如何将WhatsApp与品牌的社交媒体营销相结合
    RflySim | 滤波器设计实验二
  • 原文地址:https://blog.csdn.net/weixin_73901182/article/details/134465867