Chinaunix首页 | 论坛 | 博客
  • 博客访问: 299566
  • 博文数量: 76
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 715
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-20 20:38
文章分类
文章存档

2016年(20)

2015年(56)

分类: 嵌入式

2015-06-01 19:18:39


触摸屏驱动

15年6月1日19:17:30

程序如下:

1

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11 #include

12 #include

13 #include

14 #include

15

16 #include

17

18 #include

19 #include

20

21 static struct s3c_ts_regs {

22 unsigned long adccon;

23 unsigned long adctsc;

24 unsigned long adcdly;

25 unsigned long adcdat0;

26 unsigned long adcdat1;

27 unsigned long adcupdn;

28 };

29

30 static struct input_dev *s3c_ts_dev;

31 static struct timer_list s3c_ts_timer;

32

33 static volatile struct s3c_ts_regs *s3c_ts_regs;

34

35 static void enter_wait_pen_down_mode()

36 {

37 s3c_ts_regs->adctsc = 0xd3;

38 }

39

40 static void enter_wait_pen_up_mode()

41 {

42 s3c_ts_regs->adctsc = 0x1d3;

43 }

44

45 static void enter_measure_xy_mode(void)

46 {

47 s3c_ts_regs->adctsc = (1<<2) | (1<<3);

48 }

49

50 static void start_adc(void)

51 {

52 s3c_ts_regs->adccon |= (1<<0);

53 }

54

55 static int s3c_filter_ts(int x[], int y[])

56 {

57 #define ERR_LIMIT 10

58 int avr_x, avr_y;

59 int det_x, det_y;

60

61 avr_x = (x[0] + x[1])/2;

62 avr_y = (y[0] + y[1])/2;

63

64 det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);

65 det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);

66

67 if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))

68 return 0;

69

70 avr_x = (x[1] + x[2])/2;

71 avr_y = (y[1] + y[2])/2;

72

73 det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);

74 det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);

75

76 if ((det_x > ERR_LIMIT) | (det_y > ERR_LIMIT))

77 return 0;

78

79 return 1;

80

81 }

82

83 static irqreturn_t adc_irq(int irq, void *dev_id)

84 {

85 static int cnt = 0;

86 int adcdat0, adcdat1;

87 static int x[4], y[4];

88

89 adcdat0 = s3c_ts_regs->adcdat0;

90 adcdat1 = s3c_ts_regs->adcdat1;

91

92 if (s3c_ts_regs->adcdat0 & (1<<15))

93 {

94 cnt = 0;

95 input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);

96 input_report_key(s3c_ts_dev, BTN_TOUCH, 0);

97

98 enter_wait_pen_down_mode();

99 }

100 else

101 {

102 x[cnt] = s3c_ts_regs->adcdat0 & 0x3ff;

103 y[cnt] = s3c_ts_regs->adcdat1 & 0x3ff;

104 ++cnt;

105

106 if (cnt == 4)

107 {

108 if (s3c_filter_ts(x, y))

109 {

110 //printk("x = %d, ,y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);

111 input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);

112 input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);

113 input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);

114 input_report_key(s3c_ts_dev, BTN_TOUCH, 1);

115

116 }

117

118 cnt = 0;

119 enter_wait_pen_up_mode();

120

121 mod_timer(&s3c_ts_timer, jiffies + HZ/100);

122 }

123 else

124 {

125 enter_measure_xy_mode();

126 start_adc();

127 }

128 //printk("cnt = %d, x = %d, ,y = %d\n", ++cnt, s3c_ts_regs->adcdat0 & 0x3ff, s3c_ts_regs->adcdat1 & 0x3ff);

129 }

130 return IRQ_HANDLED;

131 }

132

133 static irqreturn_t pen_down_up_irq(int irq, void *dev_id)

134 {

135 if(s3c_ts_regs->adcdat0 & (1<<15))

136 {

137 printk("pen up!\n");

138 enter_wait_pen_down_mode();

139 }

140 else

141 {

142 //printk("pen down!\n");

143 //enter_wait_pen_up_mode();

144 enter_measure_xy_mode();

145 start_adc();

146 }

147 return IRQ_HANDLED;

148 }

149

150 static void s3c_ts_timer_function (unsigned long data)

151 {

152 if(s3c_ts_regs->adcdat0 & (1<<15))

153 {

154 enter_wait_pen_down_mode();

155 }

156 else

157 {

158 enter_measure_xy_mode();

159 start_adc();

160 }

161 }

162

163 static int s3c_ts_init(void)

164 {

165 struct clk* clk;

166

167 /* 1. 分配 input_dev 结构体 */

168 s3c_ts_dev = input_allocate_device();

169

170 /* 2. 设置 */

171 /* 2.1 neng chan sheng na lei shi jian */

172 set_bit(EV_KEY, s3c_ts_dev->evbit);

173 set_bit(EV_ABS, s3c_ts_dev->evbit);

174

175 /*2.2 能产生这类事件的哪些事件 */

176 set_bit(BTN_TOUCH, s3c_ts_dev->keybit);

177

178 input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);

179 input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);

180 input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);

181

182

183 /* 3. 注册 */

184 input_register_device(s3c_ts_dev);

185

186 /* 4. 硬件相关操作 */

187 /* 4.1 使能时钟 */

188 clk = clk_get(NULL, "adc");

189 clk_enable(clk);

190

191 /* 4.2 设置 s3c2440 adc/ts 寄存器 */

192 s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));

193

194 /* bit[14]: 1. A/D converter prescaler enable

195 * bit[13:6]: 49. A/D converter prescaler value

196 * ADCCLK = PCLK/(49+1) = 50MHZ/(50) = 1MHZ.

197 * bit[0] :0. A/D conversion starts by enable.

198 */

199 s3c_ts_regs->adccon = (1<<14) | (49<<6);

200

201 request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);

202 request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

203

204 /* 优化措施1 1 */

205 s3c_ts_regs->adcdly = 0xffff;

206

207 init_timer(&s3c_ts_timer);

208 s3c_ts_timer.function = s3c_ts_timer_function;

209 add_timer(&s3c_ts_timer);

210

211 enter_wait_pen_down_mode();

212

213 return 0;

214 }

215

216 static void s3c_ts_exit()

217 {

218 free_irq(IRQ_TC, NULL);

219 free_irq(IRQ_ADC, NULL);

220 iounmap(s3c_ts_regs);

221 input_unregister_device(s3c_ts_dev);

222 input_free_device(s3c_ts_dev);

223 del_timer(&s3c_ts_timer);

224 }

225

226 module_init(s3c_ts_init);

227 module_exit(s3c_ts_exit);

228

229 MODULE_LICENSE("GPL");

230


总体上来说,从驱动角度看,没有什么难点,就是一个输入子系统,外加各种字符驱动的操作,主要难在硬件相关的操作以及一些优化思想上面。

阅读(1041) | 评论(0) | 转发(0) |
0

上一篇:LCD驱动程序

下一篇:USB驱动程序

给主人留下些什么吧!~~