您的位置:

XPT2046触摸芯片详解

一、基本介绍

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 < 160) {
      digitalWrite(LED_1, HIGH);
    } else {
      digitalWrite(LED_1, LOW);
    }
    if (x >= 120 && y < 160) {
      digitalWrite(LED_2, HIGH);
    } else {
      digitalWrite(LED_2, LOW);
    }
    if (x < 120 && y >= 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需要注意到连接电路、读取触摸数据、触摸坐标转换等问题,并可以使用校准系数来调整触摸坐标的精度。