Linux下的触摸屏驱动.doc
《Linux下的触摸屏驱动.doc》由会员分享,可在线阅读,更多相关《Linux下的触摸屏驱动.doc(13页珍藏版)》请在三一办公上搜索。
1、Linux下的触摸屏驱动一触摸屏理论概述对于触摸屏驱动,我们主要需要掌握触摸屏驱动代码和应用层测试代码。下面讲的是基于Mini2440的触摸屏驱动,现在的驱动我们都将设备和驱动分离,挂在平台设备总线上,让设备和驱动去匹配。而我们在linu2.6.32.2内核版本中的触摸屏驱动仍然没有将设备和驱动分离,这样就不存在匹配问题,这种现象其实我们并不陌生,在我们学习驱动的前期,都会研究简单字符驱动代表LED驱动,那个驱动就是把设备和驱动写在了一起。总结下,驱动和设备可以分离也可以不分离,建议分离,而本触摸屏驱动没有分离设备和驱动,有兴趣可以将设备和驱动进行分离。先说明下触摸屏的工作原理,当有人在触摸屏
2、上按下触笔时,触摸屏的四个引脚会产生不同的电压值,这样触摸屏控制器就能检测到这种变化,从而产生INT_TC中断,表示触笔按下。然后在得到CPU指示的情况下,触摸屏控制器可以根据四个引脚上产生的不同电压值进行AD转换,从而计算出X和Y坐标的数值,并在将这两个值保持到其内部寄存器后,发出INT_ADC中断,表示坐标转换已完成,从而软件就可以读取按下触笔的位置。二触摸屏驱动分析本驱动分析很有特点,我对触摸屏驱动的分析是按照整个触摸事件的执行顺序进行代码分析的,有的函数由于每次被执行完成的任务不同,所以需要多次分析。同时,我把整个触摸事件的来龙去脉也都说的很清楚了。驱动分析/driver/input/
3、touchscreen/s3c2410_ts.cstatic int _init s3c2410ts_init(void)struct input_dev *input_dev;adc_clock = clk_get(NULL, adc); /获取时钟if (!adc_clock) printk(KERN_ERR failed to get adc clock sourcen);return -ENOENT;clk_enable(adc_clock); /使能时钟base_addr=ioremap(S3C2410_PA_ADC,0x20); /物理地址转为虚拟地址if (base_addr =
4、 NULL) printk(KERN_ERR Failed to remap register blockn);return -ENOMEM;s3c2410_ts_connect(); /触摸屏端口配置/使能预分频,分频系数为0xffiowrite32(S3C2410_ADCCON_PRSCEN| S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);iowrite32(0xffff, base_addr+S3C2410_ADCDLY); /延时/检查光标按下中断信号,等待中断iowrite32(WAIT4INT(0), base_addr
5、+S3C2410_ADCTSC);input_dev = input_allocate_device(); /分配input设备if (!input_dev) printk(KERN_ERR Unable to allocate the input device !n);return -ENOMEM;dev = input_dev;/支持按键事件、坐标事件dev-evbit0 = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);dev-keybitBITS_TO_LONGS(BTN_TOUCH) = BIT(BTN_TOUCH);/对于X轴范围是0-ox3ff,
6、数据误差是0,中心平滑位置是0input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0);input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);dev-name = s3c2410ts_name;dev-id.bustype = BUS_RS232;dev-id.vendor = 0xDEAD;dev-id.product = 0xBEEF;dev-id.version = S3C2410TSVERSION;/
7、申请AD转换中断if(request_irq(IRQ_ADC,stylus_acTIon,IRQF_SHARED|IRQF_SAMPLE_RANDOM,s3c2410_acTIon, dev) printk(KERN_ERR s3c2410_ts.c: Could not allocate ts IRQ_ADC !n);iounmap(base_addr);return -EIO;/申请触摸中断if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,s3c2410_acTIon, dev) printk(KERN_ERR s3c241
8、0_ts.c: Could not allocate ts IRQ_TC !n);iounmap(base_addr);return -EIO;printk(KERN_INFO %s successfully loadedn, s3c2410ts_name);input_register_device(dev);return 0;下面是这个模块加载函数中调用的一个配置端口函数staTIc inline void s3c2410_ts_connect(void)/将触摸屏用到的四个端口配置成触摸屏模式s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG
9、12_XMON);s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);我们来分析两种情况,第一种情况,如果没有按下触摸屏驱动中定义了一个定时器static struct timer_list touch_timer =TIMER_INITIALIZER(touch_timer_fire, 0, 0);因为
10、这个定时器的期限时间设置为0,这表示当驱动加载后就会执行一次定时函数touch_timer_firestatic void touch_timer_fire(unsigned long data)unsigned long data0;unsigned long data1;int updown;data0 = ioread32(base_addr+S3C2410_ADCDAT0); /读取X坐标data1 = ioread32(base_addr+S3C2410_ADCDAT1); /读取Y坐标updown = (!(data0 /触摸屏是否被按下,如果按下updowm=1if (updow
11、n) if (count != 0) long tmp;tmp = xp;xp = yp;yp = tmp;xp = 2;yp = 2;input_report_abs(dev, ABS_X, xp);input_report_abs(dev, ABS_Y, yp);input_report_key(dev, BTN_TOUCH, 1);input_report_abs(dev, ABS_PRESSURE, 1);input_sync(dev);xp = 0;yp = 0;count = 0;iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
12、 base_addr+S3C2410_ADCTSC);iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON); else /没有被按下count = 0; /初始化count为0,表示当前AD转换没发生input_report_key(dev, BTN_TOUCH, 0); /向input子系统报告未按下input_report_abs(dev, ABS_PRESSURE, 0);input_sync(dev);iowrite32(WAIT4INT
13、(0), base_addr+S3C2410_ADCTSC); /等待按键中断if (OwnADC) /OwnADC是获取一把锁标示,在此为0OwnADC = 0;up(第二种情况,如果触摸屏被按下,首先触发触摸中断,执行stylus_updown函数static irqreturn_t stylus_updown(int irq, void *dev_id)unsigned long data0;unsigned long data1;int updown;if (down_trylock(OwnADC = 1; /表示获得锁data0 = ioread32(base_addr+S3C241
14、0_ADCDAT0); /读取X轴数据data1 = ioread32(base_addr+S3C2410_ADCDAT1); /读取Y轴数据updown = (!(data0 /触摸屏是否被按下,按下updowm=1if (updown) touch_timer_fire(0); /如果触摸屏被按下,执行touch_timer_fire else /去抖动操作,释放锁OwnADC = 0;up(return IRQ_HANDLED;下面我们第二次分析touch_timer_fire,而这次主要是因为触摸中断中调用了这个函数,假设当前触摸屏被按下后,坐标值还没进行AD转换static void
15、 touch_timer_fire(unsigned long data)unsigned long data0;unsigned long data1;int updown;data0 = ioread32(base_addr+S3C2410_ADCDAT0);data1 = ioread32(base_addr+S3C2410_ADCDAT1);updown = (!(data0 if (updown) /触摸屏被按下if (count != 0) /count是全局变量,统计AD转换次数,目前未AD转换long tmp;tmp = xp;xp = yp;yp = tmp; xp = 2;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 触摸屏 驱动
链接地址:https://www.31ppt.com/p-4842639.html