觸摸屏又稱觸控面板,它是一種把觸摸位置轉化成坐標數據的輸入設備觸摸屏可以分為電阻式觸摸屏和電容式觸摸屏。這里用電阻式觸摸屏來實現觸摸控制。
電阻式觸摸屏結構如下圖所示,主要由表面硬涂層、兩個 ITO 層、間隔點以及玻璃底層構成,這些結構層都是透明的,整個觸摸屏覆蓋在液晶面板上,透過觸摸屏可看到液晶面板。表面涂層起到保護作用,玻璃底層起承載的作用,而兩個 ITO 層是觸摸屏的關鍵結構,它們是涂有銦錫金屬氧化物的導電層。兩個 ITO 層之間使用間隔點使兩層分開,當觸摸屏表面受到壓力時,表面彎曲使得上層 ITO 與下層 ITO 接觸,在觸點處連通電路。
兩個 ITO 涂層的兩端分別引出 X-、X+、Y-、Y+四個電極,通過這些電極,外部電路向這兩個涂層可檢測電壓。
當觸摸屏被按下時,兩個 ITO 層相互接觸,從觸點處把 ITO 層分為兩個電阻,且由于ITO 層均勻導電,兩個電阻的大小與觸點離兩電極的距離成比例關系,利用這個特性,可通過以下過程來檢測坐標,這也正是電阻觸摸屏名稱的由來。
計算 X 坐標時,在 X+電極施加驅動電壓 V ref ,X-極接地,所以 X+與 X-處形成了勻強電場,而觸點處的電壓通過 Y+電極采集得到,由于 ITO 層均勻導電,觸點電壓與 V ref之比等于觸點 X坐標與屏寬度之比,從而:
x =Vy+/ V ref *Width
計算 Y 坐標時,在 Y+電極施加驅動電壓 V ref ,Y-極接地,所以 Y+與 Y-處形成了勻強電場,而觸點處的電壓通過 X+電極采集得到,由于 ITO 層均勻導電,觸點電壓與 V ref之比等于觸點 Y坐標與屏高度之比,從而:
y =Vy+/ V ref *Height
這里采用XPT2046芯片作為觸摸控制芯片,XPT2046芯片控制4線電阻觸摸屏,STM32與XPT2046采用SPI通訊獲取采集得到的電壓,然后轉換成坐標。
XPT2046原理框
XPT2046 典型應用圖
XPT2046 是一種典型的逐次逼近型模數轉換器(SAR ADC),包含了采樣/保持、模數轉換、串口數據輸出等功能。同時芯片集成有一個 2.5V的內部參考電壓源、溫度檢測電路,工作時使用外部時鐘。XPT2046 可以單電源供電,電源電壓范圍為 2.7V~5.5V。參考電壓值直接決定ADC的輸入范圍,參考電壓可以使用內部參考電壓,也可以從外部直接輸入1V~VCC范圍內的參考電壓(要求外部參考電壓源輸出阻抗低)。X、Y、Z、VBAT、Temp和AUX模擬信號經過片內的控制寄存器選擇后進入ADC,ADC可以配置為單端或差分模式。選擇VBAT 、Temp和AUX時可以配置為單端模式;作為觸摸屏應用時,可以配置為差分模式,這可有效消除由于驅動開關的寄生電阻及外部的干擾帶來的測量誤差,提高轉換準確度。
XPT2046 的內部 2.5V 參考電壓源可通過控制位 PD1進行關閉或者打開。一般地,內部參考電壓只用于單端模式下 Vbatt、Temp 和 AUX 輸入測量。使用差分模式,觸摸屏可以獲得最佳性能。
外部參考電壓
+REF 和-REF之間的電壓差決定了模擬輸入的電壓范圍。XPT2046 的參考電壓輸入范圍為 1V~ VCC。參考電壓越低,則 ADC 輸出的二進制數據結果每一個數字位所代表的模擬電壓也越低。
在 12 位工作方式下,數據結果的最低位所代表的模擬電壓為 VREF/4096,其余位依此類推。因此,參考電壓越低,干擾引入的誤差會越大,此時要求盡可能使用低噪聲、低波動的參考電壓源;在設計電路板時,盡可能減少干擾,輸入的信號噪音也不能太高,否則會直接影響轉換精度。
單端工作模式
SER/ DFR 置為高電平時,XPT2046 工作在為單端模式,單端工作模式的應用原理如下圖所示。
單端模式簡單,在采樣過程完成后,轉換過程中可以關閉驅動開關,降低功耗。但這種模式的缺點是精度直接受參考電壓源的精度限制,同時由于內部驅動開關的導通電阻存在,導通電阻與觸摸屏電阻的分壓作用,也會帶來測量誤差。
差分工作模式
SER/ DFR 置為低電平時,XPT2046 為差分工作模式,如下圖所示。
差分模式的優點是:+REF 和-REF 的輸入分別直接接到 YP、YN 上,可消除由于驅動開關的導通電阻引入的坐標測量誤差。
缺點是:無論是采樣還是轉換過程中,驅動開關都需要接通,相對單端模式而言,功耗增加了。
XPT2046模擬輸入簡圖
差分模式輸入配置
表中說明了A2、A1、A0 和SER/DFR 控制位與XPT2046 的配置關系。這些控制位來自DIN腳的串行數據。
XPT2046是用來采集觸摸屏觸摸點的水平位置與垂直位置的。由表可知,測量Y位置時,需將A2A1A0設置為001,此時驅動的模擬輸入為YP和YN:測量X位置時,需將A2A1A0設置為101,此時驅動的模擬輸入為XP和XN。其他兩行用于測量觸模時作用于屏幕上的壓力,這里忽略。
控制字的控制位命令
控制字節各位描述
如果采用單端模式測量 X 坐標、Y 坐標和觸摸壓力,則需要添加一個外部參考電壓,并且 XPT2046 的電源也必須來自這個外部參考源。需要特別注意的一點是,當使用單端模式時,輸入 ADC 的電壓不能超過內部參考電壓,尤其是當工作電壓大于 2.7V 的時候。
注意 :差分模式僅用于 X 坐標、Y 坐標和觸摸壓力的測量,其它測量要求采用單端模式。
XPT2046的數據接口是串行的,通過該接口可輕易地與單片機或處理器完成互連,處理器和轉換器之間的通信需要8個時鐘周期,通過這8個時鐘周期來確定XPT72046轉換的模擬通道及采用的轉換模式。一次完整的轉換需要24個串行同步時鐘來完成。
前8個時鐘用來通過DIN引腳輸入控制命令(字節),當轉換器獲取有關下一次轉換的足夠信息后,接著根據獲得的信息設置輸入多路選擇器和參考源輸入,并進入采樣模式,如果需要,將啟動觸摸面板驅動器,3個多時鐘周期后,控制字節設置完成,轉換器進入轉換狀態。這時,輸入采樣保持器進入保持狀態,觸摸面板驅動器停止工作(單端工作模式)。接著的12個時鐘周期將完成真正的模數轉換。在差分模式時,驅動器在轉換過程中將一直工作,第13個時鐘將輸出轉換結果的最后一位。剩下的3個多時鐘周期將用來完成被轉換器忽略的最后字節(DOUT輸出0)。XPI2046 24周期的轉換時序如圖所示:
由圖可知。控制字節由DIN送入XPT2046,其包括啟動轉換位、尋址位,ADC分辨率設置位,單端/差分設置位和掉電控制位,起始位是拉制字的首位,取值恒為1,在DIN引腳檢測到起始位前,所有的輸入都將被忽略。尋址位即A2A1A0,由表可知,當A2A1A0為001時,XPT2046采集Y位置,當A2A1A0為101時,XPT2046采集X位置。MODE位為模式選擇位,其用于設置ADC分辨率,當MODE為0時,下一次轉換將是12位模式:當MODE為1時,下一次轉換將是8位模式。SER/DFR位用于選擇參考源的模式,當 SER/DFR為1時,選擇單端模式;當 SER/DFR為0時,選擇差分模式,為提高AD轉換的精度并消除測量誤差,這里選擇12位轉換模式和差分模式。最后兩位用于掉電控制,這里將之配置為00,即在兩次AD轉換之間掉電,下次轉換一開始,芯片立即進入完全上電狀態,而無需額外延時,另外,此時 PENIRQ是一直使能的。
分析可得轉換X通道時所對應的控制字為0xD0,轉換Y通道時所對應的控制字為0x90。為方便使用,將這兩個控制字定義為宏:
#define X_CMD 0XD0
#define Y_CMD 0X90
接著開始編寫觸摸屏程序,原理圖如下:
引腳分別是T_MOSI:PF11、T_MISO:PB2 、T_CS:PC13、T_CLK:PB0、T_PEN:PB1。
為方便調用對引腳進行的控制進行宏定義,。
#define T_CS_H() do{GPIOC- >BSRRL = 1< 13;}while(0)
#define T_CS_L() do{GPIOC- >BSRRH = 1< 13;}while(0)
#define T_CLK_H() do{GPIOB- >BSRRL = 1< 0;}while(0)
#define T_CLK_L() do{GPIOB- >BSRRH = 1< 0;}while(0)
#define T_MOSI_H() do{GPIOF- >BSRRL = 1< 11;}while(0)
#define T_MOSI_L() do{GPIOF- >BSRRH = 1< 11;}while(0)
初始化引腳:
void Touch_gpio_Init()
{
//1.開時鐘
RCC- >AHB1ENR |= 1< 1 | 1< 2 | 1< 5;
//2. 模式、類型、速度、上下拉
//PB1/2:輸入
GPIOB- >MODER &= ~(0XF< 2);
GPIOB- >PUPDR &= ~(0XF< 2);
GPIOB- >PUPDR |= (0x1< 2);
//PB0:
GPIOB- >MODER &= ~(0X3< 0);
GPIOB- >MODER |= 1< 0;
GPIOB- >OTYPER &= ~(1< 0); //推挽
GPIOB- >OSPEEDR &= ~(0X3< 0);//2mHZ
GPIOB- >PUPDR &= ~(0X3< 0); //無上下拉
//PC13
GPIOC- >MODER &= ~(0X3< 26);
GPIOC- >MODER |= 1< 26;
GPIOC- >OTYPER &= ~(1< 13); //推挽
GPIOC- >OSPEEDR &= ~(0X3< 26);//2mHZ
GPIOC- >PUPDR &= ~(0X3< 26); //無上下拉
//PF11
GPIOF- >MODER &= ~(0X3< 22);
GPIOF- >MODER |= 1< 22;
GPIOF- >OTYPER &= ~(1< 11); //推挽
GPIOF- >OSPEEDR &= ~(0X3< 22);//2mHZ
GPIOF- >PUPDR &= ~(0X3< 22); //無上下拉
//3. 初始狀態
T_CS_H(); //片選信號低電平有效,初始時不片選
T_CLK_L();
}
初始化完成,根據時序編寫對X或Y通道完成一次轉換的函數實現
u16 Touch_GetADC(u8 cmd)
{
u8 i = 0;
u16 res = 0;
T_CLK_L();
T_CS_L();
Delay_us(1);
for(i=0;i< 8;i++)
{
if(cmd & 0x80)
T_MOSI_H(); //數據有效輸出高電平
else
T_MOSI_L(); //數據有效輸出低電平
Delay_us(1);
T_CLK_H();
Delay_us(1);
T_CLK_L();
Delay_us(1);
cmd < <= 1;
}
T_CLK_H(); //ADC需要一個周期
Delay_us(1);
res = 0;
for(i=0;i< 15;i++)
{
res < <= 1; //空出最低位,準備接收
T_CLK_L();
Delay_us(1);
T_CLK_H();
Delay_us(1);
if(GPIOB- >IDR & (1< 2))
res |= 1;
Delay_us(1);
}
T_CLK_L();
Delay_us(1);
T_CS_H();
res > >= 3; //最低3位是補充的0,移掉不要
return res;
}
有了上面的函數,只需依次送入X通道的控制字節和Y通道的控制字節,即可在一次接觸后,獲取接觸點x、y方向的AD值。但針對AD轉換,為了提高轉換的準確性,這里采用中值平均濾波算法進行濾波。中值平均算法即將獲取的AD值通過冒泡法排序,然后掐頭去尾,取平均值并返回。具體如下:
u16 Touch_GetAvgADC(u8 cmd, u16 * buf,u8 size)
{
u8 i = 0,j=0;
u16 temp = 0;
float res = 0;
for(i=0;i< size;i++)
buf[i] = Touch_GetADC(cmd);
for(i=0;i< size-1;i++)
{
for(j=i+1;j< size;j++)
{
if(buf[i]
接著,就可以用這個函數得到一個點的坐標。先把點的坐標定義為結構體:
typedef struct
{
u16 x;
u16 y;
}Point_Typedef;
通過筆中斷引腳判斷是否有觸摸動作,然后分別讀出X和Y的ADC值并返回出一個點的坐標ADC。
Point_Typedef Touch_GetPointADC()
{
Point_Typedef ts = {0xffff,0xffff};
if((GPIOB- >IDR & (1< 1))==0) //有觸摸動作
{
ts.x = Touch_GetAvgADC(X_CMD, Point_buf[0],10);
ts.y = Touch_GetAvgADC(Y_CMD, Point_buf[1],10);
}
return ts;
}
現在已經可以獲得點的坐標ADC,開始進行測試程序是否正確。
主函數
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "stdio.h"
#include "touch.h"
int main()
{
Point_Typedef ts = {0xffff,0xffff};
Usart1_Init(115200);
Touch_gpio_Init();
while(1)
{
ts = Touch_GetPointADC();
printf("(%d,%d)rn",ts.x,ts.y);
Delay_ms(2000);
}
}
運行程序,發現沒有觸摸時點的坐標是獲取不到的,有觸摸動作時,點的ADC坐標就是在12位ADC的范圍內,獲取點的坐標ADC測試成功。
評論
查看更多