原文地址:http://blog.sina.com.cn/s/blog_56dee71a0100dw9k.html
S3C2440A内置一个带8个模拟输入通道的10位逐次逼近型(recycling type)CMOS模数转换器。在2.5MHz的模数转换时钟频率下,转换速率可达到500KSPS(Kilo Samples Per Second),并且支持片内采样保持功能和省电模式。S3C2440A还带有触摸屏接口,可以控制/选择触摸屏的XP,XM,YP,YM输入以进行X,Y位置转换。
AD转换频率 = GCLK / (p + 1)
AD转换时间 = 1 / (AD转换频率 / 5) = 5 * (p + 1) / GCLK
其中,GCLK是系统主时钟频率,一般等于50MHz;p是预分频值,在0到255之间;除以5表示每次转换需要5个时钟周期。AD转换器的设计最大时钟频率为2.5MHz,所以p最大为19;最大转换频率为0.5MHz,所以最大转换速率为0.5M个采样每秒,即500KSPS。
简单地使用AD转换器是很容易实现的,参考《基于ARM的嵌入式系统开发与实例》第12章的程序,稍作修改就可以了。主要的修改是选择模拟输入通道为AIN1,因为开发板上的可调电阻是通过这个通道连接到处理器的。程序运行后,用螺丝刀调节可调电阻,可以看到采样值的变化。
困难的是如何实现触摸屏接口。开发板配套的示例程序只是在触摸笔离开屏幕的时候输出触摸笔的位置,这显然是不满足通常的应用的。一般要求在触摸笔按下时可以判断按下位置,随后笔在屏幕上滑动时可以不断判断笔的位置,最后还要判断笔离开屏幕。
1 触摸屏接口模式
触摸屏有四种接口模式:
(1)普通转换模式
与通用AD转换的使用方式很相似。通过设置ADCCON来初始化,并以一个读和写ADCDAT0的操作完成。
(2)X/Y位置分别转换模式
又可以分成两种模式:X位置转换模式和Y位置转换模式。这两种模式下,触摸屏分别把X、Y位置转换数据写入到ADCDAT0和ADCDAT1中之后,向中断控制器发起中断请求。
(3)自动(顺序)X/Y位置转换模式
触摸屏控制器依次转换X和Y位置,把转换结果分别写入到ADCDAT0和ADCDAT1中,然后向中断控制器发起中断请求。
(4)等待中断模式
设置ADCTSC为0xD3,当触摸笔按下时,控制器发起中断请求。
注意这里的中断类型:最终向处理器发起的中断请求类型是INT_ADC,但它分为两种子中断类型,即INT_SUB_ADC表示AD采样完成;INT_SUB_TC表示触摸屏中断,即笔在屏幕上按下或者离开屏幕。触摸屏X、Y位置采样完成时发起的中断是INT_SUB_ADC,而不是INT_SUB_TC,因为X、Y位置采样也是一种AD采样动作,采样完成也就是AD转换完成。
2 定时采样
若采用普通转换模式,则需要选择某个触摸屏输入(XP/XM/YP/YM),然后在中断发生时从ADCDAT0中读取采样值,X和Y位置需要分别采样。此外,也不懂XP/XM/YP/YM是什么意思,要看触摸屏接口芯片文档才知道。
X/Y位置分别采样模式:采样自动发生,采样完成后从ADCDAT0和ADCDAT1中分别读取X或者Y位置。与普通采样模式的不同只是在于不需要选择触摸屏输入,还有就是Y位置是从ADCDAT1读取的(而不是从ADCDAT0)。
X/Y位置自动采样:采样自动发生,只是在X和Y都完成采样后才发起中断请求。
等待中断模式:当触摸笔在屏幕上按下或者离开屏幕时发起中断请求。注意这个与X、Y位置采样无关。
要实现X、Y位置判断,当然是用自动采样模式最好;而要判断触摸笔的按下与离开,则应使用等待中断模式。问题是怎么把二者结合起来。最终采用的方法是,采用等待中断模式来判断笔的按下与离开;另外设置一个采样定时器,每隔一定时间(10ms)对X、Y位置进行采样。有几点要注意:
(1)只有在笔按下状态时才进行位置采样,笔不在屏幕上时,采样是没有意义的。
(2)位置采样采用轮询模式实现,即等待采样完成;采样完成后要恢复ADCTSC,重置为等待中断模式。
(3)在普通转换模式,分别采样模式和自动采样模式下,ADCDAT0的最高位无效,不能用它来判断笔的状态。只有在触摸屏中断(INT_SUB_TC)中才可以用ADCDAT0来判断触摸笔状态。
(4)位置采样完成后要屏蔽BIT_SUB_ADC。否则,ADC持续进行采样,会以很高的频率(因为采样频率很高)发起INT_SUB_ADC中断请求,最终向处理器发起INT_ADC请求,这会严重影响处理器的工作。这也是不采用自动采样,而要用定时器定时采样的原因。
最终程序如下,其中GetCursorPos()被采样定时器(10ms)中断服务程序调用,进行一次位置采样。这里获取的X、Y位置值只是AD转换器的输出结果,一般与图形系统中的坐标值是不同的,需要通过一定的计算才能把采样值转换为坐标值,这就是触摸屏校准了。
typedef struct static MOUSE_STATE g_mouse_state; rSUBSRCPND = BIT_SUB_ADC; UART0_printf("[%3d,%3d]\n",g_mouse_state.x_pos,g_mouse_state.y_pos); if (0 == (rSUBSRCPND & BIT_SUB_TC)) if (0 == g_mouse_state.btn_state) void TouchPanelTest(void) pISR_ADC = (unsigned int)TouchPanelIsr; |