这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » XPT2046触控芯片驱动

共2条 1/1 1 跳转至

XPT2046触控芯片驱动

助工
2025-04-18 16:05:47     打赏

1、简介

XPT2046是一款四线制电阻触摸屏控制芯片,由深圳市矽普特科技有限公司研发生产,内含12位分辨率125KHz转换速率逐步逼近型A/D转换器。XPT2046 支持从1.5V到5.25V的低电压I/O接口。XPT2046能通过执行两次A/D转换查出被按的屏幕位置, 除此之外,还可以测量加在触摸屏上的压力。内部自带2.5V参考电压,可以作为辅助输入、温度测量和电池监测之用, 在2.7V的典型工作状态下,关闭参考电压,功耗可小于0.75mW。其内部框图如下:

image.png

左边红框为触控点输入,右边红框为外部SPI通信接口,至少与外部MCU连接CS、CLK、DIN、DOUT这四个通信引脚,使用IRQ中断则MCU需要再提供一个输入引脚。

2、xpt2046触控屏驱动

这里直接使用厂商提供的xpt2046,只需要完成xpt2046触控屏的接线和通信API设置就可以实现触控输入检测。主控MCU为STM32F429,使用CubeMX工具配置SPI硬件外设。SPI4外设通信方式为主机全双工,从机为xpt2046,NSS使用软件片选CS

image.png

中断IRQ引脚设为外部下降沿中断、默认上拉

image.png

3、程序设计

XPT2046_touch.h

/*
 * XPT2046_touch.h
 */

#ifndef XPT2046_TOUCH_H
#define XPT2046_TOUCH_H

#include "main.h"
#include <stdbool.h>

/*** Redefine if necessary ***/
//#define	SOFTWARE_SPI
#define XPT2046_SPI_PORT hspi4 
extern SPI_HandleTypeDef XPT2046_TOUCH_SPI_PORT;

#define XPT2046_IRQ_Pin T_IRQ_Pin 
#define XPT2046_IRQ_GPIO_Port T_IRQ_GPIO_Port 
#define XPT2046_CS_Pin T_CS_Pin 
#define XPT2046_CS_GPIO_Port T_CS_GPIO_Port

#ifdef SOFTWARE_SPI

#define XPT2046_MISO_Pin       	T_MISO_Pin
#define XPT2046_MISO_GPIO_Port 	T_MISO_GPIO_Port
#define XPT2046_MOSI_Pin        T_MOSI_Pin
#define XPT2046_MOSI_GPIO_Port  T_MOSI_GPIO_Port
#define XPT2046_CLK_Pin       	T_CLK_Pin
#define XPT2046_CLK_GPIO_Port 	T_CLK_GPIO_Port

#else

// Warning! Use SPI bus with < 2.5 Mbit speed, better ~650 Kbit to be save.
#define XPT2046_SPI_PORT hspi4
extern SPI_HandleTypeDef XPT2046_SPI_PORT;

#endif /* SOFTWARE_SPI */

//////#define XPT2046_IRQ_Pin       	T_PEN_Pin
//////#define XPT2046_IRQ_GPIO_Port 	T_PEN_GPIO_Port
//////#define XPT2046_CS_Pin        	T_CS_Pin
//////#define XPT2046_CS_GPIO_Port  	T_CS_GPIO_Port

#define TOUCH_ORIENTATION_PORTRAIT 			(0U)
#define TOUCH_ORIENTATION_LANDSCAPE 		(1U)
#define TOUCH_ORIENTATION_PORTRAIT_MIRROR 	(2U)
#define TOUCH_ORIENTATION_LANDSCAPE_MIRROR 	(3U)

#define ORIENTATION	(TOUCH_ORIENTATION_PORTRAIT_MIRROR)

// change depending on screen orientation
#if (ORIENTATION == 0)
#define XPT2046_SCALE_X 240
#define XPT2046_SCALE_Y 320
#elif (ORIENTATION == 1)
#define XPT2046_SCALE_X 320
#define XPT2046_SCALE_Y 240
#elif (ORIENTATION == 2)
#define XPT2046_SCALE_X 240
#define XPT2046_SCALE_Y 320
#elif (ORIENTATION == 3)
#define XPT2046_SCALE_X 320
#define XPT2046_SCALE_Y 240
#endif

// to calibrate uncomment UART_Printf line in ili9341_touch.c
#define XPT2046_MIN_RAW_X 3400
#define XPT2046_MAX_RAW_X 29000
#define XPT2046_MIN_RAW_Y 3300
#define XPT2046_MAX_RAW_Y 30000

#ifdef __cplusplus
 extern "C" {
#endif

// call before initializing any SPI devices
extern bool XPT2046_TouchPressed(void);
extern bool XPT2046_TouchGetCoordinates(uint16_t* x, uint16_t* y);

#ifdef __cplusplus
}
#endif

#endif /* XPT2046_TOUCH_H_ */

XPT2046_touch.c

/*
 * XPT2046_touch.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <XPT2046_touch.h>

#if (ORIENTATION == 0)
#define READ_X 0xD0
#define READ_Y 0x90
#elif (ORIENTATION == 1)
#define READ_Y 0xD0
#define READ_X 0x90
#elif (ORIENTATION == 2)
#define READ_X 0xD0
#define READ_Y 0x90
#elif (ORIENTATION == 3)
#define READ_Y 0xD0
#define READ_X 0x90
#endif

#ifdef SOFTWARE_SPI

#define SPI_CLK_L()		HAL_GPIO_WritePin(XPT2046_CLK_GPIO_Port, XPT2046_CLK_Pin, GPIO_PIN_RESET)
#define SPI_CLK_H()		HAL_GPIO_WritePin(XPT2046_CLK_GPIO_Port, XPT2046_CLK_Pin, GPIO_PIN_SET)
#define SPI_MOSI_L()	HAL_GPIO_WritePin(XPT2046_MOSI_GPIO_Port, XPT2046_MOSI_Pin, GPIO_PIN_RESET)
#define SPI_MOSI_H()	HAL_GPIO_WritePin(XPT2046_MOSI_GPIO_Port, XPT2046_MOSI_Pin, GPIO_PIN_SET)
#define SPI_MISO()		HAL_GPIO_ReadPin(XPT2046_MISO_GPIO_Port, XPT2046_MISO_Pin)

static void spi_write_byte(uint8_t data)
{
	for(size_t i = 0; i < 8; i++)
	{
		if (data & 0x80)
		{
			SPI_MOSI_H();
		}
		else
		{
			SPI_MOSI_L();
		}
		data = data << 1;
		SPI_CLK_L();
		SPI_CLK_H();
	}
}

static uint8_t spi_read_byte(void)
{
	uint8_t i, ret , value;
	ret = 0;
	i = 8;

	do {
		i--;
		SPI_CLK_L();
		value = SPI_MISO();
		if (value)
		{
			//set the bit to 0 no matter what
			ret |= (1 << i);
		}

		SPI_CLK_H();
	} while (i > 0);

	return ret;
}

#endif /* SOFTWARE_SPI */

static void XPT2046_TouchSelect()
{
    HAL_GPIO_WritePin(XPT2046_CS_GPIO_Port, XPT2046_CS_Pin, GPIO_PIN_RESET);
}

static void XPT2046_TouchUnselect()
{
    HAL_GPIO_WritePin(XPT2046_CS_GPIO_Port, XPT2046_CS_Pin, GPIO_PIN_SET);
}

bool XPT2046_TouchPressed(void)
{
    return HAL_GPIO_ReadPin(XPT2046_IRQ_GPIO_Port, XPT2046_IRQ_Pin) == GPIO_PIN_RESET;
}

bool XPT2046_TouchGetCoordinates(uint16_t* x, uint16_t* y)
{
#ifndef SOFTWARE_SPI

	static const uint8_t cmd_read_x[] = { READ_X };
    static const uint8_t cmd_read_y[] = { READ_Y };
    static const uint8_t zeroes_tx[] = { 0x00, 0x00 };

#endif /* SOFTWARE_SPI */

    XPT2046_TouchSelect();

    uint32_t avg_x = 0;
    uint32_t avg_y = 0;
    uint8_t nsamples = 0;

    for(uint8_t i = 0; i < 16; i++)
    {
        if(!XPT2046_TouchPressed())
            break;

        nsamples++;

        uint8_t y_raw[2];
        uint8_t x_raw[2];

#ifdef SOFTWARE_SPI

       spi_write_byte(READ_Y);

	   y_raw[0] = spi_read_byte();
	   y_raw[1] = spi_read_byte();

	   spi_write_byte(READ_X);

	   x_raw[0] = spi_read_byte();
	   x_raw[1] = spi_read_byte();

#else

        HAL_SPI_Transmit(&XPT2046_SPI_PORT, (uint8_t*)cmd_read_y, sizeof(cmd_read_y), HAL_MAX_DELAY);
        HAL_SPI_TransmitReceive(&XPT2046_SPI_PORT, (uint8_t*)zeroes_tx, y_raw, sizeof(y_raw), HAL_MAX_DELAY);

        HAL_SPI_Transmit(&XPT2046_SPI_PORT, (uint8_t*)cmd_read_x, sizeof(cmd_read_x), HAL_MAX_DELAY);
        HAL_SPI_TransmitReceive(&XPT2046_SPI_PORT, (uint8_t*)zeroes_tx, x_raw, sizeof(x_raw), HAL_MAX_DELAY);

#endif /* SOFTWARE_SPI */

        avg_x += (((uint16_t)x_raw[0]) << 8) | ((uint16_t)x_raw[1]);
        avg_y += (((uint16_t)y_raw[0]) << 8) | ((uint16_t)y_raw[1]);
    }

    XPT2046_TouchUnselect();

    if(nsamples < 16)
        return false;

    uint32_t raw_x = (avg_x / 16);
    if(raw_x < XPT2046_MIN_RAW_X) raw_x = XPT2046_MIN_RAW_X;
    if(raw_x > XPT2046_MAX_RAW_X) raw_x = XPT2046_MAX_RAW_X;

    uint32_t raw_y = (avg_y / 16);
    if(raw_y < XPT2046_MIN_RAW_Y) raw_y = XPT2046_MIN_RAW_Y;
    if(raw_y > XPT2046_MAX_RAW_Y) raw_y = XPT2046_MAX_RAW_Y;

    // Uncomment this line to calibrate touchscreen:
//    printf("raw_x = %6d, raw_y = %6d\r\n", (int) raw_x, (int) raw_y);
//    printf("\x1b[1F");

#if (ORIENTATION == 0)
	*x = (raw_x - XPT2046_MIN_RAW_X) * XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
	*y = (raw_y - XPT2046_MIN_RAW_Y) * XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 1)
	*x = (raw_x - XPT2046_MIN_RAW_X) * XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
	*y = (raw_y - XPT2046_MIN_RAW_Y) * XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 2)
    *x = (raw_x - XPT2046_MIN_RAW_X) * XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
    *y = XPT2046_SCALE_Y - (raw_y - XPT2046_MIN_RAW_Y) * XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 3)
    *x = XPT2046_SCALE_X - (raw_x - XPT2046_MIN_RAW_X) * XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
    *y = (raw_y - XPT2046_MIN_RAW_Y) * XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#endif

    return true;
}

Mian.c文件添加IRQ中断回调函数

void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
 if (GPIO_Pin == T_IRQ_Pin)
 {
  if(XPT2046_TouchPressed())
  {
   uint16_t x = 0, y = 0;
   if(XPT2046_TouchGetCoordinates(&x, &y))
   {
    //lcdFillCircle((lcdGetWidth() - x), y, 2, COLOR_GREENYELLOW);
 printf("XPT2046 x=%d,y=%d\n",x,y);
   }
  }
 
 }
}

在Xpt.h 头文件中,触控方向设置

#define
TOUCH_ORIENTATION_PORTRAIT
                        (0U)
#define
TOUCH_ORIENTATION_LANDSCAPE
                (1U)
#define
TOUCH_ORIENTATION_PORTRAIT_MIRROR
        (2U)
#define
TOUCH_ORIENTATION_LANDSCAPE_MIRROR
        (3U)
 
#define
ORIENTATION        (TOUCH_ORIENTATION_PORTRAIT_MIRROR)

将TOUCH_ORIENTATION_PORTRAIT_MIRROR为1时,触控原点在屏幕正向左上角

TOUCH_ORIENTATION_PORTRAIT_MIRROR3时,触控原点在右上角

4、运行效果

模块接线与MCU接线

CS-PB6,PENIRQ-PD11,DCLK-PE2,DIN-MOSI,DOUT-MISO

fe39a5d5c301d685332e46fa44d180ef.jpg

22.gif






关键词: XPT2046    

专家
2025-04-18 20:53:08     打赏
2楼

支持从1.5V到5.25V的低电压I/O接口,这个好,不用考虑电平匹配的问题。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]