触摸屏驱动(基于mini2440)

来源:互联网 发布:时时彩二星智能软件 编辑:程序博客网 时间:2024/05/06 13:26

http://blog.csdn.net/charistain_huang/article/details/6372902

驱动路径: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函数

 

[c-sharp] view plaincopy
  1. static irqreturn_t stylus_updown(int irq, void *dev_id)  
  2. {  
  3.     unsigned long data0;  
  4.     unsigned long data1;  
  5.     int updown;  
  6.   
  7.     if (down_trylock(&ADC_LOCK) == 0) {      //判断是否adc可用,down_trylock可以用来获取信号量,不会休眠  
  8.         OwnADC = 1;  
  9.         data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  10.         data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  11.   
  12.         updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  
  13.   
  14.         if (updown) {   //判断触摸屏是否按下  
  15.             touch_timer_fire(0);  //启动adc  
  16.         } else {  
  17.             OwnADC = 0;  
  18.             up(&ADC_LOCK);  
  19.         }  
  20.     }  
  21.   
  22.     return IRQ_HANDLED;  
  23. }  

 

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

[c-sharp] view plaincopy
  1. static void touch_timer_fire(unsigned long data)  
  2. {  
  3.     unsigned long data0;  
  4.     unsigned long data1;  
  5.     int updown;  
  6.   
  7.     data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  8.     data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  9.   
  10.     updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  
  11.   
  12.     if (updown) {  //判断现在是否还按下  
  13.         if (count != 0) {   //采样完成,count的值我下面会讲解  
  14.             long tmp;  
  15.                                                                                         //应为是240×320,需要x,y调换一下           
  16.             tmp = xp;  
  17.             xp = yp;  
  18.             yp = tmp;  
  19.                                                                                  //在stylus_action中取得是连续四次采样的结果需要处以4                  
  20.                         xp >>= 2;  
  21.                         yp >>= 2;  
  22.   
  23.             input_report_abs(dev, ABS_X, xp); //x,y坐标报告  
  24.             input_report_abs(dev, ABS_Y, yp);  
  25.   
  26.             input_report_key(dev, BTN_TOUCH, 1);  
  27.             input_report_abs(dev, ABS_PRESSURE, 1);  
  28.             input_sync(dev);  //同步  
  29.         }  
  30.   
  31.         xp = 0;   //否则开始采用  
  32.         yp = 0;  
  33.         count = 0;  
  34.   
  35.         iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);  
  36.         iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);  
  37.     } else {   //是否抬起  
  38.         count = 0;  
  39.   
  40.         input_report_key(dev, BTN_TOUCH, 0);  
  41.         input_report_abs(dev, ABS_PRESSURE, 0);  
  42.         input_sync(dev);  
  43.   
  44.         iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);  
  45.         if (OwnADC) {  
  46.             OwnADC = 0;  
  47.             up(&ADC_LOCK);  
  48.         }  
  49.     }  
  50. }  

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

[cpp] view plaincopy
  1. static irqreturn_t stylus_action(int irq, void *dev_id)  
  2. {  
  3.     unsigned long data0;  
  4.     unsigned long data1;  
  5.   
  6.     if (OwnADC) {  
  7.         data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  8.         data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  9.   
  10.         xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;  
  11.         yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;  
  12.         count++;  
  13.   
  14.         if (count < (1<<2)) {  //如果小于4,继续启动adc  
  15.             iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);  
  16.             iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);  
  17.         } else {  //已经采样了4次,等待1ms后调用touch_timer函数。  
  18.             mod_timer(&touch_timer, jiffies+1);  
  19.             iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);  
  20.         }  
  21.     }  
  22.   
  23.     return IRQ_HANDLED;  
  24. }  

 接下来就得看一下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函数

下面是修改后的代码

 

 

[c-sharp] view plaincopy
  1. static void touch_timer_fire(unsigned long data)  
  2. {  
  3.  unsigned long data0;  
  4.  unsigned long data1;  
  5.  int updown;  
  6.  data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  7.  data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  8.  updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  
  9.  if (updown)//判断是否按下  
  10.   {  
  11.   if (count != 0) //AD采集完成  
  12.   {  
  13.              xp >>= 2;  
  14.            yp >>= 2;  
  15.    input_report_abs(dev, ABS_X, xp);  
  16.    input_report_abs(dev, ABS_Y, yp);  
  17.     input_report_key(dev, BTN_TOUCH, 1);  
  18.    input_report_abs(dev, ABS_PRESSURE, 1);  
  19.    input_sync(dev);  
  20.    //next two lines add by Charistain_huang  
  21.    s3c2410_gpio_setpin(S3C2410_GPG4,1);  // light_backlight  
  22.    mod_timer(&backlight_control,jiffies+10*200); //2000ms后执行backlight_control------>off_backlight熄灭背光  
  23.    ////////////////////  
  24.   }//否则开始采集  
  25.    xp = 0;  
  26.   yp = 0;  
  27.   count = 0;  
  28.   iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);  
  29.    iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);//启动AD转换  
  30.   }   
  31.  else //判断为抬起  
  32.  {  
  33.    count = 0;  
  34.    input_report_key(dev, BTN_TOUCH, 0);  
  35.   input_report_abs(dev, ABS_PRESSURE, 0);  
  36.   input_sync(dev);  
  37.   iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);  
  38.     
  39.  }  
  40. }  

 

 

ok!!!完美的句号!!

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

 

0 0
原创粉丝点击