校准例程的名称是CalibrateTouchScreen(),它是一个简单的逐步操作过程,会在屏幕上向用户提供图形目标,并要求用户触摸目标,然后记录下原始的ADC读数,该读数将用于后面的原始数据转换到像素位置的调整例程。图形目标和用户提示通过使用便携式图形用户界面(PEG)图形软件API显示在屏幕上,不过这也可以通过类似的图形软件实现。
在理想情况下你只需两组(X和Y)原始数据,即在屏幕对角读取的最小和最大值。而在实际应用中,因为许多电阻触摸屏存在显著的非线性,因此如果在最小和最大值之间简单的插入位置数值会导致驱动程序非常的不精确。
非线性意味着在屏幕上的等距物理移动会导致原始数据的增量不等。更糟的情况下,即使我们只改变X轴的触摸位置,但从Y轴读取的数据也会发生很大的变化。为了演示这一现象,我用触控笔在一个典型的电阻触摸屏上从左到右移动,尽量保持Y轴位置不变,同时在图上记录Y轴的读数。你当然希望触控笔从左到右在X轴上滑动时Y轴读数能保持一定程度的恒定,但从图3可以看出完全不是这回事。
得出的结论是采用的校准点越多越好,尽量减小内插窗口的间距,才能产生可能的最佳精度。如果你能在工厂做一次校准,那么得到大量采样点并不是件难事。如果无法在工厂完成校准,那你必须确定用户需要输入多少个点才能产生足够精确的校准。本文提供的校准例程用了四个数据点,即屏幕的每个角一个。对于参考板上的VGA分辨率(640x480)显示屏幕来说,这样做的精度可达到一个或二个像素之内。对于更高的屏幕分辨率或其它触摸屏,要产生一个精确的驱动程序这些点也许过多,也许不够。做出准确判定的唯一途径只能是对具体的硬件进行大量反复测试。
在任何情况下,我的建议是尽可能多做些校准点。对用户来说,难得做一次较长时间的校准操作总比正常状态下系统无法对触摸输入做出精确响应要好。
正常操作
一旦校准过程完成,我们就可以开始正常的操作,并开始向更高层软件发送触摸事件。我把提供的每个触摸驱动程序在每种支持的RTOS环境中都作为低优先级任务加以执行。任务的入口名叫PegTouchTask,因为驱动程序需要与PEG图形软件进行交互操作。这些驱动程序修改后,可与其它图形软件甚至你自己编写的用户接口环境协同工作。在任何时候PegTouchTask总是先调用硬件配置例程,然后调用校准例程,最后进入等待触摸输入的无限循环中。 在MX1驱动程序中,无限循环通过等待前文描述的PEN_DOWN中断事件中止自身循环。当屏幕被触摸时,该任务会持续读取原始数据,将他们转换成屏幕像素坐标,并将触摸位置或状态的变化发送给更高层的软件。我把这称为"活动跟踪"模式。
LH79524驱动程序以相似的方式工作。当产生PEN_DOWN中断时,我们命令ADC序列器开始进行转换。驱动程序以20Hz的速度工作,检查位置的变化,直到屏幕不再处于被触摸的状态。
当屏幕被触摸时,我们需要对每个轴连续读取多个转换值以确定触摸位置是否稳定。如果任何两个连续读数中的增量或变化超出#defined定义的噪声窗口范围,我们就要重新开始。我们一直这样做,直到读取的多个连续值处于#defined定义的稳定范围内,此时我们可以调整该结果并向更高层软件报告更新。当屏幕不再被触摸时,我们又可以中断此任务,等待触摸输入事件的发生。
在每个转换过程的前后,驱动程序必须检查并确认屏幕仍处于被触摸状态。我们不希望向更高层的软件报告实际上是处于"开路状态"的稳定读数。我也看到过有的驱动程序在屏幕被初始触摸后会忽略掉N个读数。不过对于这两块参考电路板,我没有发现忽略掉一定数量的初始读数是有必要或有益的。 当屏幕被触摸时,驱动程序得到每个稳定的读数,并利用简单的线性插值法将原始数据转换成像素坐标。读取原始数据并将它们转换成屏幕坐标的例程名字叫GetScaleTouchPosition()。 最后部分
好了,我们终于调整好驱动程序,获得了精确、调整过的、可靠的触摸信息。这些重要的数据能用来干什么呢?如果你正在运行象PEG这样的图形用户接口系统,大部分工作到此就结束了。你只要简单的将这些触摸数据整理成消息,并将消息发送到PEG消息队列。PEG软件会对这些数据作出正确地处理。
PEG可以识别三种触摸输入事件类型,分别对应于向下触摸、向上触摸和拖曳。发送拖曳事件是可选的,但如果你希望向用户提供平滑的屏幕移动操作,那么发送拖曳事件就是必须的了。确定该发送哪种类型的消息给PEG消息队列的逻辑包含在所提供的源代码中名为SendTouchMessage()的函数中。
这里需要强调的一点是用于发送drag(PM_POINTERMOVE)消息的名为Fold()的函数的使用。这是一个方便使用的PEG API函数,可以防止用户接口的响应落后于用户的输入。例如,如果用户正在高分辨率显示器上滚动一个大窗口,那么用户接口很可能在重画滚动窗口时迟滞一段时间。在用户接口的响应能跟上时,用户一释放滚动条屏幕就应该立即停止滚动。但如果消息队列已经包含了一个PM_POINTERMOVE消息,我们只需要将这条消息更新到最新位置,而不用再发送新的消息。这样做的效果就是用户接口滚动到最新位置,跳过了对处理器来说太快的所有中间位置更新。
这就是PEG提供Fold函数的目的。它会检查这个消息类型是否已经在消息队列中,如果在,那么它只是简单的更新这条已有的消息,而不是发送全新的消息。如果你正在使用另外一种图形软件包,你也会希望实现类似的功能。
动手下载
本文主要介绍了如何为两个集成了触摸屏控制电路的主流CPU编写触摸屏驱动程序。你可以从ftp://ftp.embedded.com/pub/2005/07maxwell 网站免费下载每个驱动程序的源代码,并按照你的意图使用和修改。
提供精确可靠的触摸信息显然要花费大量的处理器时间。专门设计用于支持触摸屏输入的智能化的ADC可以显著地减轻核心CPU的负担,并有效地提高触摸屏输入系统的精度
|