ARM开发板——实时获取用户点击触摸屏的LCD坐标信息(阻塞式读取)

ARM开发板——实时获取用户点击触摸屏的LCD坐标信息(阻塞式读取)

1、硬件信息

ARM开发板使用的内核为CotexA53芯片,LCD屏为七寸800 * 480像素,触摸屏为1024 * 600

2、代码需求

实时监听用户点击触摸屏的事件,并获取点击位置(LCD坐标)

3、代码实现

基本步骤:

  1. 打开触摸屏设备文件,触摸屏设备文件位于/dev/input/event0;

  2. 创建输入事件结构体,该结构体定义于/usr/include/linux/input.h;

    /*
     * /usr/include/linux/input.h 摘录
     */ 
    
    /*
     * The event structure itself
     */
    
    struct input_event {
    	struct timeval time;
    	__u16 type;
    	__u16 code;
    	__s32 value;
    };
    
    // ...省略
    
    /*
     * Event types
     */
    
    #define EV_SYN			0x00
    #define EV_KEY			0x01
    #define EV_REL			0x02
    #define EV_ABS			0x03     // 绝对位置
    #define EV_MSC			0x04
    #define EV_SW			0x05
    #define EV_LED			0x11
    #define EV_SND			0x12
    #define EV_REP			0x14
    #define EV_FF			0x15
    #define EV_PWR			0x16
    #define EV_FF_STATUS		0x17
    #define EV_MAX			0x1f
    #define EV_CNT			(EV_MAX+1)
    
    // ...省略
    
    /*
     * Absolute axes
     */
    
    #define ABS_X			0x00			// x轴
    #define ABS_Y			0x01			// y轴
    #define ABS_Z			0x02
    #define ABS_RX			0x03
    #define ABS_RY			0x04
    #define ABS_RZ			0x05
    #define ABS_THROTTLE		0x06
    #define ABS_RUDDER		0x07
    #define ABS_WHEEL		0x08
    #define ABS_GAS			0x09
    #define ABS_BRAKE		0x0a
    #define ABS_HAT0X		0x10
    #define ABS_HAT0Y		0x11
    #define ABS_HAT1X		0x12
    #define ABS_HAT1Y		0x13
    #define ABS_HAT2X		0x14
    #define ABS_HAT2Y		0x15
    #define ABS_HAT3X		0x16
    #define ABS_HAT3Y		0x17
    #define ABS_PRESSURE		0x18
    #define ABS_DISTANCE		0x19
    #define ABS_TILT_X		0x1a
    #define ABS_TILT_Y		0x1b
    #define ABS_TOOL_WIDTH		0x1c
    
  3. 循环读取事件(阻塞式读取);

    在ARM开发板的触摸屏事件监听中,看似“死循环”的代码设计其实并非低效的忙等待(busy-waiting),而是基于阻塞式读取(blocking read)的事件驱动机制:

    • 当调用 read(fd, &event, sizeof(event)) 时,若设备文件(如 /dev/input/event0)无事件发生,内核会将进程挂起(进入阻塞状态),此时不占用CPU资源,直到有触摸事件触发中断,内核唤醒进程并返回数据。
    • 示例代码中的 while(1) 循环本质上是等待事件的“休眠-唤醒”过程,而非持续消耗CPU的忙等待。
    行为 资源占用 实现场景
    阻塞式读取(read 无事件时CPU占用率接近0% 适用于实时事件监听
    忙等待(轮询) 持续占用CPU(如 while(1) { poll(); } 需避免,仅用于极低延迟场景

    嵌入式系统中类似机制广泛存在(如传感器数据采集),均依赖阻塞IO而非主动轮询,在典型ARM Linux系统中,阻塞式读取触摸屏事件的进程在无操作时CPU占用率为0%,触摸事件响应延迟在10ms以内

  4. 根据event结构体的type 判断是否为绝对位置,code判断是y轴还是x轴数据;

  5. 将触摸屏坐标转换为LCD坐标后输出坐标信息;

具体实现如下:

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

int main(int argc, char const *argv[])
{
    // 1、打开触摸屏设备文件
    int touch = open("/dev/input/event0", O_RDWR);

    if (touch == -1)
    {
        printf("文件打开出错!");
        exit(-1);
    }
    
    // 2、创建输入事件结构体
    struct input_event event;

    // 3、循环读取事件(阻塞式读取)
    int count = 0;
    int x = 0;
    int y = 0;
    while (1)
    {
        ssize_t size = read(touch, &event , sizeof(struct input_event));
        if(event.type == EV_ABS){
            if(event.code == ABS_X)
            {
                count ++;
                x = event.value * 800 / 1024;  // lcd_width: 800,触摸屏x:1024
            } 
            if(event.code == ABS_Y)
            {
                count ++;
                y = event.value * 480 / 600; // lcd_height: 480, 触摸屏y:600
            } 
            if(count ==2) {
                printf("x = %d\t", x);
                printf("y = %d\n", y);
                count = 0;
            }
        }
    }
    
    // 4、关闭文件
    close(touch);
    return 0;
}

编译后传输至开发板测试:

[root@GEC6818 /workspace/touchtest]#./touchtest
x = 316 y = 229
x = 402 y = 332
x = 388 y = 336
x = 133 y = 377
x = 29 y = 412
x = 1 y = 468
x = 1 y = 236
x = 5 y = 222
x = 58 y = 231
x = 114 y = 250
x = 444 y = 272
x = 576 y = 271
x = 723 y = 262
x = 798 y = 244
x = 798 y = 254

测试无误,需求实现!

posted @ 2025-03-24 00:11  小镇青年达师傅  阅读(76)  评论(0)    收藏  举报