原文地址: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; |