一、Linux输入子系统的结构:

二、触摸屏驱动代码:

  s3c_ts.c

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h> #include <asm/plat-s3c24xx/ts.h> #include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h> struct s3c_ts_regs {
unsigned long adccon;
unsigned long adctsc;
unsigned long adcdly;
unsigned long adcdat0;
unsigned long adcdat1;
unsigned long adcupdn;
}; static struct input_dev *s3c_ts_dev;
static volatile struct s3c_ts_regs *s3c_ts_regs; static struct timer_list ts_timer; static void enter_wait_pen_down_mode(void)
{
s3c_ts_regs->adctsc = 0xd3;
} static void enter_wait_pen_up_mode(void)
{
s3c_ts_regs->adctsc = 0x1d3;
} static void enter_measure_xy_mode(void)
{
s3c_ts_regs->adctsc = (<<)|(<<);
} static void start_adc(void)
{
s3c_ts_regs->adccon |= (<<);
} static int s3c_filter_ts(int x[], int y[])
{
#define ERR_LIMIT 10 int avr_x, avr_y;
int det_x, det_y; avr_x = (x[] + x[])/;
avr_y = (y[] + y[])/; det_x = (x[] > avr_x) ? (x[] - avr_x) : (avr_x - x[]);
det_y = (y[] > avr_y) ? (y[] - avr_y) : (avr_y - y[]); if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
return ; avr_x = (x[] + x[])/;
avr_y = (y[] + y[])/; det_x = (x[] > avr_x) ? (x[] - avr_x) : (avr_x - x[]);
det_y = (y[] > avr_y) ? (y[] - avr_y) : (avr_y - y[]); if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
return ; return ;
} static void s3c_ts_timer_function(unsigned long data)
{
if (s3c_ts_regs->adcdat0 & (<<))
{
/* 已经松开 */
input_report_abs(s3c_ts_dev, ABS_PRESSURE, );
input_report_key(s3c_ts_dev, BTN_TOUCH, );
input_sync(s3c_ts_dev);
enter_wait_pen_down_mode();
}
else
{
/* 测量X/Y坐标 */
enter_measure_xy_mode();
start_adc();
}
} static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
if (s3c_ts_regs->adcdat0 & (<<))
{
//printk("pen up\n");
input_report_abs(s3c_ts_dev, ABS_PRESSURE, );
input_report_key(s3c_ts_dev, BTN_TOUCH, );
input_sync(s3c_ts_dev);
enter_wait_pen_down_mode();
}
else
{
//printk("pen down\n");
//enter_wait_pen_up_mode();
enter_measure_xy_mode();
start_adc();
}
return IRQ_HANDLED;
} static irqreturn_t adc_irq(int irq, void *dev_id)
{
static int cnt = ;
static int x[], y[];
int adcdat0, adcdat1; /* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */
adcdat0 = s3c_ts_regs->adcdat0;
adcdat1 = s3c_ts_regs->adcdat1; if (s3c_ts_regs->adcdat0 & (<<))
{
/* 已经松开 */
cnt = ;
input_report_abs(s3c_ts_dev, ABS_PRESSURE, );
input_report_key(s3c_ts_dev, BTN_TOUCH, );
input_sync(s3c_ts_dev);
enter_wait_pen_down_mode();
}
else
{
// printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);
/* 优化措施3: 多次测量求平均值 */
x[cnt] = adcdat0 & 0x3ff;
y[cnt] = adcdat1 & 0x3ff;
++cnt;
if (cnt == )
{
/* 优化措施4: 软件过滤 */
if (s3c_filter_ts(x, y))
{
//printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);
input_report_abs(s3c_ts_dev, ABS_X, (x[]+x[]+x[]+x[])/);
input_report_abs(s3c_ts_dev, ABS_Y, (y[]+y[]+y[]+y[])/);
input_report_abs(s3c_ts_dev, ABS_PRESSURE, );
input_report_key(s3c_ts_dev, BTN_TOUCH, );
input_sync(s3c_ts_dev);
}
cnt = ;
enter_wait_pen_up_mode(); /* 启动定时器处理长按/滑动的情况 */
mod_timer(&ts_timer, jiffies + HZ/);
}
else
{
enter_measure_xy_mode();
start_adc();
}
} return IRQ_HANDLED;
} static int s3c_ts_init(void)
{
struct clk* clk; /* 1. 分配一个input_dev结构体 */
s3c_ts_dev = input_allocate_device(); /* 2. 设置 */
/* 2.1 能产生哪类事件 */
set_bit(EV_KEY, s3c_ts_dev->evbit);
set_bit(EV_ABS, s3c_ts_dev->evbit); /* 2.2 能产生这类事件里的哪些事件 */
set_bit(BTN_TOUCH, s3c_ts_dev->keybit); input_set_abs_params(s3c_ts_dev, ABS_X, , 0x3FF, , );
input_set_abs_params(s3c_ts_dev, ABS_Y, , 0x3FF, , );
input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, , , , ); /* 3. 注册 */
input_register_device(s3c_ts_dev); /* 4. 硬件相关的操作 */
/* 4.1 使能时钟(CLKCON[15]) */
clk = clk_get(NULL, "adc");
clk_enable(clk); /* 4.2 设置S3C2440的ADC/TS寄存器 */
s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs)); /* bit[14] : 1-A/D converter prescaler enable
* bit[13:6]: A/D converter prescaler value,
* 49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz
* bit[0]: A/D conversion starts by enable. 先设为0
*/
s3c_ts_regs->adccon = (<<)|(<<); request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL); /* 优化措施1:
* 设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断
*/
s3c_ts_regs->adcdly = 0xffff; /* 优化措施5: 使用定时器处理长按,滑动的情况
*
*/
init_timer(&ts_timer);
ts_timer.function = s3c_ts_timer_function;
add_timer(&ts_timer); enter_wait_pen_down_mode(); return ;
} static void s3c_ts_exit(void)
{
free_irq(IRQ_TC, NULL);
free_irq(IRQ_ADC, NULL);
iounmap(s3c_ts_regs);
input_unregister_device(s3c_ts_dev);
input_free_device(s3c_ts_dev);
del_timer(&ts_timer);
} module_init(s3c_ts_init);
module_exit(s3c_ts_exit); MODULE_LICENSE("GPL");

  Makefile

KERN_DIR = /work/system/linux-2.6.22.6

all:
make -C $(KERN_DIR) M=`pwd` modules clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order obj-m += s3c_ts.o

三、驱动测试:

1. make menuconfig  //去掉原来的触摸屏驱动程序
-> Device Drivers
  -> Input device support
    -> Generic input layer
      -> Touchscreens
      <>   S3C2410/S3C2440 touchscreens

2. ls /dev/input/event*    //确认当前event节点有哪些
3. insmod s3c_ts.ko  //加载触摸屏驱动模块
4. ls /dev/input/event*   //查看触摸屏节点
5. hexdump /dev/input/event0 //十六进制打印输入数据
            秒       微秒   type code    value
0000000 29a4 0000 8625 0008 0003 0000 0172 0000
0000010 29a4 0000 8631 0008 0003 0001 027c 0000
0000020 29a4 0000 8634 0008 0003 0018 0001 0000
0000030 29a4 0000 8638 0008 0001 014a 0001 0000
0000040 29a4 0000 863c 0008 0000 0000 0000 0000
0000050 29a4 0000 c85e 0008 0003 0000 0171 0000
0000060 29a4 0000 c874 0008 0003 0001 027d 0000
0000070 29a4 0000 c87b 0008 0000 0000 0000 0000
0000080 29a4 0000 ed37 0008 0003 0018 0000 0000
0000090 29a4 0000 ed48 0008 0001 014a 0000 0000
00000a0 29a4 0000 ed4a 0008 0000 0000 0000 0000

Linux学习: 触摸屏驱动的更多相关文章

  1. 基于FT5x06嵌入式Linux电容触摸屏驱动

    **************************************************************************************************** ...

  2. Linux学习: LCD驱动

    一.LCD驱动框架: 1.分配一个fb_info结构体:s3c_lcd = framebuffer_alloc(0,NULL); 2.设置fb_info(s3c_lcd): ID.固定参数.可变参数. ...

  3. Linux内核触摸屏驱动--多点触摸 【转】

      转自:http://blog.chinaunix.net/uid-24227137-id-3127126.html 简介 为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指 ...

  4. Linux下触摸屏驱动程序分析

    [摘要: 本文以linux3.5--Exynos4412仄台,剖析触摸屏驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos4412 ...

  5. i2c触摸屏驱动文件的实现

    转自:http://blog.chinaunix.net/uid-29507718-id-4314013.html Linux下I2C接口触摸屏驱动分析  分类: LINUX linux下触摸屏驱动的 ...

  6. AM335x(TQ335x)学习笔记——触摸屏驱动编写

    前面几篇文章已经通过配置DTS的方式完成了多个驱动的移植,接下来我们解决TQ335x的触摸驱动问题.由于种种原因,TQ335x的触摸屏驱动是以模块方式提供的,且Linux官方内核中也没有带该触摸屏的驱 ...

  7. linux 触摸屏驱动

    目录 linux 触摸屏驱动 输入子系统怎么写? 触摸屏事件 事件分类 事件设置 硬件配置 设计思路 完整程序 测试 ts_lib 使用 问题小结 title: linux 触摸屏驱动 tags: l ...

  8. 【Linux高级驱动】触摸屏驱动的移植

    触摸屏驱动的移植 流程 注意:看框架图 1.添加input.c组件 Device Drivers  ---> Input device support  --->  Generic inp ...

  9. linux 输入子系统之电阻式触摸屏驱动

    一.输入子系统情景回忆ING...... 在Linux中,输入子系统是由输入子系统设备驱动层.输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成.其中设备 ...

随机推荐

  1. 对nginx进行平滑升级

    1.查看服务器当前nginx版本 [root@instance-hwl9ix5l licenses]# nginx -v           #查看版本 nginx: nginx version: n ...

  2. 20165303学习基础和C语言基础调查

    20165303学习基础和C语言基础调查 技能学习心得 我认为我的乒乓球打的还不错,不能说非常好,但是基本的一些技巧都还是会的,小时候爸爸就非常爱看乒乓球比赛,有时候也带着我一起看,最开始看的时候我发 ...

  3. NexT 个性化设置

    NexT 主题添加分类页面 新建页面 在本地使用终端 cd 到 blog 文件夹下,执行如下命令: $ cd Documents/blog $ hexo new page categories 设置页 ...

  4. android -------- ConstraintLayout 约束属性(二)

    ConstraintLayout 介绍 (一) ConstraintLayout 最基本的属性控制有以下几个,即 layout_constraintXXX_toYYYOf 格式的属性,即将“View ...

  5. Misha and Palindrome Degree CodeForces - 501E (回文串计数)

    大意: 给定字符串, 求多少个区间重排后能使原串为回文串. 先特判掉特殊情况, 对于两侧已经相等的位置之间可以任意组合, 并且区间两端点至少有一个在两侧相等的位置处, 对左右两种情况分别求出即可. # ...

  6. Subordinates CodeForces - 737C (树,构造)

    大意: 求构造一棵树, 每个节点回答它的祖先个数, 求最少打错次数. 挺简单的一个构造, 祖先个数等价于节点深度, 所以只需要确定一个最大深度然后贪心即可. 需要特判一下根的深度, 再特判一下只有一个 ...

  7. 『TensorFlow』第七弹_保存&载入会话_霸王回马

    首更: 由于TensorFlow的奇怪形式,所以载入保存的是sess,把会话中当前激活的变量保存下来,所以必须保证(其他网络也要求这个)保存网络和载入网络的结构一致,且变量名称必须一致,这是caffe ...

  8. React文档(七)处理事件

    React元素处理事件和DOM元素处理事件很类似.下面是一些语法的不同之处: React事件的命名是用驼峰命名,而不是小写字母. 利用JSX你传递一个函数作为事件处理器,而不是一个字符串. 举个例子, ...

  9. 关于Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.的解决方案

    Warning: setState(...): Can only update a mounted or mounting component. This usually means you call ...

  10. python-flask-请求源码流程

    启动先执行manage.py 中的    app.run() class Flask(_PackageBoundObject): def run(self, host=None, port=None, ...