当前位置: 首页 > news >正文

Linux学习笔记--触摸屏驱动

关键数据结构

1. 触摸控制器寄存器结构

struct qemu_ts_con {volatile unsigned int pressure;  // 压力/触摸状态volatile unsigned int x;         // X 坐标volatile unsigned int y;         // Y 坐标  volatile unsigned int clean;     // 清理标志
};
  • volatile 确保编译器不会优化对这些寄存器的访问

  • 这个结构体映射到硬件的内存区域

2. 全局变量

static struct input_dev *g_input_dev;  // 输入设备
static int g_irq;                      // 中断号
static struct qemu_ts_con *ts_con;     // 映射的硬件寄存器
struct timer_list ts_timer;            // 定时器

核心机制:中断 + 定时器

1. 定时器回调函数

static void ts_irq_timer(unsigned long _data)
{if (ts_con->pressure) // 如果仍然处于按压状态{// 持续上报坐标input_event(g_input_dev, EV_ABS, ABS_X, ts_con->x);input_event(g_input_dev, EV_ABS, ABS_Y, ts_con->y);input_sync(g_input_dev);// 重新设置定时器,实现轮询mod_timer(&ts_timer, jiffies + msecs_to_jiffies(TOUCHSCREEN_POLL_TIME_MS));}
}
  • 在触摸持续期间,定时器每 10ms 触发一次

  • 持续上报触摸坐标,实现触摸移动的跟踪

为什么需要定时器轮询?

触摸移动的连续性

  • 中断只在触摸开始和结束时触发

  • 但在触摸过程中,手指可能持续移动

  • 定时器轮询可以捕获这些连续的坐标变化

时间间隔选择:10ms

TOUCHSCREEN_POLL_TIME_MS 10 的含义:

  • 100Hz 采样率:每秒采样 100 次坐标

  • 平衡性能与流畅度

    • 太频繁:CPU 占用率高

    • 太稀疏:触摸轨迹不连贯

  • 典型触摸屏的采样率在 60-120Hz 之间

内核定时器机制
定时器初始化:
setup_timer(&ts_timer, ts_irq_timer, (unsigned long)NULL);
时间计算:
jiffies + msecs_to_jiffies(10)
  • jiffies: 当前时间(从系统启动开始的节拍数)

  • msecs_to_jiffies(10): 将 10ms 转换为对应的节拍数

  • 结果:定时器在"当前时间 + 10ms"后再次触发

与中断处理函数的协作
中断函数中的定时器启动:
// 在 input_dev_demo_isr 中:
if (ts_con->pressure)  // 触摸按下
{// ... 上报初始坐标 .../* start timer */mod_timer(&ts_timer, jiffies + msecs_to_jiffies(TOUCHSCREEN_POLL_TIME_MS));
}

2. 中断服务程序

static irqreturn_t input_dev_demo_isr(int irq, void *dev_id)
{if (ts_con->pressure)  // 触摸按下{// 上报初始触摸坐标input_event(g_input_dev, EV_ABS, ABS_X, ts_con->x);input_event(g_input_dev, EV_ABS, ABS_Y, ts_con->y);input_event(g_input_dev, EV_KEY, BTN_TOUCH, 1);  // 触摸开始input_sync(g_input_dev);// 启动定时器进行持续轮询mod_timer(&ts_timer, jiffies + msecs_to_jiffies(TOUCHSCREEN_POLL_TIME_MS));}else  // 触摸释放{input_event(g_input_dev, EV_KEY, BTN_TOUCH, 0);  // 触摸结束input_sync(g_input_dev);// 注意:这里应该停止定时器,但代码中缺失了 del_timer}return IRQ_HANDLED;
}

驱动probe函数详解

1. 设备信息获取

// 从设备树获取 GPIO
gpio = of_get_gpio(pdev->dev.of_node, 0);// 获取内存映射资源
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ts_con = ioremap(io->start, io->end - io->start + 1);

2. 输入设备设置

/* set 1: which type event ? */	
__set_bit(EV_KEY, g_input_dev->evbit);    // 按键事件
__set_bit(EV_ABS, g_input_dev->evbit);    // 绝对坐标事件
__set_bit(INPUT_PROP_DIRECT, g_input_dev->propbit);  // 直接输入设备/* set 2: which event ? */	
__set_bit(BTN_TOUCH, g_input_dev->keybit);  // 触摸按键
__set_bit(ABS_X, g_input_dev->absbit);      // X 坐标
__set_bit(ABS_Y, g_input_dev->absbit);      // Y 坐标/* set 3: event params ? */	
input_set_abs_params(g_input_dev, ABS_X, 0, 0xffff, 0, 0);
input_set_abs_params(g_input_dev, ABS_Y, 0, 0xffff, 0, 0);

__set_bit(INPUT_PROP_DIRECT, g_input_dev->propbit);

用于设置输入设备的属性,表明这是一个直接输入设备

__set_bit 宏:

// 内核中的位操作宏
#define __set_bit(nr, addr) set_bit(nr, addr)
  • 作用:将位图中的特定位设置为 1

  • nr:要设置的位号(这里是 INPUT_PROP_DIRECT

  • addr:位图地址(这里是 g_input_dev->propbit

参数说明:

  • INPUT_PROP_DIRECT:输入设备属性常量,值为 0

  • g_input_dev->propbit:输入设备的属性位图

INPUT_PROP_DIRECT 的含义

直接输入设备(Direct Input Device):

  • 定义:用户直接在设备表面上操作,操作位置与光标位置直接对应

  • 典型例子

    • 触摸屏(Touchscreen)

    • 数字化仪(Graphics Tablet)

    • 触摸板(Touchpad)

3. 硬件初始化

// 内存映射
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ts_con = ioremap(io->start, io->end - io->start + 1);// GPIO 转中断号,并注册中断
g_irq = gpio_to_irq(gpio);
error = request_irq(g_irq, input_dev_demo_isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "input_dev_demo_irq", NULL);// 初始化定时器
setup_timer(&ts_timer, ts_irq_timer, (unsigned long)NULL);

工作流程

1. 触摸按下流程

GPIO 中断(上升沿) → 中断处理函数 → 上报触摸开始 → 启动定时器 → 定时器轮询坐标

2. 触摸移动流程

定时器每10ms触发 → 读取坐标 → 上报新位置 → 重置定时器

3. 触摸释放流程

GPIO 中断(下降沿) → 中断处理函数 → 上报触摸结束 → 停止定时器(代码中缺失)

设备树配置

这个驱动期望的设备树节点:

input_dev_demo: input_dev_demo {compatible = "100ask,input_dev_demo";reg = <0x12345000 0x1000>;        // 内存映射区域gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;  // GPIO 引脚interrupt-parent = <&gpio1>;interrupts = <1 IRQ_TYPE_EDGE_BOTH>;  // 双边沿触发
};

http://www.dtcms.com/a/470638.html

相关文章:

  • 浏览器跨域Access-Control-Allow-Origin三五问
  • 中企动力做的网站经常打不开怎么做网页设计稿
  • c 手机网站开发做电商一个月可以赚多少钱
  • openFuyao v25.09 版本正式发布!社区发行版全新升级,AI推理进一步优化
  • 世界标准日:关于 “标准”
  • 从671B到70B,如何用更低成本实现企业大模型工程化的RAG、Agent与微调落地,大模型入门到精通,收藏这篇就足够了!
  • 给网站添加关键词流行的wordpress主题
  • 深入理解epoll_data数据关联机制:四种方式详解与实践指南
  • m3u8格式在直播场景中的应用
  • 医疗门户网站管理系统在线营销推广
  • 积分非线性(INL)和微分非线性(DNL)的含义与联系
  • JavaSE面向对象(上)
  • 光的礼赞:探索自然界中的神奇之光
  • 一个企业网站的建设流程微信小程序商城收费吗
  • C++核心语法精要指南
  • 网站中弹出广告怎么做的腾讯官方网站做书签
  • 国外优秀的设计网站公司要做seo
  • 丰台体育馆网站建设WordPress批量修改文章
  • 计算机操作系统:进程同步
  • 怎么制作网站封面建设网站的视频
  • 为什么做网站要有自己的服务器做网站自己租服务器还是网络公司
  • DeepSeek vs ChatGPT 技术架构、成本与场景全解析
  • java开发三层架构下的分层解耦
  • 缔客网络上海响应式网站建设如何建平台网站
  • 学习Java第三十七天——黑马点评61~68
  • 网站 运营 外包 每个月多少钱h5制作易企秀
  • 基础算法:滑动窗口
  • 数据比例与尺度:如何避免让图“放大”差异
  • 《动手学深度学习v2》学习笔记 | 3.4-3.7 softmax 回归
  • Python驱动的无人机多光谱-点云融合技术在生态三维建模与碳储量、生物量、LULC估算中的全流程实战