触摸屏驱动(基于mini2440)

驱动路径:drivers/input/touchscreen/s3c2410_ts.c

在static int __init s3c2410ts_init(void)函数中注册了两个中断

1.if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
  "s3c2410_action", dev))

2.if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
   "s3c2410_action", dev))

中断处理函数stylus_action和stylus_updown。当点击触摸屏时进入该函数,在该函数中启动ad转换,转换完成就触发中断进入stylus_action在stylus_action中读取数据。

 

首先来看一下stylus_updown函数

 static irqreturn_t stylus_updown(int irq, void *dev_id) { unsigned long data0; unsigned long data1; int updown; if (down_trylock(&ADC_LOCK) == 0) { //判断是否adc可用,down_trylock可以用来获取信号量,不会休眠 OwnADC = 1; data0 = ioread32(base_addr+S3C2410_ADCDAT0); data1 = ioread32(base_addr+S3C2410_ADCDAT1); updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown) { //判断触摸屏是否按下 touch_timer_fire(0); //启动adc } else { OwnADC = 0; up(&ADC_LOCK); } } return IRQ_HANDLED; }

 

下面开一下touch_timer_fire是怎么个玩法

static void 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 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown) { //判断现在是否还按下 if (count != 0) { //采样完成,count的值我下面会讲解 long tmp; //应为是240×320,需要x,y调换一下 tmp = xp; xp = yp; yp = tmp; //在stylus_action中取得是连续四次采样的结果需要处以4 xp >>= 2; yp >>= 2; input_report_abs(dev, ABS_X, xp); //x,y坐标报告 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, base_addr+S3C2410_ADCTSC); iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON); } else { //是否抬起 count = 0; input_report_key(dev, BTN_TOUCH, 0); input_report_abs(dev, ABS_PRESSURE, 0); input_sync(dev); iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC); if (OwnADC) { OwnADC = 0; up(&ADC_LOCK); } } }

注意:当第一次按下时,count==0,启动ad,当转换完成将触发中断,进入stylus_action中断处理函数,好家伙来看一下哦

static irqreturn_t stylus_action(int irq, void *dev_id) { unsigned long data0; unsigned long data1; if (OwnADC) { data0 = ioread32(base_addr+S3C2410_ADCDAT0); data1 = ioread32(base_addr+S3C2410_ADCDAT1); xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK; yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK; count++; if (count < (1<<2)) { //如果小于4,继续启动adc iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON); } else { //已经采样了4次,等待1ms后调用touch_timer函数。 mod_timer(&touch_timer, jiffies+1); iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC); } } return IRQ_HANDLED; }

 接下来就得看一下touch_timer在忙些什么请看招。。。。。。。。。。。

static struct timer_list touch_timer =
  TIMER_INITIALIZER(touch_timer_fire, 0, 0); 重新初始化

相当于又执行了touch_timer_fire(0);

此时count==4,my ladygaga 现在知道怎么回事了吧。。。。

 

想一想:如果要实现按键的时候点亮背光,隔一段时间没按键自动熄灭背光该怎么搞呢?

1.首先当然是先配置一下背光的引脚了(假设与GPG4相连)

    在s3c2410_ts_connect()中添加s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_OUTP);

2. 编写背光控制函数

 static void off_backlight(unsinged long data)  //熄灭背光

  {

             s3c2410_gpio_setpin(S3C2410_GPG4,0);
 }

static struct timer_list  backlight_control=TIMER_INITIALIZER(off_backlight,0,0);

 

3.修改touch_timer_fire函数

下面是修改后的代码

 

 

static void 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 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown)//判断是否按下 { if (count != 0) //AD采集完成 { 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); //next two lines add by Charistain_huang s3c2410_gpio_setpin(S3C2410_GPG4,1); // light_backlight mod_timer(&backlight_control,jiffies+10*200); //2000ms后执行backlight_control------>off_backlight熄灭背光 //////////////////// }//否则开始采集 xp = 0; yp = 0; count = 0; iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);//启动AD转换 } else //判断为抬起 { count = 0; input_report_key(dev, BTN_TOUCH, 0); input_report_abs(dev, ABS_PRESSURE, 0); input_sync(dev); iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC); } }

 

 

ok!!!完美的句号!!

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

 

 

你可能感兴趣的:(c,timer,report,XP,input,action)