触摸屏的硬件原理Word文档格式.docx
- 文档编号:21525056
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:14
- 大小:22.12KB
触摸屏的硬件原理Word文档格式.docx
《触摸屏的硬件原理Word文档格式.docx》由会员分享,可在线阅读,更多相关《触摸屏的硬件原理Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
2.独立X/Y位置转换模式(SeparateX/YPositionConversionMode)
独立X/Y轴坐标转换模式其实包含了X轴模式和Y轴模式。
为获得X、Y坐标,需首先进行X轴的坐标转换(AUTO_PST=0,XY_PST=1),X轴的转换资料会写到ADCDAT0寄存器的XPDAT中,等待转换完成后,触摸屏控制器会产生INT_ADC中断。
然后,进行Y轴的坐标转换(AUTO_PST=0,XY_PST=2),Y轴的转换资料会写到ADCDAT1寄存器的YPDAT中,等待转换完成后,触摸屏控制器也会产生INT_ADC中断。
3.自动(连续)X/Y位置转换模式(AutoX/YPositionConversionMode)
自动(连续)X/Y位置转换模式(AUTO_PST=1,XY_PST=0)运行方式是触摸屏控制自动转换X位置和Y位置。
触摸屏控制器在ADCDAT0的XPDATA位写入X测定数据,在ADCDAT1的YPADATA位写入Y测定数据。
自动(连续)位置转换后,触摸屏控制器产生INT_ADC中断。
4.等待中断模式(WaitforInterruptMode)
当触摸屏控制器等待中断模式时,它等待触摸屏触点信号的到来。
当触点信号到来时,控制器产生INT_TC中断信号。
然后,X位置和Y位置能被适当地转换模式(独立X/Y位置转换模式或自动X/Y位置转换模式)读取到。
5.待机模式(StandbyMode)
当ADCCON寄存器的STDBM位置1时,待机模式被激活。
在这种模式下,A/D转换动作被禁止,ADCDAT0的XPDATA位和ADXDATA1的YPDAT保留以前被转换的数据。
12.2.2触摸屏设备驱动中数据结构
触摸屏设备结构体的成员与按键设备结构体的成员类似,也包含一个缓冲区,同时包括自旋锁、等待队列和fasync_struct指针,如代码清单12.12所示。
代码清单12.12触摸屏设备结构体
1typedefstruct
2{
3unsignedintpenStatus;
/*PEN_UP,PEN_DOWN,PEN_SAMPLE*/
4TS_RETbuf[MAX_TS_BUF];
/*缓冲区*/
5unsignedinthead,tail;
/*缓冲区头和尾*/
6wait_queue_head_twq;
/*等待队列*/
7spinlock_tlock;
8#ifdefUSE_ASYNC
9structfasync_struct*aq;
10#endif
11structcdevcdev;
12}TS_DEV;
触摸屏结构体中包含的TS_RET值的类型定义如代码清单12.13所示,包含X、Y坐标和状态(PEN_DOWN、PEN_UP)等信息,这个信息会在用户读取触摸信息时复制到用户空间。
代码清单12.13TS_RET结构体
1typedefstruct
3unsignedshortpressure;
//PEN_DOWN、PEN_UP
4unsignedshortx;
//x坐标
5unsignedshorty;
//y坐标
6unsignedshortpad;
7}TS_RET;
在触摸屏设备驱动中,将实现open()、release()、read()、fasync()和poll()函数,因此,其文件操作结构体定义如代码清单12.14所示。
代码清单12.14触摸屏驱动文件操作结构体
1staticstructfile_operationss3c2410_fops=
3owner:
THIS_MODULE,
4open:
s3c2410_ts_open,//打开
5read:
s3c2410_ts_read,//读坐标
6release:
7s3c2410_ts_release,
9fasync:
s3c2410_ts_fasync,//fasync()函数
11poll:
s3c2410_ts_poll,//轮询
12};
12.2.3触摸屏驱动中的硬件控制
代码清单12.15中的一组宏用于控制触摸屏和ADC进入不同的工作模式,如等待中断、X/Y位置转换等。
代码清单12.15触摸屏和ADC硬件控制
1#definewait_down_int(){ADCTSC=DOWN_INT|XP_PULL_UP_EN|\
2XP_AIN|XM_HIZ|YP_AIN|YM_GND|\
3XP_PST(WAIT_INT_MODE);
}
4#definewait_up_int(){ADCTSC=UP_INT|XP_PULL_UP_EN|XP_AIN|\
5XM_HIZ|YP_AIN|YM_GND|XP_PST(WAIT_INT_MODE);
6#definemode_x_axis(){ADCTSC=XP_EXTVLT|XM_GND|YP_AIN\
7|YM_HIZ|XP_PULL_UP_DIS|XP_PST(X_AXIS_MODE);
8#definemode_x_axis_n(){ADCTSC=XP_EXTVLT|XM_GND|YP_AIN|\
9YM_HIZ|XP_PULL_UP_DIS|XP_PST(NOP_MODE);
10#definemode_y_axis(){ADCTSC=XP_AIN|XM_HIZ|YP_EXTVLT\
11|YM_GND|XP_PULL_UP_DIS|XP_PST(Y_AXIS_MODE);
12#definestart_adc_x(){ADCCON=PRESCALE_EN|PRSCVL(49)|\
13ADC_INPUT(ADC_IN5)|ADC_START_BY_RD_EN|\
14ADC_NORMAL_MODE;
\
15ADCDAT0;
16#definestart_adc_y(){ADCCON=PRESCALE_EN|PRSCVL(49)|\
17ADC_INPUT(ADC_IN7)|ADC_START_BY_RD_EN|\
18ADC_NORMAL_MODE;
19ADCDAT1;
20#definedisable_ts_adc(){ADCCON&
=~(ADCCON_READ_START);
12.2.4触摸屏驱动模块加载和卸载函数
在触摸屏设备驱动的模块加载函数中,要完成申请设备号、添加cdev、申请中断、设置触摸屏控制引脚(YPON、YMON、XPON、XMON)等多项工作,如代码清单12.16所示。
代码清单12.16触摸屏设备驱动的模块加载函数
1staticint__inits3c2410_ts_init(void)
3intret;
4tsEvent=tsEvent_dummy;
5...//申请设备号,添加cdev
6
7/*设置XP、YM、YP和YM对应引脚*/
8set_gpio_ctrl(GPIO_YPON);
9set_gpio_ctrl(GPIO_YMON);
10set_gpio_ctrl(GPIO_XPON);
11set_gpio_ctrl(GPIO_XMON);
12
13/*使能触摸屏中断*/
14ret=request_irq(IRQ_ADC_DONE,s3c2410_isr_adc,
15SA_INTERRUPT,DEVICE_NAME,s3c2410_isr_adc);
16if(ret)
17gotoadc_failed;
18ret=request_irq(IRQ_TC,s3c2410_isr_tc,SA_INTERRUPT,
19DEVICE_NAME,s3c2410_isr_tc);
20if(ret)
21gototc_failed;
22
23/*置于等待触点中断模式*/
24wait_down_int();
25
26printk(DEVICE_NAME"
initialized\n"
);
27
28return0;
29tc_failed:
30free_irq(IRQ_ADC_DONE,s3c2410_isr_adc);
31adc_failed:
32returnret;
33}
在触摸屏设备驱动的模块卸载函数中,要完成释放设备号、删除cdev、释放中断等工作,如代码清单12.17所示。
代码清单12.17触摸屏设备驱动模块卸载函数
1staticvoid__exits3c2410_ts_exit(void)
3...//释放设备号,删除cdev
4free_irq(IRQ_ADC_DONE,s3c2410_isr_adc);
5free_irq(IRQ_TC,s3c2410_isr_tc);
6}
12.2.5触摸屏驱动中断、定时器处理程序
由12.2.1小节对触摸屏和ADC模式的分析,可知触摸屏驱动中会产生两类中断,一类是触点中断(INT-TC),一类是X/Y位置转换中断(INT-ADC)。
在前一类中断发生后,若之前处于PEN_UP状态,则应该启动X/Y位置转换。
另外,将抬起中断也放在INT-TC处理程序中,它会调用tsEvent()完成等待队列和信号的释放,如代码清单12.18所示。
代码清单12.18触摸屏设备驱动的触点/抬起中断处理程序
1staticvoids3c2410_isr_tc(intirq,void*dev_id,structpt_regs*reg)
3spin_lock_irq(&
(tsdev.lock));
4if(tsdev.penStatus==PEN_UP)
5{
6start_ts_adc();
//开始X/Y位置转换
7}
8else
9{
10tsdev.penStatus=PEN_UP;
11DPRINTK("
PENUP:
x:
%08d,y:
%08d\n"
x,y);
12wait_down_int();
//置于等待触点中断模式
13tsEvent();
14}
15spin_unlock_irq(&
16}
当X/Y位置转换中断发生后,应读取X、Y的坐标值,填入缓冲区,如代码清单12.19所示。
代码清单12.19触摸屏设备驱动X/Y位置转换中断处理程序
1staticvoids3c2410_isr_adc(intirq,void*dev_id,structpt_regs*reg)
5s3c2410_get_XY();
//读取坐标
6#ifdefHOOK_FOR_DRAG
7else
8s3c2410_get_XY();
9#endif
10spin_unlock_irq(&
11}
上述程序中调用的s3c2410_get_XY()用于获得X、Y坐标,它使用代码清单12.15的硬件操作宏实现,如代码清单12.20所示。
代码清单12.20触摸屏设备驱动中获得X、Y坐标
1staticinlinevoids3c2410_get_XY(void)
3if(adc_state==0)
4{
5adc_state=1;
6disable_ts_adc();
//禁止INT-ADC
7y=(ADCDAT0&
0x3ff);
//读取坐标值
8mode_y_axis();
9start_adc_y();
//开始y位置转换
10}
11elseif(adc_state==1)
12{
13adc_state=0;
14disable_ts_adc();
15x=(ADCDAT1&
16tsdev.penStatus=PEN_DOWN;
17DPRINTK("
PENDOWN:
18wait_up_int();
//置于等待抬起中断模式
19tsEvent();
20}
21}
代码清单12.18、12.20中调用的tsEvent最终为tsEvent_raw(),这个函数很关键,当处于PEN_DOWN状态时调用该函数,它会完成缓冲区的填充、等待队列的唤醒以及异步通知信号的释放;
否则(处于PEN_UP状态),将缓冲区头清0,也唤醒等待队列并释放信号,如代码清单12.21所示。
代码清单12.21触摸屏设备驱动的tsEvent_raw()函数
1staticvoidtsEvent_raw(void)
3if(tsdev.penStatus==PEN_DOWN)
5/*填充缓冲区*/
6BUF_HEAD.x=x;
7BUF_HEAD.y=y;
8BUF_HEAD.pressure=PEN_DOWN;
9
10#ifdefHOOK_FOR_DRAG
11ts_timer.expires=jiffies+TS_TIMER_DELAY;
12add_timer(&
ts_timer);
//启动定时器
13#endif
15else
16{
17#ifdefHOOK_FOR_DRAG
18del_timer(&
19#endif
20
21/*填充缓冲区*/
22BUF_HEAD.x=0;
23BUF_HEAD.y=0;
24BUF_HEAD.pressure=PEN_UP;
25}
26
27tsdev.head=INCBUF(tsdev.head,MAX_TS_BUF);
28wake_up_interruptible(&
(tsdev.wq));
//唤醒等待队列
29
30#ifdefUSE_ASYNC
31if(tsdev.aq)
32kill_fasync(&
(tsdev.aq),SIGIO,POLL_IN);
//异步通知
33#endif
34}
在包含了对拖动轨迹支持的情况下,定时器会被启用,周期为10ms,在每次定时器处理函数被引发时,调用start_ts_adc()开始X/Y位置转换过程,如代码清单12.22所示。
代码清单12.22触摸屏设备驱动的定时器处理函数
1#ifdefHOOK_FOR_DRAG
2staticvoidts_timer_handler(unsignedlongdata)
3{
4spin_lock_irq(&
5if(tsdev.penStatus==PEN_DOWN)
6{
7start_ts_adc();
8}
9spin_unlock_irq(&
11#endif
12.2.6触摸屏设备驱动的打开、释放函数
在触摸屏设备驱动的打开函数中,应初始化缓冲区、penStatus和定期器、等待队列及tsEvent时间处理函数指针,如代码清单12.23所示。
代码清单12.23触摸屏设备驱动的打开函数
1staticints3c2410_ts_open(structinode*inode,structfile*filp)
3tsdev.head=tsdev.tail=0;
4tsdev.penStatus=PEN_UP;
//初始化触摸屏状态为PEN_UP
5#ifdefHOOK_FOR_DRAG//如果定义了拖动钩子函数
6init_timer(&
//初始化定时器
7ts_timer.function=ts_timer_handler;
8#endif
9tsEvent=tsEvent_raw;
10init_waitqueue_head(&
//初始化等待队列
11
12return0;
13}
触摸屏设备驱动的释放函数非常简单,删除为用于拖动轨迹所使用的定时器即可,如代码清单12.24所示。
代码清单12.24触摸屏设备驱动的释放函数
1staticints3c2410_ts_release(structinode*inode,structfile*filp)
3#ifdefHOOK_FOR_DRAG
4del_timer(&
//删除定时器
5#endif
6return0;
12.2.7触摸屏设备驱动的读函数
触摸屏设备驱动的读函数实现缓冲区中信息向用户空间的复制,当缓冲区有内容时,直接复制;
否则,如果用户阻塞访问触摸屏,则进程在等待队列上睡眠,否则,立即返回-EAGAIN,如代码清单12.25所示。
代码清单12.25触摸屏设备驱动的读函数
1staticssize_ts3c2410_ts_read(structfile*filp,char*buffer,size_tcount,
2loff_t*ppos)
4TS_RETts_ret;
5
6retry:
7if(tsdev.head!
=tsdev.tail)//缓冲区有信息
8{
9intcount;
10count=tsRead(&
ts_ret);
11if(count)
12copy_to_user(buffer,(char*)&
ts_ret,count);
//复制到用户空间
13returncount;
17if(filp->
f_flags&
O_NONBLOCK)//非阻塞读
18return-EAGAIN;
19interruptible_sleep_on(&
//在等待队列上睡眠
20if(signal_pending(current))
21return-ERESTARTSYS;
22gotoretry;
23}
24
25returnsizeof(TS_RET);
26}
12.2.8触摸屏设备驱动的轮询与异步通知
在触摸屏设备驱动中,通过s3c2410_ts_poll()函数实现了轮询接口,这个函数的实现非常简单。
它将等待队列添加到poll_table,当缓冲区有数据时,返回资源可读取标志,否则返回0,如代码清单12.26所示。
代码清单12.26触摸屏设备驱动的poll()函数
1staticunsignedints3c2410_ts_poll(structfile*filp,structpoll_table_struct*wait)
3poll_wait(filp,&
(tsdev.wq),wait);
//添加等待队列到poll_table
4return(tsdev.head==tsdev.tail)?
0:
(POLLIN|POLLRDNORM);
5}
而为了实现触摸屏设备驱动对应用程序的异步通知,设备驱动中要实现s3c2410_ts_fasync()函数,这个函数与第9章给出的模板完全一样,如代码清单12.27所示。
代码清单12.27触摸屏设备驱动的fasync()函数
1#ifdefUSE_ASYNC
2staticints3c2410_ts_fasync(intfd,structfile*f
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 触摸屏 硬件 原理