新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM-Linux驅動-觸摸屏驅動分析

        ARM-Linux驅動-觸摸屏驅動分析

        作者: 時間:2016-11-20 來源:網絡 收藏
        硬件平臺:FL2440

        內核版本:2.6.28

        本文引用地址:http://www.104case.com/article/201611/318865.htm

        主機平臺:Ubuntu 11.04

        內核版本:2.6.39

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

        當觸摸屏接口使用時,XM或YM接觸摸屏接口的地

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

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

        (1) 正常轉換模式

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

        (2) 分離XY坐標模式

        X坐標模式寫X坐標轉換數據到ADCDAT0,觸摸屏接口產生中斷到中斷控制寄存器。Y坐標模式寫Y坐標轉換數據到ADCDAT1,觸摸屏接口產生中斷到中斷控制寄存器。兩種模

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

        相應的引腳連接:

        (3) 自動XY坐標模式

        觸摸屏控制器連續的轉換X和Y的坐標,在X坐標轉換后的值存入ADCDAT0后,自動將Y坐標轉換后的值存入ADCDAT1,觸摸屏接口產生中斷到中斷控制器。

        相應的引腳連接:

        (4) 等待中斷模式

        當光標被按下,觸摸屏控制器產生中斷IRQ_TC,當產生中斷信號時,等待中斷模式必須被清除。

        引腳定義如下:

        3、下面是s3c2440觸摸屏驅動的分析

        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觸摸屏使用的數據結構體
        34. structs3c2440ts{
        35. structinput_dev*dev;
        36. longxp;
        37. longyp;
        38. intcount;
        39. intshift;
        40. };
        41. staticstructs3c2440tsts;
        42. staticstructclk*adc_clock;
        43. //__iomem聲明地址空間是設備地址映射空間
        44. staticvoid__iomem*base_addr;
        45. //函數聲明
        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中斷處理函數
        56. staticirqreturn_ttc_irq(intirq,void*dev_id)
        57. {
        58. //data0,data1用于存放讀取的ADCDAT數據寄存器的值
        59. unsignedlongdata0;
        60. unsignedlongdata1;
        61. intupdown;//用于存放光標的按下或提起的狀態
        62. //讀取ADCDAT0、ADCDAT1數據寄存器的值
        63. data0=readl(base_addr+S3C2410_ADCDAT0);
        64. data1=readl(base_addr+S3C2410_ADCDAT1);
        65. //查看數據寄存器的第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,則通過函數touch_timer_fire()函數來啟動ADC轉換
        71. if(updown)
        72. touch_timer_fire(0);
        73. returnIRQ_HANDLED;
        74. }
        75. staticvoidtouch_timer_fire(unsignedlongdata)
        76. {
        77. //用于存儲數據寄存器ADCDAT0、ADCDAT1的值
        78. unsignedlongdata0;
        79. unsignedlongdata1;
        80. //用于存放光標是否被按下
        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. //如果光標被按下,執行
        87. if(updown)
        88. {
        89. //ts.count!=0表示ADC已經轉換過,下面就報告事件和光標位置數據
        90. if(ts.count!=0)
        91. {
        92. ts.xp>>=ts.shift;//這里shift為2,這里實際上是求均值,四次的和/4,這樣定位更加準確
        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. 下面的函數位于/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的絕對坐標
        109. input_report_abs(ts.dev,ABS_X,ts.xp);
        110. input_report_abs(ts.dev,ABS_Y,ts.yp);
        111. //報告事件,1代表光標被按下
        112. input_report_key(ts.dev,BTN_TOUCH,1);
        113. //報告觸摸屏狀態,1代表觸摸屏被按下
        114. input_report_abs(ts.dev,ABS_PRESSURE,1);
        115. //等待接收方的確認,用于事件的同步
        116. input_sync(ts.dev);
        117. }
        118. //現在光標被按下,并且ADC轉換沒有啟動
        119. ts.xp=0;
        120. ts.yp=0;
        121. ts.count=0;
        122. //設置觸摸屏控制寄存器的值為0xdcB:11011100,設置控制寄存器上拉無效,自動轉換X,Y坐標
        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轉換
        126. writel(readl(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);
        127. }
        128. else//光標沒有被按下
        129. {
        130. ts.count=0;
        131. //報告事件及光標的位置狀態
        132. input_report_key(ts.dev,BTN_TOUCH,0);
        133. input_report_abs(ts.dev,ABS_PRESSURE,0);
        134. //等待接收方的應答,用于同步
        135. input_sync(ts.dev);
        136. //設置觸摸屏控制寄存器為等待中斷模式
        137. writel(WAIT4INT(0),base_addr+S3C2410_ADCTSC);
        138. }
        139. }
        140. staticirqreturn_tadc_irq(intirq,void*dev_id)
        141. {
        142. //用于存放數據寄存器的數據
        143. unsignedlongdata0;
        144. unsignedlongdata1;
        145. //讀取數據,這次主要讀取的是位置數據
        146. data0=readl(base_addr+S3C2410_ADCDAT0);
        147. data1=readl(base_addr+S3C2410_ADCDAT1);
        148. ts.xp+=data0&S3C2410_ADCDAT0_XPDATA_MASK;//累加四次準換結果的X坐標和
        149. ts.yp+=data1&S3C2410_ADCDAT1_YPDATA_MASK;//累加四次準換結果的Y坐標和
        150. ts.count++;//轉換次數加一
        151. //如果轉換次數小于4
        152. if(ts.count<(1<
        153. {
        154. //再次設置觸摸屏控制寄存器上拉不使能、自動X、Y轉換模式
        155. writel(S3C2410_ADCTSC_PULL_UP_DISABLE|AUTOPST,base_addr+S3C2410_ADCTSC);
        156. //再次啟動ADC轉換
        157. writel(readl(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);
        158. }
        159. else//這時,ADC轉換四次完成,延遲一個系統滴答,執行touch_timer_fire()函數
        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. 該結構體定義在/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. 下面結構體定義在/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轉換需要時鐘,這里獲取時鐘
        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實現物理地址到虛擬地址的轉換
        215. base_addr=ioremap(S3C2410_PA_ADC,0x20);
        216. if(base_addr==NULL){
        217. printk(KERN_ERR"Failedtoremapregisterblockn");
        218. return-ENOMEM;
        219. }
        220. //設置ADCCON控制寄存器為0x4c40,設置預分頻有效,預分頻值為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. 設置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. 設置ADC觸摸屏控制寄存器ADC_TSC:0xd3B:11010011
        236. [8]檢測光標按下中斷信號
        237. [7]YM輸出驅動有效(GND)
        238. [6]YP輸出驅動無效(AIN5)
        239. [5]XM輸出驅動無效(Hi-z)
        240. [4]XP輸出驅動無效(AIN7)
        241. [3]XP上拉有效
        242. [2]普通ADC轉換
        243. [0:1]等待中斷模式測量X和Y的坐標
        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. 下面的函數
        251. 為新的輸入設備分配內存。
        252. 使用free_device()釋放沒有被注冊的函數,使用input_unregister_device()解除已經注冊的設備
        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. //下面初始化輸入設備信息
        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. //可以調試自己的ADC轉換驅動,中斷處理函數為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中斷,中斷處理函數為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. /*這里注冊設備
        312. 函數功能:
        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. 函數原型如下:
        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結構體
        422. structplatform_driver{
        423. int(*probe)(structplatform_device*);//設備的檢測,所以需要先前的設備注冊
        424. int(*remove)(structplatform_device*);//刪除該設備
        425. void(*shutdown)(structplatform_device*);//關閉該設備
        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;//設備驅動,定義在include/linux/device.h中
        432. };
        433. 內核提供的platform_driver結構體的注冊函數為platform_driver_register(),該函數定義在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、分析完成后對觸摸屏的工作過程就有了一個比較明確的認識

        從觸摸屏被按下到系統相應的過程如下:

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

        (2) ADC轉換完成后,會觸發IRQ_ADC中斷,執行相應的中斷處理函數,如果ADC轉換次數小于4,再次啟動ADC轉換;如果ADC轉換次數為4,則啟動一個系統滴答定時器,執行touch_timer_fire()函數

        (3) 執行定時器服務程序時,如果此時觸摸屏仍被按下,則上報事件和坐標數據,重復(2);如果沒有被按下,上報時間和坐標數據,將觸摸屏控制寄存器設置為中斷等待狀態
        可見,觸摸屏驅動的服務是一個封閉的循環過程。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 冕宁县| 金乡县| 沅江市| 福鼎市| 张家界市| 厦门市| 洛川县| 佛山市| 手游| 江永县| 民丰县| 宜兴市| 驻马店市| 富宁县| 尼玛县| 平昌县| 精河县| 五家渠市| 辉南县| 额尔古纳市| 东辽县| 馆陶县| 彩票| 江孜县| 浏阳市| 涟水县| 廊坊市| 古蔺县| 霍林郭勒市| 达孜县| 黄山市| 岳普湖县| 平凉市| 长春市| 来宾市| 房产| 内黄县| 廉江市| 金塔县| 天镇县| 同仁县|