基于mini2440触摸屏驱动

这篇博客详细解析了S3C2410触摸屏驱动的工作原理,包括注册中断、中断处理函数stylus_updown和stylus_action的功能。在触摸屏按下和抬起时,驱动如何启动和停止ADC转换,并通过中断同步坐标数据。此外,还介绍了如何实现按键点亮背光并在一段时间无按键操作后自动熄灭的机制。
摘要由CSDN通过智能技术生成

驱动路径: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_actionstylus_updown。当点击触摸屏时进入该函数,在该函数中启动ad转换,转换完成就触发中断进入stylus_actionstylus_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);   

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是怎么个玩法

24 static void touch_timer_fire(unsigned long data)   

25 {   

26     unsigned long data0;   

27     unsigned long data1;   

28     int updown;   

29   

30     data0 = ioread32(base_addr+S3C2410_ADCDAT0);   

31     data1 = ioread32(base_addr+S3C2410_ADCDAT1);   

32   

33     updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));   

34   

35     if (updown) {  //判断现在是否还按下   

36         if (count != 0) {   //采样完成,count的值我下面会讲解   

37             long tmp;   

38                                                                                         //应为是240×320,需要x,y调换一下            

39             tmp = xp;   

40             xp = yp;   

41             yp = tmp;   

42                                                                                  //stylus_action中取得是连续四次采样的结果需要处以4                   

43                         xp >>= 2;   

44                         yp >>= 2;   

45   

46             input_report_abs(dev, ABS_X, xp); //xy坐标报告   

47             input_report_abs(dev, ABS_Y, yp);   

48   

49             input_report_key(dev, BTN_TOUCH, 1);   

50             input_report_abs(dev, ABS_PRESSURE, 1);   

51             input_sync(dev);  //同步   

52         }   

53   

54         xp = 0;   //否则开始采用   

55         yp = 0;   

56         count = 0;   

57   

58         iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);   

59         iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);   

60     } else {   //是否抬起   

61         count = 0;   

62   

63         input_report_key(dev, BTN_TOUCH, 0);   

64         input_report_abs(dev, ABS_PRESSURE, 0);   

65         input_sync(dev);   

66   

67         iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);   

68         if (OwnADC) {   

69             OwnADC = 0;   

70             up(&ADC_LOCK);   

71         }   

72     }   

73 }  

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

74 static irqreturn_t stylus_action(int irq, void *dev_id)   

75 {   

76     unsigned long data0;   

77     unsigned long data1;   

78   

79     if (OwnADC) {   

80         data0 = ioread32(base_addr+S3C2410_ADCDAT0);   

81         data1 = ioread32(base_addr+S3C2410_ADCDAT1);   

82   

83         xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;   

84         yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;   

85         count++;   

86   

87         if (count < (1<<2)) {  //如果小于4,继续启动adc   

88             iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);   

89             iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);   

90         } else {  //已经采样了4次,等待1ms后调用touch_timer函数。   

91             mod_timer(&touch_timer, jiffies+1);   

92             iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);   

93         }   

94     }   

95   

96     return IRQ_HANDLED;   

97 }  

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

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

相当于又执行了touch_timer_fire0);

此时count==4my 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函数

下面是修改后的代码

98 static void touch_timer_fire(unsigned long data)   

99 {   

100  unsigned long data0;   

101  unsigned long data1;   

102  int updown;   

103  data0 = ioread32(base_addr+S3C2410_ADCDAT0);   

104  data1 = ioread32(base_addr+S3C2410_ADCDAT1);   

105  updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));   

106  if (updown)//判断是否按下   

107   {   

108   if (count != 0) //AD采集完成   

109   {   

110              xp >>= 2;   

111            yp >>= 2;   

112    input_report_abs(dev, ABS_X, xp);   

113    input_report_abs(dev, ABS_Y, yp);   

114     input_report_key(dev, BTN_TOUCH, 1);   

115    input_report_abs(dev, ABS_PRESSURE, 1);   

116    input_sync(dev);   

117    //next two lines add by Charistain_huang   

118    s3c2410_gpio_setpin(S3C2410_GPG4,1);  // light_backlight   

119    mod_timer(&backlight_control,jiffies+10*200); //2000ms后执行backlight_control------>off_backlight熄灭背光   

120       

121   }//否则开始采集   

122    xp = 0;   

123   yp = 0;   

124   count = 0;   

125   iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);   

126    iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);//启动AD转换   

127   }    

128  else //判断为抬起   

129  {   

130    count = 0;   

131    input_report_key(dev, BTN_TOUCH, 0);   

132   input_report_abs(dev, ABS_PRESSURE, 0);   

133   input_sync(dev);   

134   iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);   

135      

136  }   

137 }  

ok!!!完美的句号!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值