平台:S3C2440
触摸屏的硬件相关模块其实有两个:
一个是触摸屏本身,当然就是用于触摸响应。当被触摸屏被按下的时候产生电信号,当按下被松开的时候又产生电信号。
另外一个就是adc,也就是模数转换模块。当触摸屏被按下的时候会产生电信号(电压)而我们需要通过该电压得到触摸屏按下的位置,因此需要利用adc对该电压进行测量,进而得出位置相关的数据。
首先,来了解一下电阻触摸屏
电阻屏的主体其实是块透明的电阻板 , 中部为空 , 每块电阻板有两端都上连线 , 一般情况下两块电阻板互不接触.
当电阻屏上的某点被按下 , 我们需要得到该点在电阻屏上的位置 , 这时候各个接口就能发挥作用了
如果触摸屏的A点被按下,上下两块电阻屏就会被导通
这时候如果我们把XM断开,单纯把触摸屏看作电阻,那么就有如下面的第二张图,成了一个滑动电阻器
如果现在去测量XP的电压,就能知道A点的相对位置,也就是触点A的x坐标
同理能测出A点的y坐标。
对于ADC,首先能确定的是x,y对应的电压信号是从XP跟YP引脚输入的,但是XP,YP引脚除了作为电阻屏的电压输入之外还用作ADC的其他用途,因此,我们必须知道如何配置这些引脚。以下就是触摸屏和ADC的接口结构
我们只关心XP,XM,YP,YM这些引脚
把这些引脚转换成等效电路图,如图14.4,并说明工作过程(转嵌入式linux应用开发——韦东山)
(1)平时触摸屏没有被按下,如图14.5
以下寄存器设置参照s3c2440手册
对于14.5的等待中断模式,又分为两种等待模式:
等待按下(设置ADCTSC为0xd3、其中d是设置引脚,3是设置为等待中断模式),当按下触摸屏时,产生低电平,发送中断
等待松开(设置ADCTSC为0x1d3),当松开触摸屏时,产生高电平,发送中断
由于两者公用同一中断,因此需要通过其他方法判断究竟发生的是哪个中断
这里是通过读取ADCDAT0的第15位判断
触摸屏流程:
1.设置触摸屏为中断等待按下模式
2.按下触摸屏,中断发生后,就会进入中断服务程序,为了获得触点的x,y坐标,应该把触摸屏的引脚设置为可让ADC读数据的模式(设置ADCTSC的第2,3位为1)
3.然后让ADC开始测量(设置ADCCON的第0位为1)
4.ADC测量完成之后会发出中断,进入中断处理程序,在中断处理程序里面我们可以通过读取ADCDAT0和ADCDAT1的前10bit获得x、y坐标
5.如果我们需要获得长按触摸屏或者滑动触摸屏时触点的x、y坐标的话,就需要加入定时器,在函数内让ADC重新测量,并在ADC测量中断处理程序最后设置定时器执行时间,
6.另外还有防噪声的优化(设置ADCDLY值为大数,多次测量求平均,自己编写过滤函数等优化方法)
以下为调试过程中某些错误处理办法:
"523错误":
如果没按下屏幕而又去读数的话,会得到523左右的值
而如果做平均取值求坐标,假设有4个取值需要求平均值,当你在第3个坐标松开的时候,会得到x=523左右的值,因此会影响数据的精确值,
另外如果加上过滤器过滤数据的话,这个数据会被丢掉,那么重新获取的数据就也是没按下的值(523左右),因此,当得到这种值的时候应该丢弃,并且不该继续读数
adc中断处理程序无法注册:(转)
分析一下/kernel/irq/manage.c的代码就明白了,如下:
...
if (irqflags & IRQF_SHARED) && !dev_id)
return -EINVAL;
...
我想遇到申请中断返回-22的朋友多半是在申请的时候使用了IRQF_SHARED标志,却在dev_id这个参数传递了NULL吧。
解决方法非常简单,只需要把这个参数设为非空即可,因为如果IRQF_SHARED的话,中断机制需要将dev_id传递给Handler.如果实在不需要这个参数的话,就按照如下处理 就行:
static int noused;
request_irq(...., &noused);
event*文件不在/dev目录下:
在mini2440上新增的event*文件在/dev/input/下