一、基本介紹
XPT2046是一種四線SPI介面、集成了複位電路和充電電路的電容式觸摸屏晶元,廣泛應用於各種移動智能終端、嵌入式系統和工業控制設備中。
XPT2046可以支持多種觸摸模式,包括電容式單點觸摸、電容式多點觸摸和壓力觸摸,支持多種傳輸模式和數據格式。
作為一個外圍設備,XPT2046並不會通過SPI主機發送請求,而是在XPT2046內部集成了一個循環掃描控制器,自主進行掃描以獲得觸摸數據,並將觸摸數據通過SPI介面發送到主機。
二、連接電路
XPT2046可以使用4條SPI線來與主控晶元通訊,包括SCK、MISO、MOSI和CS(Chip Select)。其中,SCK是時鐘線,MISO是主機的數據輸入線,MOSI是主機的數據輸出線,CS是片選線用於選中XPT2046晶元。
除了四根SPI線,XPT2046還需要一個複位電路和一個充電電路。複位電路可以使用一個複位IC或一個RC電路實現,充電電路可以使用一個限流二極體和一個電容器實現。
// 假設連接方式如下: // CS - GPIO33 // SCK - GPIO32 // MISO - GPIO35 // MOSI - GPIO34 // INT - GPIO26 // RST - GPIO27 #include #define CS_PIN 33 #define SCK_PIN 32 #define MISO_PIN 35 #define MOSI_PIN 34 #define INT_PIN 26 #define RST_PIN 27 void setup() { pinMode(CS_PIN, OUTPUT); // 設置CS為輸出模式 digitalWrite(CS_PIN, HIGH); // 默認禁止片選 SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN); // 初始化SPI SPI.setFrequency(4000000); // 設置SPI時鐘頻率為4MHz pinMode(INT_PIN, INPUT_PULLUP); // 設置INT為上拉輸入,便於檢測觸摸事件 pinMode(RST_PIN, OUTPUT); // 設置RST為輸出模式 digitalWrite(RST_PIN, HIGH); // 默認複位禁止 } void loop() { // 待實現的代碼 }
三、讀取觸摸數據
XPT2046晶元內部集成了一個寄存器數組,用於記錄當前觸摸狀態、掃描計數、觸摸坐標等信息。在讀取觸摸數據之前,需要向XPT2046晶元發送一個0x80指令,表示讀取一個事件。XPT2046會自主掃描觸摸屏,並將觸摸數據通過SPI介面發送到主機。
在讀取觸摸數據時,需要注意到XPT2046可能會傳輸多個命令,因此需要不斷地接收數據並解析,直到讀取到一個有效的觸摸事件。一旦讀取到有效的觸摸事件,就可以從XPT2046晶元內部的寄存器數組中讀取觸摸坐標。
#define CMD_READ 0x80 // 讀取一個事件 #define CMD_X 0x90 // 讀取X坐標值 #define CMD_Y 0xd0 // 讀取Y坐標值 int readTouchX() { int xRaw = 0; digitalWrite(CS_PIN, LOW); SPI.transfer(CMD_X); xRaw = SPI.transfer16(0) >> 3; digitalWrite(CS_PIN, HIGH); return xRaw; } int readTouchY() { int yRaw = 0; digitalWrite(CS_PIN, LOW); SPI.transfer(CMD_Y); yRaw = SPI.transfer16(0) >>3; digitalWrite(CS_PIN, HIGH); return yRaw; } bool readTouchPoint(int &x, int &y) { if (digitalRead(INT_PIN) == LOW) { // 檢測觸摸事件 digitalWrite(RST_PIN, LOW); // 啟用複位 digitalWrite(CS_PIN, LOW); // 允許片選 SPI.transfer(CMD_READ); // 發送讀取事件指令 x = readTouchX(); // 讀取X坐標 y = readTouchY(); // 讀取Y坐標 digitalWrite(CS_PIN, HIGH); // 禁止片選 digitalWrite(RST_PIN, HIGH); // 禁用複位 return true; } else { return false; } }
四、觸摸坐標轉換
由於觸摸屏的尺寸和解析度各異,因此需要將XPT2046晶元讀取出來的原始觸摸坐標轉換為實際屏幕坐標。觸摸坐標轉換可以通過一組公式實現。
其中,觸摸坐標Xc和Yc是從XPT2046晶元內部寄存器中讀取到的原始坐標,觸摸屏尺寸為W和H,觸摸坐標X和Y是實際屏幕坐標:
X = ((Xc * a + Yc * b + c) / d) * W
Y = ((Xc * e + Yc * f + g) / h) * H
其中,a、b、c、d、e、f、g和h均是校準係數,根據實際觸摸屏進行調整。校準係數可以通過在不同位置嘗試觸摸,記錄下相應的觸摸坐標和實際屏幕坐標,然後通過線性方程組求解得到。
#define TOUCH_WIDTH 240 #define TOUCH_HEIGHT 320 float calA = 0.012367262544294; float calB = -0.001709139042816; float calC = -19.316064986921131; float calD = 1.838251825135559; float calE = -0.000992525359333; float calF = 0.195498693029731; float calG = -46.090023031789299; float calH = 2.038698937062327; bool readTouchPoint(int &x, int &y) { if (digitalRead(INT_PIN) == LOW) { // 檢測觸摸事件 digitalWrite(RST_PIN, LOW); // 啟用複位 digitalWrite(CS_PIN, LOW); // 允許片選 SPI.transfer(CMD_READ); // 發送讀取事件指令 int xRaw = readTouchX(); // 讀取X坐標 int yRaw = readTouchY(); // 讀取Y坐標 digitalWrite(CS_PIN, HIGH); // 禁止片選 digitalWrite(RST_PIN, HIGH); // 禁用複位 x = ((xRaw * calA + yRaw * calB + calC) / calD) * TOUCH_WIDTH; y = ((xRaw * calE + yRaw * calF + calG) / calH) * TOUCH_HEIGHT; return true; } else { return false; } }
五、觸摸應用示例
XPT2046可以廣泛應用於各種移動智能終端、嵌入式系統和工業控制設備中。下面是一個簡單的觸摸應用示例,通過讀取觸摸數據,控制LED的亮滅。
在這個示例中,將在屏幕上劃分出四個區域,分別對應四個LED。當用戶觸摸到各個區域時,相應的LED會亮起或熄滅。
int LED_1 = 12; int LED_2 = 13; int LED_3 = 14; int LED_4 = 15; void setup() { // 初始化IO pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); pinMode(LED_3, OUTPUT); pinMode(LED_4, OUTPUT); } void loop() { int x, y; if (readTouchPoint(x, y)) { if (x < 120 && y = 120 && y < 160) { digitalWrite(LED_2, HIGH); } else { digitalWrite(LED_2, LOW); } if (x = 160) { digitalWrite(LED_3, HIGH); } else { digitalWrite(LED_3, LOW); } if (x >= 120 && y >= 160) { digitalWrite(LED_4, HIGH); } else { digitalWrite(LED_4, LOW); } } }
六、總結
XPT2046是一款成熟的電容式觸摸晶元,具有靈敏度高、讀取精度高等優點,可以廣泛應用於各種移動智能終端、嵌入式系統和工業控制設備中。使用XPT2046需要注意到連接電路、讀取觸摸數據、觸摸坐標轉換等問題,並可以使用校準係數來調整觸摸坐標的精度。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/236767.html