您的位置 首页 方案

ARM-Linux驱动-触摸屏驱动剖析

硬件平台:FL2440内核版本:2.6.28主机平台:Ubuntu11.04内核版本:2.6.391、下面是ADC和触摸屏接口的模块图当触摸屏接口使用时,XM或YM…

硬件渠道:FL2440

内核版别:2.6.28

主机渠道: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>“//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%d\n”,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:%03ld\n”,(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%x\n”,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:noplatformdataforts\n”);
  199. return-EINVAL;
  200. }
  201. #ifdefCONFIG_TOUCHSCREEN_S3C2410_DEBUG
  202. printk(DEBUG_LVL”Enterings3c2440ts_init\n”);
  203. #endif
  204. //我们ADC转化需求时钟,这儿获取时钟
  205. adc_clock=clk_get(NULL,”adc”);
  206. if(!adc_clock){
  207. printk(KERN_ERR”failedtogetadcclocksource\n”);
  208. return-ENOENT;
  209. }
  210. clk_enable(adc_clock);//使能时钟
  211. #ifdefCONFIG_TOUCHSCREEN_S3C2410_DEBUG
  212. printk(DEBUG_LVL”gotandenabledclock\n”);
  213. #endif
  214. //经过ioremap完成物理地址到虚拟地址的转化
  215. base_addr=ioremap(S3C2410_PA_ADC,0x20);
  216. if(base_addr==NULL){
  217. printk(KERN_ERR”Failedtoremapregisterblock\n”);
  218. return-ENOMEM;
  219. }
  220. //设置ADCCON操控寄存器为0x4c40,设置预分频有用,预分频值为B:110001D:49
  221. //printk(“ADCCONis0x%x\n”,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%x\n”,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%x\n”,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:%d\n”,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”%ssuccessfullyloaded\n”,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%s\n”,
  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_L%&&&&&%ENSE(“GPL”);

4、剖析完结后对角度屏的作业进程就有了一个比较清晰的知道

从角度屏被按下到体系相应的进程如下:

(1) 当角度屏感觉到角度,触发IRQ_TC中止,然后读取角度屏操控寄存器的值,判别是否被按下,假如被按下,发动定时器,碑文touch_timer_fire()函数发动ADC转化。

(2) ADC转化完结后,会触发IRQ_ADC中止,碑文相应的中止处理函数,假如ADC转化次数小于4,再次发动ADC转化;假如ADC转化次数为4,则发动一个体系滴答定时器,碑文touch_timer_fire()函数

(3) 碑文定时器服务程序时,假如此刻角度屏仍被按下,则上报事情和坐标数据,重复(2);假如没有被按下,上报时刻和坐标数据,将角度屏操控寄存器设置为中止等候状况
可见,角度屏驱动的服务是一个关闭的循环进程。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/264334.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部