<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM-Linux驅(qū)動-觸摸屏驅(qū)動分析

          ARM-Linux驅(qū)動-觸摸屏驅(qū)動分析

          作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
          硬件平臺:FL2440

          內(nèi)核版本:2.6.28

          本文引用地址:http://www.ex-cimer.com/article/201611/318865.htm

          主機平臺:Ubuntu 11.04

          內(nèi)核版本:2.6.39

          1、下面是ADC和觸摸屏接口的模塊圖

          當(dāng)觸摸屏接口使用時,XM或YM接觸摸屏接口的地

          當(dāng)觸摸屏接口不使用時,XM或YM接模擬信號,做普通ADC使用。

          2、觸摸屏接口的幾種操作模式

          (1) 正常轉(zhuǎn)換模式

          通過設(shè)置ADCCON(adc控制寄存器)來完成初始化,并對ADCDAT0數(shù)據(jù)寄存器進行操作。

          (2) 分離XY坐標(biāo)模式

          X坐標(biāo)模式寫X坐標(biāo)轉(zhuǎn)換數(shù)據(jù)到ADCDAT0,觸摸屏接口產(chǎn)生中斷到中斷控制寄存器。Y坐標(biāo)模式寫Y坐標(biāo)轉(zhuǎn)換數(shù)據(jù)到ADCDAT1,觸摸屏接口產(chǎn)生中斷到中斷控制寄存器。兩種模

          式可以選擇一種模式工作。

          相應(yīng)的引腳連接:

          (3) 自動XY坐標(biāo)模式

          觸摸屏控制器連續(xù)的轉(zhuǎn)換X和Y的坐標(biāo),在X坐標(biāo)轉(zhuǎn)換后的值存入ADCDAT0后,自動將Y坐標(biāo)轉(zhuǎn)換后的值存入ADCDAT1,觸摸屏接口產(chǎn)生中斷到中斷控制器。

          相應(yīng)的引腳連接:

          (4) 等待中斷模式

          當(dāng)光標(biāo)被按下,觸摸屏控制器產(chǎn)生中斷IRQ_TC,當(dāng)產(chǎn)生中斷信號時,等待中斷模式必須被清除。

          引腳定義如下:

          3、下面是s3c2440觸摸屏驅(qū)動的分析

          1. //#defineCONFIG_TOUCHSCREEN_S3C2410_DEBUG
          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. #include
          16. #include
          17. #defineTRUE1//CoAsiaadded
          18. #defineFALSE0//CoAsiaadded
          19. #defineFILTER_LIMIT25//CoAsiaadded
          20. /*Forts.dev.id.version*/
          21. #defineS3C2410TSVERSION0x0101
          22. #defineTSC_SLEEP(S3C2410_ADCTSC_PULL_UP_DISABLE|S3C2410_ADCTSC_XY_PST(0))
          23. #defineWAIT4INT(x)(((x)<<8)|
          24. S3C2410_ADCTSC_YM_SEN|S3C2410_ADCTSC_YP_SEN|S3C2410_ADCTSC_XP_SEN|
          25. S3C2410_ADCTSC_XY_PST(3))
          26. #defineAUTOPST(S3C2410_ADCTSC_YM_SEN|S3C2410_ADCTSC_YP_SEN|S3C2410_ADCTSC_XP_SEN|
          27. S3C2410_ADCTSC_AUTO_PST|S3C2410_ADCTSC_XY_PST(0))
          28. #defineDEBUG_LVL"<3>"http://KERN_DEBUG
          29. staticchar*s3c2440ts_name="s3c2440TouchScreen";
          30. /*
          31. *Per-touchscreendata.
          32. */
          33. //定義s3c2440觸摸屏使用的數(shù)據(jù)結(jié)構(gòu)體
          34. structs3c2440ts{
          35. structinput_dev*dev;
          36. longxp;
          37. longyp;
          38. intcount;
          39. intshift;
          40. };
          41. staticstructs3c2440tsts;
          42. staticstructclk*adc_clock;
          43. //__iomem聲明地址空間是設(shè)備地址映射空間
          44. staticvoid__iomem*base_addr;
          45. //函數(shù)聲明
          46. staticvoidtouch_timer_fire(unsignedlongdata);
          47. staticirqreturn_ttc_irq(intirq,void*dev_id);
          48. staticirqreturn_tadc_irq(intirq,void*dev_id);
          49. staticint__inits3c2440ts_probe(structplatform_device*pdev);
          50. staticints3c2440ts_remove(structplatform_device*pdev);
          51. staticints3c2440ts_resume(structplatform_device*pdev);
          52. //定義定時器
          53. staticstructtimer_listtouch_timer=
          54. TIMER_INITIALIZER(touch_timer_fire,0,0);
          55. //IRQ_TC中斷處理函數(shù)
          56. staticirqreturn_ttc_irq(intirq,void*dev_id)
          57. {
          58. //data0,data1用于存放讀取的ADCDAT數(shù)據(jù)寄存器的值
          59. unsignedlongdata0;
          60. unsignedlongdata1;
          61. intupdown;//用于存放光標(biāo)的按下或提起的狀態(tài)
          62. //讀取ADCDAT0、ADCDAT1數(shù)據(jù)寄存器的值
          63. data0=readl(base_addr+S3C2410_ADCDAT0);
          64. data1=readl(base_addr+S3C2410_ADCDAT1);
          65. //查看數(shù)據(jù)寄存器的第15位的值
          66. updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));
          67. /*TODOweshouldnevergetaninterruptwithupdownsetwhile
          68. *thetimerisrunning,butmaybeweoughttoverifythatthe
          69. *timerisntrunninganyways.*/
          70. //如果data0和data1的第15位都是0,則updown為1,則通過函數(shù)touch_timer_fire()函數(shù)來啟動ADC轉(zhuǎn)換
          71. if(updown)
          72. touch_timer_fire(0);
          73. returnIRQ_HANDLED;
          74. }
          75. staticvoidtouch_timer_fire(unsignedlongdata)
          76. {
          77. //用于存儲數(shù)據(jù)寄存器ADCDAT0、ADCDAT1的值
          78. unsignedlongdata0;
          79. unsignedlongdata1;
          80. //用于存放光標(biāo)是否被按下
          81. intupdown;
          82. data0=readl(base_addr+S3C2410_ADCDAT0);
          83. data1=readl(base_addr+S3C2410_ADCDAT1);
          84. updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));
          85. //printk("Thenumberofupdownis%dn",updown);
          86. //如果光標(biāo)被按下,執(zhí)行
          87. if(updown)
          88. {
          89. //ts.count!=0表示ADC已經(jīng)轉(zhuǎn)換過,下面就報告事件和光標(biāo)位置數(shù)據(jù)
          90. if(ts.count!=0)
          91. {
          92. ts.xp>>=ts.shift;//這里shift為2,這里實際上是求均值,四次的和/4,這樣定位更加準(zhǔn)確
          93. ts.yp>>=ts.shift;
          94. #ifdefCONFIG_TOUCHSCREEN_S3C2410_DEBUG
          95. {
          96. structtimevaltv;
          97. do_gettimeofday(&tv);
          98. printk(DEBUG_LVL"T:%06d,X:%03ld,Y:%03ldn",(int)tv.tv_usec,ts.xp,ts.yp);
          99. }
          100. #endif
          101. /*
          102. 下面的函數(shù)位于/include/linux/input.h,作用是報告事件
          103. staticinlinevoidinput_report_abs(structinput_dev*dev,unsignedintcode,intvalue)
          104. {
          105. input_event(dev,EV_ABS,code,value);
          106. }
          107. */
          108. //報告X,Y的絕對坐標(biāo)
          109. input_report_abs(ts.dev,ABS_X,ts.xp);
          110. input_report_abs(ts.dev,ABS_Y,ts.yp);
          111. //報告事件,1代表光標(biāo)被按下
          112. input_report_key(ts.dev,BTN_TOUCH,1);
          113. //報告觸摸屏狀態(tài),1代表觸摸屏被按下
          114. input_report_abs(ts.dev,ABS_PRESSURE,1);
          115. //等待接收方的確認(rèn),用于事件的同步
          116. input_sync(ts.dev);
          117. }
          118. //現(xiàn)在光標(biāo)被按下,并且ADC轉(zhuǎn)換沒有啟動
          119. ts.xp=0;
          120. ts.yp=0;
          121. ts.count=0;
          122. //設(shè)置觸摸屏控制寄存器的值為0xdcB:11011100,設(shè)置控制寄存器上拉無效,自動轉(zhuǎn)換X,Y坐標(biāo)
          123. //printk("S3C2410_ADCTSC:0x%xn",S3C2410_ADCTSC_PULL_UP_DISABLE|AUTOPST);
          124. writel(S3C2410_ADCTSC_PULL_UP_DISABLE|AUTOPST,base_addr+S3C2410_ADCTSC);
          125. //啟動ADC轉(zhuǎn)換
          126. writel(readl(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);
          127. }
          128. else//光標(biāo)沒有被按下
          129. {
          130. ts.count=0;
          131. //報告事件及光標(biāo)的位置狀態(tài)
          132. input_report_key(ts.dev,BTN_TOUCH,0);
          133. input_report_abs(ts.dev,ABS_PRESSURE,0);
          134. //等待接收方的應(yīng)答,用于同步
          135. input_sync(ts.dev);
          136. //設(shè)置觸摸屏控制寄存器為等待中斷模式
          137. writel(WAIT4INT(0),base_addr+S3C2410_ADCTSC);
          138. }
          139. }
          140. staticirqreturn_tadc_irq(intirq,void*dev_id)
          141. {
          142. //用于存放數(shù)據(jù)寄存器的數(shù)據(jù)
          143. unsignedlongdata0;
          144. unsignedlongdata1;
          145. //讀取數(shù)據(jù),這次主要讀取的是位置數(shù)據(jù)
          146. data0=readl(base_addr+S3C2410_ADCDAT0);
          147. data1=readl(base_addr+S3C2410_ADCDAT1);
          148. ts.xp+=data0&S3C2410_ADCDAT0_XPDATA_MASK;//累加四次準(zhǔn)換結(jié)果的X坐標(biāo)和
          149. ts.yp+=data1&S3C2410_ADCDAT1_YPDATA_MASK;//累加四次準(zhǔn)換結(jié)果的Y坐標(biāo)和
          150. ts.count++;//轉(zhuǎn)換次數(shù)加一
          151. //如果轉(zhuǎn)換次數(shù)小于4
          152. if(ts.count<(1<
          153. {
          154. //再次設(shè)置觸摸屏控制寄存器上拉不使能、自動X、Y轉(zhuǎn)換模式
          155. writel(S3C2410_ADCTSC_PULL_UP_DISABLE|AUTOPST,base_addr+S3C2410_ADCTSC);
          156. //再次啟動ADC轉(zhuǎn)換
          157. writel(readl(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);
          158. }
          159. else//這時,ADC轉(zhuǎn)換四次完成,延遲一個系統(tǒng)滴答,執(zhí)行touch_timer_fire()函數(shù)
          160. {
          161. mod_timer(&touch_timer,jiffies+1);
          162. writel(WAIT4INT(1),base_addr+S3C2410_ADCTSC);
          163. }
          164. returnIRQ_HANDLED;
          165. }
          166. /*
          167. *Thefunctionsforinserting/removingusasamodule.
          168. */
          169. /*
          170. 該結(jié)構(gòu)體定義在/include/linux/platform_device.h
          171. structplatform_device{
          172. constchar*name;
          173. intid;
          174. structdevicedev;
          175. u32num_resources;
          176. structresource*resource;
          177. };
          178. */
          179. staticint__inits3c2440ts_probe(structplatform_device*pdev)
          180. {
          181. intrc;
          182. /*
          183. 下面結(jié)構(gòu)體定義在/include/mach/s3c2410_ts.h
          184. structs3c2410_ts_mach_info{
          185. intdelay;
          186. intpresc;
          187. intoversampling_shift;
          188. };
          189. */
          190. structs3c2410_ts_mach_info*info;
          191. structinput_dev*input_dev;
          192. /*
          193. void*platform_data;//Platformspecificdata,devicecoredoesnttouchit
          194. */
          195. info=(structs3c2440_ts_mach_info*)pdev->dev.platform_data;
          196. if(!info)
          197. {
          198. printk(KERN_ERR"Hm...toobad:noplatformdatafortsn");
          199. return-EINVAL;
          200. }
          201. #ifdefCONFIG_TOUCHSCREEN_S3C2410_DEBUG
          202. printk(DEBUG_LVL"Enterings3c2440ts_initn");
          203. #endif
          204. //由于ADC轉(zhuǎn)換需要時鐘,這里獲取時鐘
          205. adc_clock=clk_get(NULL,"adc");
          206. if(!adc_clock){
          207. printk(KERN_ERR"failedtogetadcclocksourcen");
          208. return-ENOENT;
          209. }
          210. clk_enable(adc_clock);//使能時鐘
          211. #ifdefCONFIG_TOUCHSCREEN_S3C2410_DEBUG
          212. printk(DEBUG_LVL"gotandenabledclockn");
          213. #endif
          214. //通過ioremap實現(xiàn)物理地址到虛擬地址的轉(zhuǎn)換
          215. base_addr=ioremap(S3C2410_PA_ADC,0x20);
          216. if(base_addr==NULL){
          217. printk(KERN_ERR"Failedtoremapregisterblockn");
          218. return-ENOMEM;
          219. }
          220. //設(shè)置ADCCON控制寄存器為0x4c40,設(shè)置預(yù)分頻有效,預(yù)分頻值為B:110001D:49
          221. //printk("ADCCONis0x%xn",S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(info->presc&0xFF));
          222. if((info->presc&0xff)>0)
          223. writel(S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
          224. base_addr+S3C2410_ADCCON);
          225. else
          226. writel(0,base_addr+S3C2410_ADCCON);
          227. /*Initialiseregisters*/
          228. /*
          229. 設(shè)置ADC開始延時寄存器ADCDLY:0x4e20
          230. */
          231. //printk("ADCDLY:0x%xn",info->delay&0xffff);
          232. if((info->delay&0xffff)>0)
          233. writel(info->delay&0xffff,base_addr+S3C2410_ADCDLY);
          234. /*
          235. 設(shè)置ADC觸摸屏控制寄存器ADC_TSC:0xd3B:11010011
          236. [8]檢測光標(biāo)按下中斷信號
          237. [7]YM輸出驅(qū)動有效(GND)
          238. [6]YP輸出驅(qū)動無效(AIN5)
          239. [5]XM輸出驅(qū)動無效(Hi-z)
          240. [4]XP輸出驅(qū)動無效(AIN7)
          241. [3]XP上拉有效
          242. [2]普通ADC轉(zhuǎn)換
          243. [0:1]等待中斷模式測量X和Y的坐標(biāo)
          244. */
          245. //printk("ADC_TSC:0x%xn",WAIT4INT(0));
          246. writel(WAIT4INT(0),base_addr+S3C2410_ADCTSC);
          247. /*Initialiseinputstuff*/
          248. memset(&ts,0,sizeof(structs3c2440ts));
          249. /*
          250. 下面的函數(shù)
          251. 為新的輸入設(shè)備分配內(nèi)存。
          252. 使用free_device()釋放沒有被注冊的函數(shù),使用input_unregister_device()解除已經(jīng)注冊的設(shè)備
          253. 定義在/drivers/input/input.c
          254. structinput_dev*input_allocate_device(void)
          255. {
          256. structinput_dev*dev;
          257. dev=kzalloc(sizeof(structinput_dev),GFP_KERNEL);
          258. if(dev){
          259. dev->dev.type=&input_dev_type;
          260. dev->dev.class=&input_class;
          261. device_initialize(&dev->dev);
          262. mutex_init(&dev->mutex);
          263. spin_lock_init(&dev->event_lock);
          264. INIT_LIST_HEAD(&dev->h_list);
          265. INIT_LIST_HEAD(&dev->node);
          266. __module_get(THIS_MODULE);
          267. }
          268. returndev;
          269. }
          270. */
          271. input_dev=input_allocate_device();
          272. if(!input_dev){
          273. printk(KERN_ERR"Unabletoallocatetheinputdevice!!n");
          274. return-ENOMEM;
          275. }
          276. //下面初始化輸入設(shè)備信息
          277. ts.dev=input_dev;
          278. ts.dev->evbit[0]=BIT_MASK(EV_SYN)|BIT_MASK(EV_KEY)|
          279. BIT_MASK(EV_ABS);
          280. ts.dev->keybit[BIT_WORD(BTN_TOUCH)]=BIT_MASK(BTN_TOUCH);
          281. input_set_abs_params(ts.dev,ABS_X,0,0x3FF,0,0);
          282. input_set_abs_params(ts.dev,ABS_Y,0,0x3FF,0,0);
          283. input_set_abs_params(ts.dev,ABS_PRESSURE,0,1,0,0);
          284. //ts.dev->private=&ts;
          285. ts.dev->name=s3c2440ts_name;
          286. ts.dev->id.bustype=BUS_RS232;
          287. ts.dev->id.vendor=0xDEAD;
          288. ts.dev->id.product=0xBEEF;
          289. ts.dev->id.version=S3C2410TSVERSION;
          290. ts.shift=info->oversampling_shift;
          291. //printk("shift:%dn",ts.shift);
          292. /*Getirqs*/
          293. //申請ADC中斷,注意,中斷類型為IRQF_SAMPLE_RANDOM|IRQF_SHARED,這樣在使用觸摸屏的時候
          294. //可以調(diào)試自己的ADC轉(zhuǎn)換驅(qū)動,中斷處理函數(shù)為adc_irq
          295. if(request_irq(IRQ_ADC,adc_irq,IRQF_SAMPLE_RANDOM|IRQF_SHARED,
          296. "s3c2440_action",ts.dev)){
          297. printk(KERN_ERR"s3c2440_ts.c:CouldnotallocatetsIRQ_ADC!n");
          298. iounmap(base_addr);
          299. return-EIO;
          300. }
          301. //申請TC中斷,中斷處理函數(shù)為tc_irq
          302. if(request_irq(IRQ_TC,tc_irq,IRQF_SAMPLE_RANDOM,
          303. "s3c2440_action",ts.dev)){
          304. printk(KERN_ERR"s3c2440_ts.c:CouldnotallocatetsIRQ_TC!n");
          305. free_irq(IRQ_ADC,ts.dev);
          306. iounmap(base_addr);
          307. return-EIO;
          308. }
          309. printk(KERN_INFO"%ssuccessfullyloadedn",s3c2440ts_name);
          310. /*Allwentok,soregistertotheinputsystem*/
          311. /*這里注冊設(shè)備
          312. 函數(shù)功能:
          313. *Thisfunctionregistersdevicewithinputcore.Thedevicemustbe
          314. *allocatedwithinput_allocate_device()andallitscapabilities
          315. *setupbeforeregistering.
          316. *Iffunctionfailsthedevicemustbefreedwithinput_free_device().
          317. *Oncedevicehasbeensuccessfullyregistereditcanbeunregistered
          318. *withinput_unregister_device();input_free_device()shouldnotbe
          319. *calledinthiscase.
          320. 函數(shù)原型如下:
          321. intinput_register_device(structinput_dev*dev)
          322. {
          323. staticatomic_tinput_no=ATOMIC_INIT(0);
          324. structinput_handler*handler;
          325. constchar*path;
          326. interror;
          327. __set_bit(EV_SYN,dev->evbit);
          328. init_timer(&dev->timer);
          329. if(!dev->rep[REP_DELAY]&&!dev->rep[REP_PERIOD]){
          330. dev->timer.data=(long)dev;
          331. dev->timer.function=input_repeat_key;
          332. dev->rep[REP_DELAY]=250;
          333. dev->rep[REP_PERIOD]=33;
          334. }
          335. if(!dev->getkeycode)
          336. dev->getkeycode=input_default_getkeycode;
          337. if(!dev->setkeycode)
          338. dev->setkeycode=input_default_setkeycode;
          339. snprintf(dev->dev.bus_id,sizeof(dev->dev.bus_id),
          340. "input%ld",(unsignedlong)atomic_inc_return(&input_no)-1);
          341. error=device_add(&dev->dev);
          342. if(error)
          343. returnerror;
          344. path=kobject_get_path(&dev->dev.kobj,GFP_KERNEL);
          345. printk(KERN_INFO"input:%sas%sn",
          346. dev->name?dev->name:"Unspecifieddevice",path?path:"N/A");
          347. kfree(path);
          348. error=mutex_lock_interruptible(&input_mutex);
          349. if(error){
          350. device_del(&dev->dev);
          351. returnerror;
          352. }
          353. list_add_tail(&dev->node,&input_dev_list);
          354. list_for_each_entry(handler,&input_handler_list,node)
          355. input_attach_handler(dev,handler);
          356. input_wakeup_procfs_readers();
          357. mutex_unlock(&input_mutex);
          358. return0;
          359. }
          360. */
          361. rc=input_register_device(ts.dev);
          362. if(rc){
          363. free_irq(IRQ_TC,ts.dev);
          364. free_irq(IRQ_ADC,ts.dev);
          365. clk_disable(adc_clock);
          366. iounmap(base_addr);
          367. return-EIO;
          368. }
          369. return0;
          370. }
          371. staticints3c2440ts_remove(structplatform_device*pdev)
          372. {
          373. disable_irq(IRQ_ADC);
          374. disable_irq(IRQ_TC);
          375. free_irq(IRQ_TC,ts.dev);
          376. free_irq(IRQ_ADC,ts.dev);
          377. if(adc_clock){
          378. clk_disable(adc_clock);
          379. clk_put(adc_clock);
          380. adc_clock=NULL;
          381. }
          382. input_unregister_device(ts.dev);
          383. iounmap(base_addr);
          384. return0;
          385. }
          386. #ifdefCONFIG_PM
          387. staticints3c2440ts_suspend(structplatform_device*pdev,pm_message_tstate)
          388. {
          389. writel(TSC_SLEEP,base_addr+S3C2410_ADCTSC);
          390. writel(readl(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_STDBM,
          391. base_addr+S3C2410_ADCCON);
          392. disable_irq(IRQ_ADC);
          393. disable_irq(IRQ_TC);
          394. clk_disable(adc_clock);
          395. return0;
          396. }
          397. staticints3c2440ts_resume(structplatform_device*pdev)
          398. {
          399. structs3c2440_ts_mach_info*info=
          400. (structs3c2440_ts_mach_info*)pdev->dev.platform_data;
          401. clk_enable(adc_clock);
          402. msleep(1);
          403. enable_irq(IRQ_ADC);
          404. enable_irq(IRQ_TC);
          405. if((info->presc&0xff)>0)
          406. writel(S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
          407. base_addr+S3C2410_ADCCON);
          408. else
          409. writel(0,base_addr+S3C2410_ADCCON);
          410. /*Initialiseregisters*/
          411. if((info->delay&0xffff)>0)
          412. writel(info->delay&0xffff,base_addr+S3C2410_ADCDLY);
          413. writel(WAIT4INT(0),base_addr+S3C2410_ADCTSC);
          414. return0;
          415. }
          416. #else
          417. #defines3c2440ts_suspendNULL
          418. #defines3c2440ts_resumeNULL
          419. #endif
          420. /*
          421. 下面是/linux/platform_device.h定義的platform_driver結(jié)構(gòu)體
          422. structplatform_driver{
          423. int(*probe)(structplatform_device*);//設(shè)備的檢測,所以需要先前的設(shè)備注冊
          424. int(*remove)(structplatform_device*);//刪除該設(shè)備
          425. void(*shutdown)(structplatform_device*);//關(guān)閉該設(shè)備
          426. int(*suspend)(structplatform_device*,pm_message_tstate);
          427. int(*suspend_late)(structplatform_device*,pm_message_tstate);
          428. int(*resume_early)(structplatform_device*);
          429. int(*resume)(structplatform_device*);
          430. structpm_ext_ops*pm;
          431. structdevice_driverdriver;//設(shè)備驅(qū)動,定義在include/linux/device.h中
          432. };
          433. 內(nèi)核提供的platform_driver結(jié)構(gòu)體的注冊函數(shù)為platform_driver_register(),該函數(shù)定義在driver/base/platform.c中
          434. */
          435. staticstructplatform_drivers3c2440ts_driver={
          436. .driver={
          437. .name="s3c2440-ts",
          438. .owner=THIS_MODULE,
          439. },
          440. .probe=s3c2440ts_probe,
          441. .remove=s3c2440ts_remove,
          442. .suspend=s3c2440ts_suspend,
          443. .resume=s3c2440ts_resume,
          444. };
          445. staticint__inits3c2440ts_init(void)
          446. {
          447. intrc;
          448. rc=platform_driver_register(&s3c2440ts_driver);
          449. if(rc<0)
          450. printk(KERN_ERR"platform_driver_registererror!n");
          451. returnrc;
          452. }
          453. staticvoid__exits3c2440ts_exit(void)
          454. {
          455. platform_driver_unregister(&s3c2440ts_driver);
          456. }
          457. module_init(s3c2440ts_init);
          458. module_exit(s3c2440ts_exit);
          459. MODULE_AUTHOR("YANMING");
          460. MODULE_DESCRIPTION("Mys3c2440touchscreendriver");
          461. MODULE_LICENSE("GPL");
          4、分析完成后對觸摸屏的工作過程就有了一個比較明確的認(rèn)識

          從觸摸屏被按下到系統(tǒng)相應(yīng)的過程如下:

          (1) 當(dāng)觸摸屏感覺到觸摸,觸發(fā)IRQ_TC中斷,然后讀取觸摸屏控制寄存器的值,判斷是否被按下,如果被按下,啟動定時器,執(zhí)行touch_timer_fire()函數(shù)啟動ADC轉(zhuǎn)換。

          (2) ADC轉(zhuǎn)換完成后,會觸發(fā)IRQ_ADC中斷,執(zhí)行相應(yīng)的中斷處理函數(shù),如果ADC轉(zhuǎn)換次數(shù)小于4,再次啟動ADC轉(zhuǎn)換;如果ADC轉(zhuǎn)換次數(shù)為4,則啟動一個系統(tǒng)滴答定時器,執(zhí)行touch_timer_fire()函數(shù)

          (3) 執(zhí)行定時器服務(wù)程序時,如果此時觸摸屏仍被按下,則上報事件和坐標(biāo)數(shù)據(jù),重復(fù)(2);如果沒有被按下,上報時間和坐標(biāo)數(shù)據(jù),將觸摸屏控制寄存器設(shè)置為中斷等待狀態(tài)
          可見,觸摸屏驅(qū)動的服務(wù)是一個封閉的循環(huán)過程。



          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();