STM32F1与STM32CubeIDE编程实例-XPT2046电阻触摸屏驱动

XPT2046电阻触摸屏驱动

1、XPT2046介绍

XPT2046 是一款 4 线电阻式触摸屏控制器,包含一个 12 位 125 kHz 采样 SAR 型 A/D 转换器。XPT2046支持1.5V到5.25V的低电压I/O接口。XPT2046通过两次A/D转换就可以确认被按的屏幕位置。其功能框图如下:

在这里插入图片描述

XPT2046支持SPI和QSPI通信,支持8位或12位采集样。XPT2046与MCU的典型连接电路如下:

在这里插入图片描述

2、XPT2046配置

开发环境搭建、系统时钟配置、调试配置及串口配置,请参考:

本次配置如下:

SPI配置如下:

在这里插入图片描述

XPT2046的CS引脚及IRQ引脚配置如下:

在这里插入图片描述

3、XPT2046驱动实现

1)XPT2046驱动基本定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/\*
\* xpt2046\_touch.h
\*
\* Created on: Jul 4, 2022
\* Author: jenson
\*/

#ifndef XPT2046\_XPT2046\_TOUCH\_H\_
#define XPT2046\_XPT2046\_TOUCH\_H\_

#include "main.h"
#include <stdbool.h>
#include <stm32f1xx\_hal.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)

// 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

// 需要根据触摸板的硬件参数确定
#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


typedef struct {
uint8\_t id;
SPI_HandleTypeDef\* spi;
GPIO_TypeDef\* cs_port;
uint16\_t cs_pin;
GPIO_TypeDef\* irq_port;
uint16\_t irq_pin;
uint16\_t raw_x; // 原始X坐标
uint16\_t raw_y; // 原始Y坐标
uint16\_t x; // 转换后X坐标
uint16\_t y; // 转换后Y坐标
}xpt2046\_t;

void xpt2046\_init(xpt2046\_t\* xpt2046);
bool xpt2046\_pressed(xpt2046\_t\* xpt2046);
bool xpt2046\_read\_xy(xpt2046\_t\* xpt2046);

#ifdef \_\_cplusplus
}

#endif /\* XPT2046\_XPT2046\_TOUCH\_H\_ \*/

#endif


请注意:XPT2046触摸板的最小输出和最大输出不同触摸板可能不同,请参考触摸板的硬件参数。

2)XPT2046驱动定义实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/\*
\* XPT2046\_touch.c
\*
\* Created on: Jul 4, 2022
\* Author: jenson
\*/

#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


void \_\_xpt2046\_spi\_select(xpt2046\_t \*xpt2046) {
HAL\_GPIO\_WritePin(xpt2046->cs_port, xpt2046->cs_pin, GPIO_PIN_RESET);
}

void \_\_xpt2046\_spi\_deselect(xpt2046\_t \*xpt2046) {
HAL\_GPIO\_WritePin(xpt2046->cs_port, xpt2046->cs_pin, GPIO_PIN_SET);
}

void xpt2046\_init(xpt2046\_t \*xpt2046) {

}

bool xpt2046\_pressed(xpt2046\_t \*xpt2046) {
return HAL\_GPIO\_ReadPin(xpt2046->irq_port, xpt2046->irq_pin)
== GPIO_PIN_RESET;
}

bool xpt2046\_read\_xy(xpt2046\_t \*xpt2046) {
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 };

\_\_xpt2046\_spi\_select(xpt2046);

uint32\_t avg_x = 0;
uint32\_t avg_y = 0;
uint8\_t nsamples = 0;

// 采样16次
for (uint8\_t i = 0; i < 16; i++) {
if (!xpt2046\_pressed(xpt2046))
break;

nsamples++;

uint8\_t y_raw[2];
uint8\_t x_raw[2];

HAL\_SPI\_Transmit(xpt2046->spi, (uint8\_t\*) cmd_read_y,
sizeof(cmd_read_y), HAL_MAX_DELAY);
HAL\_SPI\_TransmitReceive(xpt2046->spi, (uint8\_t\*) zeroes_tx, y_raw,
sizeof(y_raw), HAL_MAX_DELAY);

HAL\_SPI\_Transmit(xpt2046->spi, (uint8\_t\*) cmd_read_x,
sizeof(cmd_read_x), HAL_MAX_DELAY);
HAL\_SPI\_TransmitReceive(xpt2046->spi, (uint8\_t\*) zeroes_tx, x_raw,
sizeof(x_raw), HAL_MAX_DELAY);

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\_spi\_deselect(xpt2046);

if (nsamples < 16)
return false;

uint32\_t raw_x = (avg_x / 16);
uint32\_t raw_y = (avg_y / 16);
// printf("raw\_x = %6d, raw\_y = %6d\r\n", (int) raw\_x, (int) raw\_y);

xpt2046->raw_x = raw_x;
xpt2046->raw_y = raw_y;

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;

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;
// 转换坐标
#if (ORIENTATION == 0)
xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X
/ (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y
/ (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 1)
xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 2)
xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
xpt2046->y = XPT2046_SCALE_Y - (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#elif (ORIENTATION == 3)
xpt2046->x = XPT2046_SCALE_X - (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X);
xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y);
#endif

return true;
}


3、驱动测试

main.c文件中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include "xpt2046/xpt2046\_touch.h"
#include <stdio.h>
/\* USER CODE END Includes \*/

/\* USER CODE BEGIN PV \*/
xpt2046\_t xpt2046;
/\* USER CODE END PV \*/

int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_USART1\_UART\_Init();
MX\_SPI1\_Init();
/\* USER CODE BEGIN 2 \*/

xpt2046.spi = &hspi1;
xpt2046.cs_port = T_CS_GPIO_Port;
xpt2046.cs_pin = T_CS_Pin;
xpt2046.irq_port = T_PEN_GPIO_Port;
xpt2046.irq_pin = T_PEN_Pin;

xpt2046\_init(&xpt2046);

/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/
if (xpt2046\_pressed(&xpt2046)) {
if (xpt2046\_read\_xy(&xpt2046)) {
printf("x = %d,y = %d\r\n", xpt2046.x, xpt2046.y);
}
}
HAL\_Delay(30);
}
/\* USER CODE END 3 \*/
}


参考

文章来源: https://iotsmart.blog.csdn.net/article/details/125698903