ARM开发板——实时获取用户点击触摸屏的LCD坐标信息(阻塞式读取)
- ARM开发板——实时获取用户点击触摸屏的LCD坐标信息(阻塞式读取)
- 1、硬件信息
- 2、代码需求
- 3、代码实现
1、硬件信息
ARM开发板使用的内核为CotexA53芯片,LCD屏为七寸800 * 480像素,触摸屏为1024 * 600
2、代码需求
实时监听用户点击触摸屏的事件,并获取点击位置(LCD坐标)
3、代码实现
基本步骤:
-
打开触摸屏设备文件,触摸屏设备文件位于
/dev/input/event0
; -
创建输入事件结构体,该结构体定义于
/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
-
循环读取事件(阻塞式读取);
在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以内。
- 当调用
-
根据event结构体的type 判断是否为绝对位置,code判断是y轴还是x轴数据;
-
将触摸屏坐标转换为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
测试无误,需求实现!