為標準觸摸屏編寫驅動程序 盡管觸摸屏正在迅速普及開來,但大多數開發人員以前從來沒有開發過觸摸屏產品。本文詳細介紹了觸摸屏產品的設計步驟,指導讀者了解使觸摸屏首次工作需要的軟硬件細節。 觸摸屏如今隨處可見。工業控制系統、消費電子產品,甚至醫療設備上很多都裝備了觸摸屏輸入裝置。我們平時不經意間都會用到觸摸屏。在ATM機上取款、簽署包裹,辦理登機手續或查找電話號碼時都可能會用到觸摸屏。 本文介紹了二種較新的CPU,它們都內建了對觸摸屏輸入的支持。本文將介紹如何編寫軟件驅動程序,從而能夠使用這些微處理器配置、校準觸摸屏以及對觸摸屏輸入持續響應。最終將提供可免費下載和使用的工作代碼,作為讀者進一步設計的基礎。 觸摸屏作為輸入手段的優點和缺點 沒有一種輸入方式是十全十美的,對某些特定的應用和產品類型來說,觸摸屏不是最好的輸入手段。為了讓讀者清楚的了解觸摸屏的特性,下面先概括使用觸摸屏作為輸入手段的優點和缺點。 首先是優點:觸摸屏不可否認的具有酷的感覺,立刻就能使產品的使用變得更有樂趣。同時觸摸屏也非常直觀。當用戶想要選擇A選項時,他伸出手指碰一下A選項就可以了。這還不夠直觀嗎?連兩歲的嬰兒都知道怎樣伸手去觸摸他(或她)想要的東西。 最后要說的是,觸摸屏作為輸入裝置和系統固定在了一起。如果用戶忘記遙控器或鼠標放的位置,就會無法進行輸入。而如果具有觸摸屏的設備放在用戶前面,用戶馬上就可以用觸摸屏進行輸入。 再說缺點,觸摸屏可能會在不合適的場合下被錯誤的使用。這里我是指對安全性要求嚴格的設備,對于這些設備,如果沒有適當的預防措施,使用觸摸屏會非常危險。下面我將概括一些最明顯的潛在的問題,如果讀者想作更進一步的了解,可以參考更多的資料。 第一個問題是視差,即屏幕上看到的對象的位置與其在觸摸面板上的實際有效位置之間的差異。圖1說明了這個問題。我能想到的最佳例子是典型的“免下車”ATM機。這種ATM機不會根據汽車的高度升高或降低自己的高度,因此如果你坐在較高的SUV或卡車里,那么你就會從抬高的位置俯視顯示屏。為了保護昂貴的顯示器件免受惡意破壞,ATM機都會在用戶和顯示屏之間放置幾層強化玻璃。 觸摸屏是不能這樣保護的。如果真這樣做的話,用戶就無法進行觸摸了。因此觸摸屏放在表層上,而顯示屏放在表層下的幾層玻璃后面。這就造成了觸摸層和顯示層之間的物理隔離。如果用戶以某個角度觀看屏幕,就意味著用戶按壓觸摸屏進行選擇的位置會與用戶接口軟件預期的輸入位置之間存在一定的距離偏差。 圖1:視差(橫截面圖)。 人們能很快適應這種偏差。經過幾次嘗試和錯誤,使用者學習在觸摸屏的表面找到顯示信息的映射位置,然后觸摸到正確的位置。ATM設計師也認識到這一點,他們會采用大面積的按鍵,并盡量使它們相互遠離,因此有助于防止錯誤按鍵的誤觸發。當然,不小心按下錯誤的ATM按鍵不會使你得癌癥或使你失明。但如果這樣的失誤發生在醫療控制設備上,并且系統設計師沒有在系統內置足夠的安全預防措施,那么以上兩種后果確實都有可能發生。 通過縮短顯示層和觸摸層之間的物理距離可以盡量減少視差。在CRT或LCD前面總會有玻璃存在。最好的方法是將對觸摸敏感的電子元件嵌入到玻璃里,并且這層玻璃做得盡可能薄。這樣就減少了觸摸輸入層和顯示層之間的相隔距離。像Palm這樣的手持設備就可以采用這樣的策略,因為它們不必太擔心機械強度不夠或者遭受惡意破壞。隨著相隔距離的縮小(用戶覺得真的觸摸到了圖形元件),精度會大大提高。 第二個明顯的問題是,在用戶觸摸屏幕的過程中,觸摸屏幕的物體(觸控筆、手指)至少會遮擋屏幕上的一小部分面積,從而影響用戶的觀察。在工廠自動化應用中這種情況更容易發生,因為用戶很可能使用手指或手套而非觸控筆,即使是使用觸控筆,在屏幕上做選擇動作也會不時遮擋住一部分你給用戶展示的信息。例如,想象一下你想展示一個滑動控制條給用戶調節數值(如速度或音量),并且你將用戶選擇的數值以數字形式顯示在滑動控制條的左邊。這樣做一般工作情況會很好,但當左撇子用戶操作你的系統時,只有移開他的手指他才能看到所選的值。因此你必須在你的用戶界面設計中考慮這類因素。 觸摸屏硬件原理簡介 我們在開始編寫觸摸屏驅動程序之前,必須對硬件的工作原理有個基本的了解。許多不同的觸摸技術會把屏幕某個位置的壓力或接觸轉換成有意義的數字坐標。典型的觸摸技術包括電阻觸摸屏、聲表面波觸摸屏、紅外線觸摸屏和電容觸摸屏。如果想詳細了解這些技術,你可以登錄www.elotouch.com或[url]www.apollodisplays.com[/url]網站。 這里側重介紹電阻觸摸屏。電阻觸摸屏非常普及,你會發現許多評估板和開發套件中都集成了電阻觸摸屏。電阻觸摸屏普及的主要原因是價格便宜,而且在電氣上可以直接接入用戶的系統中。 之所以叫電阻觸摸屏,是因為它們本質上就是電阻分壓器。它們由兩個電阻薄層組成,這兩個薄層被非常薄的絕緣層隔開,絕緣層通常以塑料微粒子的形式存在。當你觸摸屏幕時,會使兩個電阻薄層變形到足以使它們之間發生電氣連接。然后由軟件通過檢測分壓器上產生的電壓計算出兩層的短接位置,并最終確定觸摸位置。 電阻觸摸屏分為幾種類型,比如"四線","五線"和"八線"。線越多,精度就越高,溫度漂移也越少,但基本的操作是一樣的。在最簡單的四線設計中,有一層稱為"X軸"的電阻層,上面加有一定的電壓,另一個稱為"Y軸"的電阻層作為接受層測量對應X軸位置的電壓值。這一過程再反過來執行一遍,即Y軸層加電,X軸層用于電壓檢測。 圖2是電阻觸摸屏的簡單等效電路。注意必須獲取二個完全獨立的讀數,即X軸位置和Y軸位置數據。這些數據在四線或五線電阻觸摸屏中是無法同時讀取的。軟件必須先讀一個軸,然后再讀另外一個軸。讀取的順序則無關緊要。 將電阻觸摸屏產生的電壓轉換成數字需要用到模數轉換器(ADC)。直到不久前這個ADC幾乎一直是主CPU的外圍器件。Burr Brown NS7843或NS7846就是這種ADC控制器。該器件為12位的模數轉換器,其內嵌的邏輯電路通過交替給一個薄層加電,再從另外一層轉換來控制觸摸屏。雖然可以使用諸如GPIO之類的信號線來完成薄層加電的切換,但該器件能夠分擔許多任務,還能提供產生觸摸或筆壓中斷的方式。 最近有幾家CPU制造商開始在主CPU中集成ADC模塊和專用的觸摸屏控制電路。在消費類設備、遠程信息通信或一些面向其它市場的產品中,LCD顯示屏和觸摸屏非常普遍,當想把CPU用于這類產品中時,在CPU中集成ADC和觸摸屏控制電路的做法會非常有意義。 基于兩種CPU的參考板 本文設計兩種集成了觸摸屏控制功能的CPU的參考板。這二種CPU都基于ARM處理器架構。 第一塊板是飛思卡爾的MX9823ADS評估板,采用了飛思卡爾的MC9328MX1處理器。該評估板可以直接從飛思卡爾的分銷商處定購。評估套件包括QVGA(240x320)彩色LCD和觸摸屏。 第二塊板采用了夏普LH79524 ARM處理器。這塊夏普的參考板以及集成的顯示和觸摸套件都可以從LogicPD公司處定購。有幾種可更換的顯示套件供選擇,分辨率范圍從QVGA到800x600像素不等。 本文中不提供每個驅動程序的詳細代碼,而是介紹驅動程序的設計和流程,并重點介紹其中的重要部分。總的來看,軟件提供的功能完成以下這些步驟: 1. 配置控制器硬件 2. 判斷屏幕是否被觸摸 3. 獲得穩定的、去抖動的位置測量數據 4. 校準觸摸屏 5. 將觸摸狀態和位置變化信息發送給更高層的圖形軟件 下面開始詳細介紹每個步驟。 硬件配置 觸摸驅動程序要做的第一件事是配置硬件。對這些集成控制器來說,這意味著通過向映射到存儲器的寄存器中寫入數據將控制器配置成某個確定狀態。這一過程是由每個驅動程序中的TouchConfigureHardware()函數完成的。 為了配置硬件,需要事先做好某些決定。例如,驅動程序應該使用中斷驅動嗎?為了獲得能夠響應并且精確的觸摸位置信息需要什么樣的轉換速率?讓我們看看做出這些決定的具體過程吧。 圖2:觸摸屏電路簡單等效電路。 關于觸摸驅動程序是否應該使用中斷驅動,事實上在范例的驅動程序中用的就是中斷驅動方式。坦率地講,我之所以這樣做是因為使用中斷很有趣。千萬不要由這個例子推斷出采用中斷永遠是最好或最正確的設計方式,也不要聽信別人說不采用中斷驅動方式的觸摸驅動程序就是"錯誤的"。 之所以這樣說只是因為"輪詢"對嵌入式系統程序員來說似乎變成了貶義詞。我曾經問過一位客戶,他的輸入設備采用的是輪詢還是中斷服務方式。回答是"這是嵌入式系統,我們不做任何輪詢"。我當時感覺問這個問題時我就像一個傻瓜,但進一步探討后發現查詢其實也是一種合理且值得考慮的方式。如果使用的是RTOS,并且所有任務經常為了等待某類外部事件而被中斷,處理器經常處于空閑的循環狀態,沒有什么有意義的事做。這種情況下使用空閑任務查詢觸摸屏上的輸入也許是更好的設計方式。根據你的總體系統需求,查詢也可能是一個值得考慮的合理的設計方式。 配置中斷的方法因具體操作系統而異。讀者會發現對于每一個支持的RTOS都有被(#ifdef)限定的代碼段。在所有情況下驅動程序實際會使用二種不同的中斷: 1 當屏幕被初次觸摸時喚醒主機的中斷,稱為PEN_DOWN中斷 2 當完成一組模數數據轉換時的第二種中斷信號 后文會詳細介紹這些中斷和它們產生的過程。 接下來的問題是我們希望以多快的速度從ADC接收采樣輸入讀數。采樣速度會影響我們需要如何配置時鐘來驅動觸摸屏和ADC。我們希望時鐘有足夠快的速度來提供可響應的輸入和實現精確的跟蹤,但也不要太快,以至于影響轉換精度,或讓系統消耗超過所需的功率。 根據我的經驗,觸摸屏至少需要以20Hz或50ms間隔的速度向更高層軟件提供位置更新數據,只要高層軟件跟得上,速度越快越好,我們不太擔心功耗問題。如果觸摸輸入響應比這慢得多,那么在用戶的觸摸輸入和顯示屏上可觀察到的響應之間會出現明顯和煩人的遲滯現象。 20Hz的更新速度聽起來并不是太有挑戰性,但提供20Hz的更新速度實際上要求采樣速度接近200Hz,具體數值取決于我們在確定輸入穩定之前準備采用多少讀數。為了去抖動和對觸摸輸入位置值進行平均,我們需要進行過采樣。電阻觸摸屏,特別是便宜的那種,一般會有很大的噪聲和抖動。 在向更高層軟件發送位置更新數據之前,驅動程序需要多次采樣每個軸上的輸入。我們提供的驅動程序默認情況下將以最少200Hz(5ms)的采樣速率配置各自處理器上的ADC時鐘。這樣就能讓驅動程序對輸入原始數據進行充分的去抖動和過濾,并仍能向高層用戶接口軟件提供20Hz的實際位置更新速率。 飛思卡爾i.MX處理器中的觸摸控制器模塊叫做模擬信號處理器(ASP),i.MX處理器提供兩個由內核CPU時鐘分頻得到的外設時鐘。輸入ASP模塊端口的是PERCLK2(外設時鐘2),它經過再分頻產生ASP所需的最終輸入時鐘。需要注意的是,PERCLK2除了驅動ASP模塊外,還驅動包括內部LCD控制器在內的其它子模塊,因此觸摸驅動程序無法只是為了更好的配合觸摸采樣而對PERCLK2進行編程。PERCLK2被編程為所有附屬外設所要求的最高速率(在大多數情況下是LCD控制器),然后通過分頻產生速度較慢的外設所需的時鐘。MC9328MX1參考手冊中包含一份表格,該表格定義了達到200Hz數據輸出速率所需的時鐘編程值。 夏普LH79524在硬件配置時要求對幾個GPIO引腳進行編程以便給這些引腳分配ADC功能,并要求編程和激活ADC時鐘,還要對ADC序列器編程。 LH79524 ADC本身是一個令人稱奇的電路系統,能夠實現完全可編程的狀態機和序列器。該ADC無需核心CPU的任何干預就可以通過編程完成:驅動一個觸摸層;延時;進行測量;驅動另一層;延時;進行測量等操作。理解如何對LH79524 ADC序列器控制單元編程可能是一個挑戰,不過利用夏普(www.sharpsma.com)公司提供的應用指南可以使這項工作簡單很多。本文提供的驅動程序完全符合該應用指南對如何配置夏普ADC序列控制器提出的建議。 圖3:X軸移動時Y軸上的偏移。 屏幕被觸摸到了嗎? 一旦完成了基本的硬件設置,接下來就需要一種可靠的方法判斷屏幕是否被觸摸了。如果用戶沒有觸摸屏幕,那么運行ADC獲得轉換后的讀數毫無意義。上述兩個控制器都提供了屏幕是否被觸摸的檢測機制,并且當觸摸事件發生時還可選擇是否中斷主處理器。判斷屏幕是否被觸摸的驅動程序的函數名叫WaitForTouchState()。 當控制器處于觸摸檢測模式時,Y軸觸摸層通過一個上拉電阻上拉到高電平,X軸觸摸層則連接到地。當用戶觸摸屏幕的任何地方時,這兩層就發生短接,Y軸層被拉到低電平。該事件可以在驅動程序內部連接到名為PEN_OWN IRQ的中斷發生機制。 在正常工作期間,當觸摸事件發生時驅動程序利用PEN_DOWN IRQ喚醒觸摸驅動任務。這樣做可以讓驅動程序在屏幕沒有被觸摸時中斷自己的執行,而不消耗任何CPU資源,而一旦用戶觸摸屏幕,驅動程序就被喚醒并進入轉換模式。我們也可以在轉換模式沒被激活時停止(disable)ADC時鐘來節省功耗。 在校準和主動采樣期間,驅動程序使用與上述基本相同的機制檢測屏幕是否被觸摸;不過在這些模式下驅動程序會屏蔽實際的中斷,并通過人工方式簡單的檢查觸摸狀態。對于飛思卡爾的處理器,這時要求把控制器編程到觸摸檢測模式,并檢查PEN_DOWN IRQ的數據位。對于夏普的處理器,觸摸檢測內建在ADC命令序列中,不需要額外的步驟。 讀取觸摸數據 在校準和正常操作期間,我們需要讀取X和Y軸的原始數據并去抖動,然后確定屏幕被觸摸時是否有穩定的讀數。該過程在兩個驅動程序中都叫TouchScan()。該過程的要點是: 1. 檢查屏幕是否被觸摸; 2. 采集每個軸上的多個原始讀數用于以后的過濾; 3. 檢查屏幕是否仍在被觸摸。 在執行模數轉換時,兩個控制器都提供了由編程產生延遲的方法,以在給觸摸層加電和開始實際的模數轉換之間插入一段時延。飛思卡爾把這段時延稱作數據建立計數(DSCNT),在兩層切換后會有很多個ASP輸入時鐘長度的延時。夏普把這段時延稱為預充時延。 兩種CPU都需要這種時延,因為電阻觸摸面板是二塊由薄絕緣層隔離的大面積導體,正好形成一個電容。當從將要執行模數轉換的層切換到正在加電的層時,需要一定的延時才能保證電容達到穩定狀態。 對于飛思卡爾的i.MX1處理器來說,一旦我們啟動轉換過程,那么由ADC產生的數據將被保存在一個16位寬x12個條目深度的FIFO中。ADC產生9位無符號數據,因此每個16位條目的高7位將被忽略掉。這意味著這種觸摸控制器的全部數據范圍從0到511,不過實際上沒有ADC或電阻觸摸屏會產生接近這個極限值的數據。 我們可以通過編程讓處理器在FIFO存有任何有效數據時就產生中斷,或在輸入FIFO裝滿時產生中斷。由于我們通常會做多次讀取,因此驅動程序一般會在FIFO裝滿時產生中斷。當該中斷產生時,會有12個原始的模數轉換數據等待處理,分別對應于X軸的6次讀數和Y軸的6次讀數。 夏普LH79524處理器允許在產生中斷前通過編程完成精確的步驟序列。在執行每個步驟時,結果同樣會保存在輸入FIFO中,等待驅動程序軟件的讀取。結果是以16位數值進行保存。每個結果的高10位是模數轉換值,最低4位是序列索引。10位轉換結果意味著這種觸摸控制器的最大數值范圍是0到1023,當然你永遠也不會觀察到接近極限值的結果。 一旦序列器控制字在LH79524上被編好程,驅動程序獲取原始讀數所需要做的就是命令序列器執行。當EOS(序列結束)中斷產生時,我們獲得的結果就可以用于采集和檢查了。序列器可以被配置為當屏幕被觸摸時自動觸發、根據軟件命令觸發或連續觸發三種模式。 要注意原始轉換器讀數中經常會有一些噪聲和偏差,這是正常的。你只有緊緊壓住電阻觸摸屏才能得到兩個連續的讀數,并取得一致的9位或10位原始數據。然而你會發現當觸控筆或手指按上或離開觸摸屏時,讀數的變化要比你保持穩定壓力時大得多。要記住用戶是以機械的方式連通二個平面電阻-觸摸層。當用戶按壓和釋放觸摸屏時,在很短的一段時間內兩層之間的電氣連接處于臨界狀態。我們需要丟棄這些讀數直到系統穩定下來,否則我們提交的觸摸位置讀數會產生大幅跳躍,導致更高層的軟件無法進行合適的操作。 這里不可避免要進行折衷考慮。如果我們要求較窄的穩定窗口,那么驅動程序將無法跟蹤快速的"拖曳"操作。對于在簽名輸入期間發生的滑動或筆劃跟蹤事件來說快速拖曳是非常重要的。如果我們加寬穩定窗口,我們就可能面臨著風險,這些風險包括接收到不精確的觸摸數據和上文描述過的處于臨界狀態的層連接結果。因此需要通過實驗來確定適合自己系統的最佳值。智能化的觸摸控制器同樣允許你通過軟件命令調整這些參數。 每個樣值所需的讀取次數、連續讀取間允許的偏差以及采樣速率是每個驅動程序的全部可編程參數。可以通過#defines調整這些參數以便在你的系統上產生最佳結果。智能化的外部觸摸控制器一般會以很快的速度讀取數十或數百個數據用以改善精度。由于我們是用核心CPU完成這種過濾,因此我們需要確定有多少時間可以合理地分配給觸摸采樣任務。嵌入式系統包含折衷,你的任務就是想出最佳的折衷辦法,以產生能使用戶滿意的系統。 出于游戲目的,我喜歡測試日常生活中所遇到的商業觸摸系統。下一次當你使用觸摸屏進行購物簽名或包裹簽名時,你可以嘗試快速大范圍波浪形地移動觸控筆,然后觀察結果,查看屏幕跟蹤你移動的程度如何。如果你能看到漂亮光滑的跟蹤軌跡,你就知道驅動程序的采樣速率相當快,可能在200Hz以上。經常你會觀察到移動軌跡變成了一條直線(慢速采樣)或完全丟失(由于數值改變過大而被拒絕輸入)。當你在零售商店進行這種小測試的時候千萬不要大呼小叫,否則人們會用異樣的目光看你。正常人是不會理解什么東西會使工程師那么激動。 觸摸屏的校準 到此我們已經介紹了驅動程序所支持的全部功能,這是我們進入下一步之前必須完成的繁瑣工作。既然各種功能都已就緒,可以讓用戶實際觸摸屏幕了。電阻觸摸屏需要校準。我們需要一些參考值,以便我們能夠將接收到的原始模數轉換值轉換成高層軟件所需的屏幕像素坐標。理想情況下校準程序只要在產品初次加電測試過程中運行一次就可以了,參考值被存儲在非易失性存儲器中。我已經安排好讓觸摸驅動程序在一啟動時就運行校準程序,但要記住,你要把參考值保存起來,以免讓用戶在以后的加電啟動期間再做校準。不過無論如何你仍然需要向用戶提供一種進入校準例程的途徑,從而在由于溫度漂移或其它因素造成校準不準確時進行重新校準。 校準例程的名稱是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的負擔,并有效地提高觸摸屏輸入系統的精度。 |