在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

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

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

            內核版本:2.6.28

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

            主機平臺:Ubuntu 11.04

            內核版本:2.6.39

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

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

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

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

            (1) 正常轉換模式

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

            (2) 分離XY坐標模式

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

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

            相應的引腳連接:

            (3) 自動XY坐標模式

            觸摸屏控制器連續(xù)的轉換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觸摸屏使用的數(shù)據(jù)結構體
            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. //函數(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;//用于存放光標的按下或提起的狀態(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轉換
            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. //用于存放光標是否被按下
            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. //如果光標被按下,執(zhí)行
            87. if(updown)
            88. {
            89. //ts.count!=0表示ADC已經轉換過,下面就報告事件和光標位置數(shù)據(jù)
            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. 下面的函數(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的絕對坐標
            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. //報告觸摸屏狀態(tài),1代表觸摸屏被按下
            114. input_report_abs(ts.dev,ABS_PRESSURE,1);
            115. //等待接收方的確認,用于事件的同步
            116. input_sync(ts.dev);
            117. }
            118. //現(xiàn)在光標被按下,并且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. //報告事件及光標的位置狀態(tài)
            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. //用于存放數(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;//累加四次準換結果的X坐標和
            149. ts.yp+=data1&S3C2410_ADCDAT1_YPDATA_MASK;//累加四次準換結果的Y坐標和
            150. ts.count++;//轉換次數(shù)加一
            151. //如果轉換次數(shù)小于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轉換四次完成,延遲一個系統(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. 該結構體定義在/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實現(xiàn)物理地址到虛擬地址的轉換
            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. 下面的函數(shù)
            251. 為新的輸入設備分配內存。
            252. 使用free_device()釋放沒有被注冊的函數(shù),使用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轉換驅動,中斷處理函數(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. /*這里注冊設備
            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結構體
            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結構體的注冊函數(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、分析完成后對觸摸屏的工作過程就有了一個比較明確的認識

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

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

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

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



            評論


            技術專區(qū)

            關閉